github.com/mad-day/Yawning-crypto@v0.0.0-20190711051033-5a5f8cca32ec/bcns/rlwe.go (about) 1 // 2 // Ring Learning with Errors 3 // 4 // To the extent possible under law, Yawning Angel waived all copyright 5 // and related or neighboring rights to bcns, using the Creative 6 // Commons "CC0" public domain dedication. See LICENSE or 7 // <http://creativecommons.org/publicdomain/zero/1.0/> for full details. 8 9 package bcns 10 11 // Yawning: Only the constant time variation of the code is implemented. 12 // If people want the non-constant time version, they can do it themselves. 13 14 func getbit(a []uint64, x int) uint64 { 15 return (a[(x)/64] >> uint64((x)%64)) & 1 16 } 17 18 // We assume that e contains two random bits in the two 19 // least significant positions. 20 func dbl(in uint32, e int32) uint64 { 21 // sample uniformly from [-1, 0, 0, 1] 22 // Hence, 0 is sampled with twice the probability of 1 23 e = (((e >> 1) & 1) - (int32(e & 1))) 24 return uint64((uint64(in) << uint64(1)) - uint64(e)) 25 } 26 27 func singleSample(in *[3]uint64) uint32 { 28 index := uint64(0) 29 for i := uint64(0); i < 52; i++ { 30 index = selectU64(index, i, lessThanU192(in, &rlweTable[i])) 31 } 32 return uint32(index) 33 } 34 35 func sample(s *[1024]uint32, rand *randCtx) { 36 for i := 0; i < 16; i++ { 37 r := rand.random64() 38 for j := 0; j < 64; j++ { 39 var rnd [3]uint64 40 var m, t uint32 41 rand.random192(&rnd) 42 m = uint32(r & 1) 43 r >>= 1 44 s[i*64+j] = singleSample(&rnd) 45 t = 0xFFFFFFFF - s[i*64+j] 46 s[i*64+j] = uint32(selectU64(uint64(t), uint64(s[i*64+j]), ctEqU64(uint64(m), 0))) 47 } 48 } 49 } 50 51 func round2(out *[16]uint64, in *[1024]uint32) { 52 for i := range out { 53 out[i] = 0 54 } 55 for i := 0; i < 1024; i++ { 56 inI := uint64(in[i]) 57 b := ctGeU64(inI, 1073741824) & ctLeU64(inI, 3221225471) 58 out[i/64] |= b << uint64(i%64) 59 } 60 } 61 62 func crossround2(out *[16]uint64, in *[1024]uint32, rand *randCtx) { 63 for i := range out { 64 out[i] = 0 65 } 66 for i := 0; i < 64; i++ { 67 e := rand.random32() 68 for j := 0; j < 16; j++ { 69 dd := dbl(in[i*16+j], int32(e)) 70 e >>= 2 71 b := (ctGeU64(dd, 2147483648) & ctLeU64(dd, 4294967295)) | 72 (ctGeU64(dd, 6442450942) & ctLeU64(dd, 8589934590)) 73 out[(i*16+j)/64] |= (b << uint64((i*16+j)%64)) 74 } 75 } 76 } 77 78 func rec(out *[16]uint64, w *[1024]uint32, b *[16]uint64) { 79 for i := range out { 80 out[i] = 0 81 } 82 for i := 0; i < 1024; i++ { 83 coswi := (uint64(w[i])) << 1 84 B := (ctEqU64(getbit(b[:], i), 0) & ctGeU64(coswi, 3221225472) & ctLeU64(coswi, 7516192766)) | 85 (ctEqU64(getbit(b[:], i), 1) & ctGeU64(coswi, 1073741824) & ctLeU64(coswi, 5368709118)) 86 out[i/64] |= (B << uint64(i%64)) 87 } 88 } 89 90 func keyGen(out, a, s, e *[1024]uint32, ctx *fftCtx) { 91 ctx.multiply(out, a, s) 92 ctx.add(out, out, e) 93 }