@@ -12,60 +12,70 @@ import (
12
12
"github.com/cloudflare/circl/internal/sha3"
13
13
)
14
14
15
- type (
16
- PrivateKey [PrivateKeySize ]byte
17
- PublicKey [PublicKeySize ]byte
18
- )
15
+ type PublicKey struct {
16
+ seed [PublicKeySeedSize ]byte
17
+ p3 [P3Size / 8 ]uint64
19
18
20
- func (pk * PublicKey ) Equal (other * PublicKey ) bool {
21
- return * pk == * other
19
+ // P1 and P2 are expanded from seed
20
+ p1 [P1Size / 8 ]uint64
21
+ p2 [P2Size / 8 ]uint64
22
22
}
23
23
24
- func (sk * PrivateKey ) Equal (other * PrivateKey ) bool {
25
- return subtle .ConstantTimeCompare ((* sk )[:], (* other )[:]) == 1
24
+ type PrivateKey struct {
25
+ seed [KeySeedSize ]byte
26
+
27
+ p1 [P1Size / 8 ]uint64
28
+ o [V * O ]byte
29
+ l [M * V * O / 16 ]uint64
30
+ }
31
+
32
+ func (pk * PublicKey ) Equal (other * PublicKey ) bool {
33
+ return pk .seed == other .seed && pk .p3 == other .p3
26
34
}
27
35
28
- type ExpandedPublicKey struct {
29
- p1 [P1Size ]byte
30
- p2 [P2Size ]byte
31
- p3 [P3Size ]byte
36
+ func (sk * PrivateKey ) Equal (other * PrivateKey ) bool {
37
+ return subtle .ConstantTimeCompare (sk .seed [:], other .seed [:]) == 1
32
38
}
33
39
34
- type ExpandedPrivateKey struct {
35
- seed [KeySeedSize ]byte
36
- o [V * O ]byte
37
- p1 [M * V * V / 16 ]uint64
38
- l [M * V * O / 16 ]uint64
40
+ // Packs the public key into buf.
41
+ func (pk * PublicKey ) Pack (buf * [PublicKeySize ]byte ) {
42
+ copy (buf [:PublicKeySeedSize ], pk .seed [:])
43
+ copyUint64SliceToBytesLE (buf [PublicKeySeedSize :], pk .p3 [:])
39
44
}
40
45
41
- func (pk * PublicKey ) Expand () * ExpandedPublicKey {
42
- seedPk := pk [:PublicKeySeedSize ]
46
+ // Sets pk to the public key encoded in buf.
47
+ func (pk * PublicKey ) Unpack (buf * [PublicKeySize ]byte ) {
48
+ copy (pk .seed [:], buf [:PublicKeySeedSize ])
43
49
44
50
var nonce [16 ]byte
45
51
// TODO there are unnecessary allocations
46
- block , _ := aes .NewCipher (seedPk [:])
52
+ block , _ := aes .NewCipher (pk . seed [:])
47
53
ctr := cipher .NewCTR (block , nonce [:])
48
54
49
- epk := ExpandedPublicKey {}
50
- ctr .XORKeyStream (epk .p1 [:], epk .p1 [:])
51
- ctr .XORKeyStream (epk .p2 [:], epk .p2 [:])
52
-
53
- copy (epk .p3 [:], pk [PublicKeySeedSize :])
55
+ var p1 [P1Size ]byte
56
+ var p2 [P2Size ]byte
57
+ ctr .XORKeyStream (p1 [:], p1 [:])
58
+ ctr .XORKeyStream (p2 [:], p2 [:])
54
59
55
- return & epk
60
+ copyBytesToUint64SliceLE (pk .p1 [:], p1 [:])
61
+ copyBytesToUint64SliceLE (pk .p2 [:], p2 [:])
62
+ copyBytesToUint64SliceLE (pk .p3 [:], buf [PublicKeySeedSize :])
56
63
}
57
64
58
- func (sk * PrivateKey ) Expand () * ExpandedPrivateKey {
59
- var esk ExpandedPrivateKey
65
+ // Packs the private key into buf.
66
+ func (sk * PrivateKey ) Pack (buf * [PrivateKeySize ]byte ) {
67
+ copy (buf [:], sk .seed [:])
68
+ }
60
69
61
- seed := (* sk )[:KeySeedSize ]
62
- copy (esk .seed [:], seed )
70
+ // Sets sk to the private key encoded in buf.
71
+ func (sk * PrivateKey ) Unpack (buf * [PrivateKeySize ]byte ) {
72
+ copy (sk .seed [:], buf [:])
63
73
64
74
var seedPk [PublicKeySeedSize ]byte
65
75
var o [OSize ]byte
66
76
67
77
h := sha3 .NewShake256 ()
68
- _ , _ = h .Write (seed [:])
78
+ _ , _ = h .Write (sk . seed [:])
69
79
_ , _ = h .Read (seedPk [:])
70
80
_ , _ = h .Read (o [:])
71
81
@@ -77,15 +87,13 @@ func (sk *PrivateKey) Expand() *ExpandedPrivateKey {
77
87
var p12 [P1Size + P2Size ]byte
78
88
ctr .XORKeyStream (p12 [:], p12 [:])
79
89
80
- decode (esk .o [:], o [:])
90
+ decode (sk .o [:], o [:])
81
91
82
- copyBytesToUint64SliceLE (esk .p1 [:P1Size / 8 ], p12 [:P1Size ])
83
- copyBytesToUint64SliceLE (esk .l [:], p12 [P1Size :])
92
+ copyBytesToUint64SliceLE (sk .p1 [:P1Size / 8 ], p12 [:P1Size ])
93
+ copyBytesToUint64SliceLE (sk .l [:], p12 [P1Size :])
84
94
85
95
// compute L_i = (P1 + P1^t)*O + P2
86
- mulAddMUpperTriangularWithTransposeMatXMat (esk .l [:], esk .p1 [:], esk .o [:], V , O )
87
-
88
- return & esk
96
+ mulAddMUpperTriangularWithTransposeMatXMat (sk .l [:], sk .p1 [:], sk .o [:], V , O )
89
97
}
90
98
91
99
// decode unpacks N bytes from src to N*2 nibbles of dst.
@@ -103,7 +111,7 @@ func decode(dst []byte, src []byte) {
103
111
}
104
112
}
105
113
106
- // encode packs N=length low nibbles from src to (N+1)/2 bytes in dst.
114
+ // encode packs N=length low nibbles from src to ceil(N/2) bytes in dst.
107
115
func encode (dst []byte , src []byte , length int ) {
108
116
var i int
109
117
for i = 0 ; i + 1 < length ; i += 2 {
@@ -147,51 +155,49 @@ func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) {
147
155
148
156
func NewKeyFromSeed (seed [KeySeedSize ]byte ) (* PublicKey , * PrivateKey ) {
149
157
var sk PrivateKey
150
- copy ( sk [:], seed [:] )
158
+ sk . Unpack ( & seed )
151
159
152
160
return sk .Public (), & sk
153
161
}
154
162
155
163
func (sk * PrivateKey ) Public () * PublicKey {
156
164
var pk PublicKey
157
- seedPk := pk [:PublicKeySeedSize ]
158
165
var o [OSize ]byte
159
166
160
167
h := sha3 .NewShake256 ()
161
- _ , _ = h .Write (sk [:])
162
- _ , _ = h .Read (seedPk [:])
168
+ _ , _ = h .Write (sk . seed [:])
169
+ _ , _ = h .Read (pk . seed [:])
163
170
_ , _ = h .Read (o [:])
164
171
165
172
var nonce [16 ]byte
166
173
// TODO there are unnecessary allocations
167
- block , _ := aes .NewCipher (seedPk [:])
174
+ block , _ := aes .NewCipher (pk . seed [:])
168
175
ctr := cipher .NewCTR (block , nonce [:])
169
176
170
- var p12 [P1Size + P2Size ]byte
171
- ctr .XORKeyStream (p12 [:], p12 [:])
177
+ var p1 [P1Size ]byte
178
+ var p2 [P2Size ]byte
179
+ ctr .XORKeyStream (p1 [:], p1 [:])
180
+ ctr .XORKeyStream (p2 [:], p2 [:])
181
+
182
+ copyBytesToUint64SliceLE (pk .p1 [:], p1 [:])
183
+ copyBytesToUint64SliceLE (pk .p2 [:], p2 [:])
172
184
173
185
var oo [V * O ]byte
174
186
decode (oo [:], o [:])
175
187
176
- var p1Tri [P1Size / 8 ]uint64
177
188
var p1OP2 [P2Size / 8 ]uint64
178
- copyBytesToUint64SliceLE (p1Tri [:], p12 [:P1Size ])
179
- copyBytesToUint64SliceLE (p1OP2 [:], p12 [P1Size :])
189
+ copy (p1OP2 [:], pk .p2 [:])
180
190
181
191
var p3full [M * O * O / 16 ]uint64
182
- var p3 [P3Size / 8 ]uint64
183
-
184
- mulAddMUpperTriangularMatXMat (p1OP2 [:], p1Tri [:], oo [:], V , O )
192
+ mulAddMUpperTriangularMatXMat (p1OP2 [:], pk .p1 [:], oo [:], V , O )
185
193
mulAddMatTransXMMat (p3full [:], oo [:], p1OP2 [:], V , O , O )
186
194
187
- upper (p3full [:], p3 [:], O )
188
-
189
- copyUint64SliceToBytesLE (pk [PublicKeySeedSize :], p3 [:])
195
+ upper (p3full [:], pk .p3 [:], O )
190
196
191
197
return & pk
192
198
}
193
199
194
- func Sign (msg []byte , sk * ExpandedPrivateKey , rand io.Reader ) ([]byte , error ) {
200
+ func Sign (msg []byte , sk * PrivateKey , rand io.Reader ) ([]byte , error ) {
195
201
if rand == nil {
196
202
rand = cryptoRand .Reader
197
203
}
@@ -622,7 +628,7 @@ func transpose16x16Nibbles(m []uint64) {
622
628
}
623
629
}
624
630
625
- func Verify (epk * ExpandedPublicKey , msg []byte , sig []byte ) bool {
631
+ func Verify (pk * PublicKey , msg []byte , sig []byte ) bool {
626
632
if len (sig ) != SignatureSize {
627
633
return false
628
634
}
@@ -649,13 +655,6 @@ func Verify(epk *ExpandedPublicKey, msg []byte, sig []byte) bool {
649
655
var s [K * N ]byte
650
656
decode (s [:], senc [:])
651
657
652
- var P1 [P1Size / 8 ]uint64
653
- var P2 [P2Size / 8 ]uint64
654
- var P3 [P3Size / 8 ]uint64
655
- copyBytesToUint64SliceLE (P1 [:], epk .p1 [:])
656
- copyBytesToUint64SliceLE (P2 [:], epk .p2 [:])
657
- copyBytesToUint64SliceLE (P3 [:], epk .p3 [:])
658
-
659
658
// Note: the variable time approach is overall about 30% faster
660
659
// compute P * S^t = [ P1 P2 ] * [S1] = [P1*S1 + P2*S2]
661
660
// [ 0 P3 ] [S2] [ P3*S2]
@@ -665,7 +664,7 @@ func Verify(epk *ExpandedPublicKey, msg []byte, sig []byte) bool {
665
664
// mulAddMMatXMatTrans(pst[:], P2, s[V:], V, O, K, N, false)
666
665
// mulAddMMatXMatTrans(pst[M*V*K/16:], P3, s[V:], O, O, K, N, true)
667
666
// Variable time approach with table access where index depends on input:
668
- calculatePStVarTime (pst [:], P1 [:], P2 [:], P3 [:], s [:])
667
+ calculatePStVarTime (pst [:], pk . p1 [:], pk . p2 [:], pk . p3 [:], s [:])
669
668
670
669
// compute S * PST
671
670
var sps [M * K * K / 16 ]uint64
0 commit comments