-
Notifications
You must be signed in to change notification settings - Fork 9
/
newhope_simple.go
166 lines (130 loc) · 4.17 KB
/
newhope_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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// newhope_simple.go - NewHope-Simple interface.
//
// 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
import (
"io"
"golang.org/x/crypto/sha3"
)
const (
// HighBytes is the length of the encoded secret in bytes.
HighBytes = 384
// SendASimpleSize is the length of Alice's NewHope-Simple public key in
// bytes.
SendASimpleSize = PolyBytes + SeedBytes
// SendBSimpleSize is the length of Bob's NewHope-Simple public key in
// bytes.
SendBSimpleSize = PolyBytes + HighBytes
)
func encodeBSimple(r []byte, b *poly, v *poly) {
b.toBytes(r)
v.compress(r[PolyBytes:])
}
func decodeBSimple(b *poly, v *poly, r []byte) {
b.fromBytes(r)
v.decompress(r[PolyBytes:])
}
// PublicKeySimpleAlice is Alice's NewHope-Simple public key.
type PublicKeySimpleAlice struct {
Send [SendASimpleSize]byte
}
// PrivateKeySimpleAlice is Alice's NewHope-Simple private key.
type PrivateKeySimpleAlice struct {
sk poly
}
// Reset clears all sensitive information such that it no longer appears in
// memory.
func (k *PrivateKeySimpleAlice) Reset() {
k.sk.reset()
}
// GenerateKeyPairSimpleAlice returns a NewHope-Simple private/public key pair.
// The private key is generated using the given reader, which must return
// random data. The receiver side of the key exchange (aka "Bob") MUST use
// KeyExchangeSimpleBob() instead of this routine.
func GenerateKeyPairSimpleAlice(rand io.Reader) (*PrivateKeySimpleAlice, *PublicKeySimpleAlice, error) {
var a, e, pk, r poly
var seed, noiseSeed [SeedBytes]byte
if _, err := io.ReadFull(rand, seed[:]); err != nil {
return nil, nil, err
}
seed = sha3.Sum256(seed[:]) // Don't send output of system RNG.
a.uniform(&seed, TorSampling)
if _, err := io.ReadFull(rand, noiseSeed[:]); err != nil {
return nil, nil, err
}
defer memwipe(noiseSeed[:])
privKey := new(PrivateKeySimpleAlice)
privKey.sk.getNoise(&noiseSeed, 0)
privKey.sk.ntt()
e.getNoise(&noiseSeed, 1)
e.ntt()
pubKey := new(PublicKeySimpleAlice)
r.pointwise(&privKey.sk, &a)
pk.add(&e, &r)
encodeA(pubKey.Send[:], &pk, &seed)
return privKey, pubKey, nil
}
// PublicKeySimpleBob is Bob's NewHope-Simple public key.
type PublicKeySimpleBob struct {
Send [SendBSimpleSize]byte
}
// KeyExchangeSimpleBob is the Responder side of the NewHope-Simple key
// exchange. The shared secret and "public key" are generated using the
// given reader, which must return random data.
func KeyExchangeSimpleBob(rand io.Reader, alicePk *PublicKeySimpleAlice) (*PublicKeySimpleBob, []byte, error) {
var pka, a, sp, ep, bp, v, epp, m poly
var seed, noiseSeed [SeedBytes]byte
if _, err := io.ReadFull(rand, noiseSeed[:]); err != nil {
return nil, nil, err
}
defer memwipe(noiseSeed[:])
var sharedKey [SharedSecretSize]byte
if _, err := io.ReadFull(rand, sharedKey[:]); err != nil {
return nil, nil, err
}
defer memwipe(sharedKey[:])
sharedKey = sha3.Sum256(sharedKey[:])
m.fromMsg(sharedKey[:])
decodeA(&pka, &seed, alicePk.Send[:])
a.uniform(&seed, TorSampling)
sp.getNoise(&noiseSeed, 0)
sp.ntt()
ep.getNoise(&noiseSeed, 1)
ep.ntt()
bp.pointwise(&a, &sp)
bp.add(&bp, &ep)
v.pointwise(&pka, &sp)
v.invNtt()
epp.getNoise(&noiseSeed, 2)
v.add(&v, &epp)
v.add(&v, &m) // add key
pubKey := new(PublicKeySimpleBob)
encodeBSimple(pubKey.Send[:], &bp, &v)
mu := sha3.Sum256(sharedKey[:])
// Scrub the sensitive stuff...
sp.reset()
v.reset()
m.reset()
return pubKey, mu[:], nil
}
// KeyExchangeSimpleAlice is the Initiaitor side of the NewHope-Simple key
// exchange. The provided private key is obliterated prior to returning.
func KeyExchangeSimpleAlice(bobPk *PublicKeySimpleBob, aliceSk *PrivateKeySimpleAlice) ([]byte, error) {
var v, bp, k poly
decodeBSimple(&bp, &v, bobPk.Send[:])
k.pointwise(&aliceSk.sk, &bp)
k.invNtt()
k.sub(&k, &v)
var sharedKey [SharedSecretSize]byte
k.toMsg(sharedKey[:])
// mu <- Sha3-256(v')
mu := sha3.Sum256(sharedKey[:])
// Scrub the sensitive stuff...
memwipe(sharedKey[:])
k.reset()
aliceSk.Reset()
return mu[:], nil
}