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  }