Skip to content

Commit 092d7a3

Browse files
committed
Changes after rozbb review.
1 parent 977bb19 commit 092d7a3

11 files changed

+44
-24
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Alternatively, look at the [Cloudflare Go](https://github.com/cloudflare/go/tree
3838
[RFC-9496]: https://doi.org/10.17487/RFC9496
3939
[RFC-9497]: https://doi.org/10.17487/RFC9497
4040
[FIPS 202]: https://doi.org/10.6028/NIST.FIPS.202
41+
[FIPS 204]: https://doi.org/10.6028/NIST.FIPS.204
4142
[FIPS 205]: https://doi.org/10.6028/NIST.FIPS.205
4243
[FIPS 186-5]: https://doi.org/10.6028/NIST.FIPS.186-5
4344
[BLS12-381]: https://electriccoin.co/blog/new-snark-curve/
@@ -92,7 +93,7 @@ Alternatively, look at the [Cloudflare Go](https://github.com/cloudflare/go/tree
9293
|:---:|
9394

9495
- [Dilithium](./sign/dilithium): modes 2, 3, 5 ([Dilithium](https://pq-crystals.org/dilithium/)).
95-
- [ML-DSA](./sign/mldsa): modes 44, 65, 87 ([FIPS 204](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf)).
96+
- [ML-DSA](./sign/mldsa): modes 44, 65, 87 ([FIPS 204]).
9697
- [SLH-DSA](./sign/slhdsa): twelve parameter sets, pure and pre-hash signing ([FIPS 205]).
9798

9899
### Zero-knowledge Proofs

sign/schemes/schemes.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,26 @@
66
// Ed448
77
// Ed25519-Dilithium2
88
// Ed448-Dilithium3
9+
// Dilithium
10+
// ML-DSA
11+
// SLH-DSA
912
package schemes
1013

1114
import (
1215
"strings"
1316

1417
"github.com/cloudflare/circl/sign"
18+
dilithium2 "github.com/cloudflare/circl/sign/dilithium/mode2"
19+
dilithium3 "github.com/cloudflare/circl/sign/dilithium/mode3"
20+
dilithium5 "github.com/cloudflare/circl/sign/dilithium/mode5"
1521
"github.com/cloudflare/circl/sign/ed25519"
1622
"github.com/cloudflare/circl/sign/ed448"
1723
"github.com/cloudflare/circl/sign/eddilithium2"
1824
"github.com/cloudflare/circl/sign/eddilithium3"
19-
"github.com/cloudflare/circl/sign/slhdsa"
20-
dilithium2 "github.com/cloudflare/circl/sign/dilithium/mode2"
21-
dilithium3 "github.com/cloudflare/circl/sign/dilithium/mode3"
22-
dilithium5 "github.com/cloudflare/circl/sign/dilithium/mode5"
2325
"github.com/cloudflare/circl/sign/mldsa/mldsa44"
2426
"github.com/cloudflare/circl/sign/mldsa/mldsa65"
2527
"github.com/cloudflare/circl/sign/mldsa/mldsa87"
28+
"github.com/cloudflare/circl/sign/slhdsa"
2629
)
2730

2831
var allSchemes = [...]sign.Scheme{

sign/slhdsa/acvp_test.go

-4
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,6 @@ func testVerify(t *testing.T) {
180180
}
181181

182182
func acvpKeygen(t *testing.T, paramSet string, in *keygenInput) {
183-
t.Parallel()
184-
185183
id, err := ParamIDByName(paramSet)
186184
test.CheckNoErr(t, err, "invalid param name")
187185

@@ -226,8 +224,6 @@ func acvpSign(
226224
wantSignature []byte,
227225
deterministic bool,
228226
) {
229-
t.Parallel()
230-
231227
id, err := ParamIDByName(paramSet)
232228
test.CheckNoErr(t, err, "invalid param name")
233229

sign/slhdsa/all_test.go

-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ func TestInner(t *testing.T) {
1111
param := &supportedParams[i]
1212

1313
t.Run(param.name, func(t *testing.T) {
14-
t.Parallel()
15-
1614
t.Run("Wots", func(t *testing.T) { testWotsPlus(t, param) })
1715
t.Run("Xmss", func(t *testing.T) { testXmss(t, param) })
1816
t.Run("Ht", func(tt *testing.T) { testHyperTree(tt, param) })

sign/slhdsa/fors.go

+9-4
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ func (s *statePriv) forsSkGen(addr address, idx uint32) forsPrivateKey {
4646
}
4747

4848
// See FIPS 205 -- Section 8.2 -- Algorithm 15 -- Iterative version.
49+
//
50+
// This is a stack-based implementation that computes the tree leaves
51+
// in order (from the left to the right).
52+
// Its recursive version can be found at fors_test.go file.
4953
func (s *statePriv) forsNodeIter(
5054
stack stackNode, root []byte, i, z uint32, addr address,
5155
) {
@@ -103,7 +107,8 @@ func (s *statePriv) forsSign(sig forsSignature, digest []byte, addr address) {
103107

104108
bits -= s.a
105109
indicesI := (total >> bits) & maskA
106-
forsSk := s.forsSkGen(addr, (i<<s.a)+indicesI)
110+
treeIdx := (i << s.a) + indicesI
111+
forsSk := s.forsSkGen(addr, treeIdx)
107112
copy(sig[i].sk, forsSk)
108113

109114
for j := uint32(0); j < s.a; j++ {
@@ -115,7 +120,7 @@ func (s *statePriv) forsSign(sig forsSignature, digest []byte, addr address) {
115120

116121
// See FIPS 205 -- Section 8.4 -- Algorithm 17.
117122
func (s *state) forsPkFromSig(
118-
digest []byte, sig forsSignature, addr address,
123+
sig forsSignature, digest []byte, addr address,
119124
) (pk forsPublicKey) {
120125
pk = make([]byte, s.forsPkSize())
121126

@@ -130,7 +135,7 @@ func (s *state) forsPkFromSig(
130135
s.T.Reset()
131136

132137
in, bits, total := 0, uint32(0), uint32(0)
133-
maskB := (uint32(1) << s.a) - 1
138+
maskA := (uint32(1) << s.a) - 1
134139

135140
for i := uint32(0); i < s.k; i++ {
136141
for bits < s.a {
@@ -140,7 +145,7 @@ func (s *state) forsPkFromSig(
140145
}
141146

142147
bits -= s.a
143-
indicesI := (total >> bits) & maskB
148+
indicesI := (total >> bits) & maskA
144149
treeIdx := (i << s.a) + indicesI
145150
s.F.address.SetTreeIndex(treeIdx)
146151
s.F.SetMessage(sig[i].sk)

sign/slhdsa/fors_test.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,7 @@ func testFors(t *testing.T, p *params) {
6565
curSig := cursor(make([]byte, p.forsSigSize()))
6666
sig.fromBytes(p, &curSig)
6767
state.forsSign(sig, msg, addr)
68-
69-
pkFors := state.forsPkFromSig(msg, sig, addr)
68+
pkFors := state.forsPkFromSig(sig, msg, addr)
7069

7170
var htSig hyperTreeSignature
7271
curHtSig := cursor(make([]byte, p.hyperTreeSigSize()))
@@ -111,7 +110,7 @@ func benchmarkFors(b *testing.B, p *params) {
111110
})
112111
b.Run("PkFromSig", func(b *testing.B) {
113112
for i := 0; i < b.N; i++ {
114-
_ = state.forsPkFromSig(msg, sig, addr)
113+
_ = state.forsPkFromSig(sig, msg, addr)
115114
}
116115
})
117116
}

sign/slhdsa/internal.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func slhSignInternal(
8686
defer s.Clear()
8787

8888
s.forsSign(sig.forsSig, md, addr)
89-
pkFors := s.forsPkFromSig(md, sig.forsSig, addr)
89+
pkFors := s.forsPkFromSig(sig.forsSig, md, addr)
9090
s.htSign(sig.htSig, pkFors, idxTree, idxLeaf)
9191

9292
return sigBytes, nil
@@ -114,7 +114,7 @@ func slhVerifyInternal(
114114
s := p.NewStatePub(pub.seed)
115115
defer s.Clear()
116116

117-
pkFors := s.forsPkFromSig(md, sig.forsSig, addr)
117+
pkFors := s.forsPkFromSig(sig.forsSig, md, addr)
118118
return s.htVerify(pkFors, pub.root, idxTree, idxLeaf, sig.htSig)
119119
}
120120

sign/slhdsa/slhdsa.go

+1
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ func readRandom(random io.Reader, size uint32) (out []byte, err error) {
274274

275275
var (
276276
ErrContext = fmt.Errorf("sign/slhdsa: context is larger than MaxContextSize=%v bytes", MaxContextSize)
277+
ErrMsgLen = errors.New("sign/slhdsa: invalid message length")
277278
ErrParam = errors.New("sign/slhdsa: invalid SLH-DSA parameter")
278279
ErrPreHash = errors.New("sign/slhdsa: invalid prehash function")
279280
ErrSigParse = errors.New("sign/slhdsa: failed to decode the signature")

sign/slhdsa/slhdsa_test.go

-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ func TestSlhdsa(t *testing.T) {
3737
id := supportedParameters[i]
3838

3939
t.Run(id.Name(), func(t *testing.T) {
40-
t.Parallel()
41-
4240
t.Run("Keys", func(t *testing.T) { testKeys(t, id) })
4341

4442
for j := range supportedPrehashIDs {

sign/slhdsa/wotsp.go

+17-2
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ func (ws *wotsSignature) fromBytes(p *params, c *cursor) {
2222
}
2323

2424
// See FIPS 205 -- Section 5 -- Algorithm 5.
25-
func (s *state) chain(x []byte, index, step uint32, addr address) (out []byte) {
25+
func (s *state) chain(x []byte, index, steps uint32, addr address) (out []byte) {
2626
out = x
2727
s.F.address.Set(addr)
28-
for j := index; j < index+step; j++ {
28+
for j := index; j < index+steps; j++ {
2929
s.F.address.SetHashAddress(j)
3030
s.F.SetMessage(out)
3131
out = s.F.Final()
@@ -60,6 +60,10 @@ func (s *statePriv) wotsPkGen(addr address) wotsPublicKey {
6060

6161
// See FIPS 205 -- Section 5.2 -- Algorithm 7.
6262
func (s *statePriv) wotsSign(sig wotsSignature, msg []byte, addr address) {
63+
if len(msg) != int(s.wotsLen1()/2) {
64+
panic(ErrMsgLen)
65+
}
66+
6367
curSig := cursor(sig)
6468
wotsLen1 := s.wotsLen1()
6569
csum := wotsLen1 * (wotsW - 1)
@@ -68,6 +72,7 @@ func (s *statePriv) wotsSign(sig wotsSignature, msg []byte, addr address) {
6872
s.PRF.address.SetTypeAndClear(addressWotsPrf)
6973
s.PRF.address.SetKeyPairAddress(addr.GetKeyPairAddress())
7074

75+
// Signs every nibble of the message and computes the checksum.
7176
for i := uint32(0); i < wotsLen1; i++ {
7277
s.PRF.address.SetChainAddress(i)
7378
sk := s.PRF.Final()
@@ -79,6 +84,7 @@ func (s *statePriv) wotsSign(sig wotsSignature, msg []byte, addr address) {
7984
csum -= msgi
8085
}
8186

87+
// Lastly, every nibble of the checksum is also signed.
8288
for i := uint32(0); i < wotsLen2; i++ {
8389
s.PRF.address.SetChainAddress(wotsLen1 + i)
8490
sk := s.PRF.Final()
@@ -94,6 +100,10 @@ func (s *statePriv) wotsSign(sig wotsSignature, msg []byte, addr address) {
94100
func (s *state) wotsPkFromSig(
95101
sig wotsSignature, msg []byte, addr address,
96102
) wotsPublicKey {
103+
if len(msg) != int(s.wotsLen1()/2) {
104+
panic(ErrMsgLen)
105+
}
106+
97107
wotsLen1 := s.wotsLen1()
98108
csum := wotsLen1 * (wotsW - 1)
99109

@@ -104,6 +114,8 @@ func (s *state) wotsPkFromSig(
104114
s.T.Reset()
105115
curSig := cursor(sig)
106116

117+
// Signs every nibble of the message, computes the checksum, and
118+
// feeds each signature to the T function.
107119
for i := uint32(0); i < wotsLen1; i++ {
108120
addr.SetChainAddress(i)
109121
msgi := uint32((msg[i/2] >> ((1 - (i & 1)) << 2)) & 0xF)
@@ -113,6 +125,8 @@ func (s *state) wotsPkFromSig(
113125
csum -= msgi
114126
}
115127

128+
// Every nibble of the checksum is also signed feeding the signature
129+
// to the T function.
116130
for i := uint32(0); i < wotsLen2; i++ {
117131
addr.SetChainAddress(wotsLen1 + i)
118132
csumi := (csum >> (8 - 4*i)) & 0xF
@@ -121,5 +135,6 @@ func (s *state) wotsPkFromSig(
121135
s.T.WriteMessage(sigi)
122136
}
123137

138+
// Generates the public key as the output of the T function.
124139
return s.T.Final()
125140
}

sign/slhdsa/xmss.go

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ func (xs *xmssSignature) fromBytes(p *params, c *cursor) {
2424
}
2525

2626
// See FIPS 205 -- Section 6.1 -- Algorithm 9 -- Iterative version.
27+
//
28+
// This is a stack-based implementation that computes the tree leaves
29+
// in order (from the left to the right).
30+
// Its recursive version can be found at xmss_test.go file.
2731
func (s *statePriv) xmssNodeIter(
2832
stack stackNode, root []byte, i, z uint32, addr address,
2933
) {

0 commit comments

Comments
 (0)