-
Notifications
You must be signed in to change notification settings - Fork 9
/
poly_simple.go
99 lines (84 loc) · 2.36 KB
/
poly_simple.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// poly_simple.go - NewHope-Simple polynomial.
//
// To the extent possible under law, Yawning Angel has waived all copyright
// and related or neighboring rights to newhope, using the Creative
// Commons "CC0" public domain dedication. See LICENSE or
// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
package newhope
func coeffFreeze(x uint16) uint16 {
var c int16
r := barrettReduce(x)
m := r - paramQ
c = int16(m)
c >>= 15
r = m ^ ((r ^ m) & uint16(c))
return r
}
// Computes abs(x-Q/2)
func flipAbs(x uint16) uint16 {
r := int16(coeffFreeze(x))
r = r - paramQ/2
m := r >> 15
return uint16((r + m) ^ m)
}
func (p *poly) compress(r []byte) {
var t [8]uint32
for i, k := 0, 0; i < paramN; i, k = i+8, k+3 {
for j := range t {
t[j] = uint32(coeffFreeze(p.coeffs[i+j]))
t[j] = (((t[j] << 3) + paramQ/2) / paramQ) & 0x7
}
r[k] = byte(t[0]) | byte(t[1]<<3) | byte(t[2]<<6)
r[k+1] = byte(t[2]>>2) | byte(t[3]<<1) | byte(t[4]<<4) | byte(t[5]<<7)
r[k+2] = byte(t[5]>>1) | byte(t[6]<<2) | byte(t[7]<<5)
}
for i := range t {
t[i] = 0
}
}
func (p *poly) decompress(a []byte) {
for i := 0; i < paramN; i += 8 {
a0, a1, a2 := uint16(a[0]), uint16(a[1]), uint16(a[2])
p.coeffs[i+0] = a0 & 7
p.coeffs[i+1] = (a0 >> 3) & 7
p.coeffs[i+2] = (a0 >> 6) | ((a1 << 2) & 4)
p.coeffs[i+3] = (a1 >> 1) & 7
p.coeffs[i+4] = (a1 >> 4) & 7
p.coeffs[i+5] = (a1 >> 7) | ((a2 << 1) & 6)
p.coeffs[i+6] = (a2 >> 2) & 7
p.coeffs[i+7] = (a2 >> 5)
a = a[3:]
for j := 0; j < 8; j++ {
p.coeffs[i+j] = uint16((uint32(p.coeffs[i+j])*paramQ + 4) >> 3)
}
}
}
func (p *poly) fromMsg(msg []byte) {
for i := uint(0); i < 32; i++ { // XXX: const for 32
for j := uint(0); j < 8; j++ {
mask := -(uint16((msg[i] >> j) & 1))
p.coeffs[8*i+j+0] = mask & (paramQ / 2)
p.coeffs[8*i+j+256] = mask & (paramQ / 2)
p.coeffs[8*i+j+512] = mask & (paramQ / 2)
p.coeffs[8*i+j+768] = mask & (paramQ / 2)
}
}
}
func (p *poly) toMsg(msg []byte) {
memwipe(msg[0:32])
for i := uint(0); i < 256; i++ {
t := flipAbs(p.coeffs[i+0])
t += flipAbs(p.coeffs[i+256])
t += flipAbs(p.coeffs[i+512])
t += flipAbs(p.coeffs[i+768])
//t = (~(t - PARAM_Q));
t = (t - paramQ)
t >>= 15
msg[i>>3] |= byte(t << (i & 7))
}
}
func (p *poly) sub(a, b *poly) {
for i := range p.coeffs {
p.coeffs[i] = barrettReduce(a.coeffs[i] + 3*paramQ - b.coeffs[i])
}
}