Skip to content

Commit ec347f5

Browse files
committed
Adding decaf group.
1 parent 796b37e commit ec347f5

File tree

6 files changed

+58
-96
lines changed

6 files changed

+58
-96
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,12 @@ Version numbers are [Semvers](https://semver.org/). We release a minor version f
3535
| PQ Key Exchange | SIDH | SIDH provide key exchange mechanisms using ephemeral keys. | Post-quantum key exchange in TLS |
3636
| PQ Key Exchange | cSIDH | Isogeny based drop-in replacement for Diffie–Hellman | Post-Quantum Key exchange. |
3737
| PQ KEM | SIKE | SIKE is a key encapsulation mechanism (KEM). | Post-quantum key exchange in TLS |
38+
| PQ Digital Signatures | Dilithium, Hybrid modes | Lattice (Module LWE) based signature scheme | Post-Quantum PKI |
3839
| Key Exchange | X25519, X448 | RFC-7748 provides new key exchange mechanisms based on Montgomery elliptic curves. | TLS 1.3. Secure Shell. |
3940
| Key Exchange | FourQ | One of the fastest elliptic curves at 128-bit security level. | Experimental for key agreement and digital signatures. |
4041
| Key Exchange / Digital signatures | P-384 | Our optimizations reduce the burden when moving from P-256 to P-384. | ECDSA and ECDH using Suite B at top secret level. |
4142
| Digital Signatures | Ed25519, Ed448 | RFC-8032 provides new signature schemes based on Edwards curves. | Digital certificates and authentication. |
42-
| PQ Digital Signatures | Dilithium, Hybrid modes | Lattice (Module LWE) based signature scheme | Post-Quantum PKI |
43+
| Groups | Decaf | Prime-order groups. | Protocols based on the Discrete Logarithm Problem. |
4344

4445
### Work in Progress
4546

sign/ed25519/ed25519.go

+17-24
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ import (
4343
"crypto/subtle"
4444
"errors"
4545
"fmt"
46+
"hash"
4647
"io"
47-
"strconv"
4848
)
4949

5050
const (
@@ -95,17 +95,14 @@ type PrivateKey []byte
9595
// Equal reports whether priv and x have the same value.
9696
func (priv PrivateKey) Equal(x crypto.PrivateKey) bool {
9797
xx, ok := x.(PrivateKey)
98-
if !ok {
99-
return false
100-
}
101-
return subtle.ConstantTimeCompare(priv, xx) == 1
98+
return ok && subtle.ConstantTimeCompare(priv, xx) == 1
10299
}
103100

104101
// Public returns the PublicKey corresponding to priv.
105102
func (priv PrivateKey) Public() crypto.PublicKey {
106-
publicKey := make([]byte, PublicKeySize)
103+
publicKey := make(PublicKey, PublicKeySize)
107104
copy(publicKey, priv[SeedSize:])
108-
return PublicKey(publicKey)
105+
return publicKey
109106
}
110107

111108
// Seed returns the private key seed corresponding to priv. It is provided for
@@ -163,10 +160,9 @@ func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
163160
return nil, nil, err
164161
}
165162

166-
privateKey := NewKeyFromSeed(seed)
167-
publicKey := make([]byte, PublicKeySize)
168-
copy(publicKey, privateKey[SeedSize:])
169-
163+
privateKey := make(PrivateKey, PrivateKeySize)
164+
publicKey := make(PublicKey, PublicKeySize)
165+
newKeyFromSeed(privateKey, publicKey, seed)
170166
return publicKey, privateKey, nil
171167
}
172168

@@ -175,27 +171,29 @@ func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
175171
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
176172
// package.
177173
func NewKeyFromSeed(seed []byte) PrivateKey {
178-
privateKey := make([]byte, PrivateKeySize)
179-
newKeyFromSeed(privateKey, seed)
174+
privateKey := make(PrivateKey, PrivateKeySize)
175+
newKeyFromSeed(privateKey, PublicKey(privateKey[SeedSize:]), seed)
180176
return privateKey
181177
}
182178

183-
func newKeyFromSeed(privateKey, seed []byte) {
179+
func newKeyFromSeed(privateKey PrivateKey, publicKey PublicKey, seed []byte) {
184180
if l := len(seed); l != SeedSize {
185-
panic("ed25519: bad seed length: " + strconv.Itoa(l))
181+
panic(fmt.Errorf("ed25519: bad seed length: %v", l))
186182
}
187183
var P pointR1
188184
k := sha512.Sum512(seed)
189185
clamp(k[:])
190186
reduceModOrder(k[:paramB], false)
191187
P.fixedMult(k[:paramB])
192-
copy(privateKey[:SeedSize], seed)
193188
_ = P.ToBytes(privateKey[SeedSize:])
189+
190+
copy(privateKey[:SeedSize], seed)
191+
copy(publicKey[:PublicKeySize], privateKey[SeedSize:])
194192
}
195193

196194
func sign(signature []byte, privateKey PrivateKey, message, ctx []byte, preHash bool) {
197195
if l := len(privateKey); l != PrivateKeySize {
198-
panic("ed25519: bad private key length: " + strconv.Itoa(l))
196+
panic(fmt.Errorf("ed25519: bad private key length: %v", l))
199197
}
200198

201199
H := sha512.New()
@@ -216,10 +214,7 @@ func sign(signature []byte, privateKey PrivateKey, message, ctx []byte, preHash
216214
prefix, s := h[paramB:], h[:paramB]
217215

218216
// 2. Compute SHA-512(dom2(F, C) || prefix || PH(M))
219-
H.Reset()
220-
221217
writeDom(H, ctx, preHash)
222-
223218
_, _ = H.Write(prefix)
224219
_, _ = H.Write(PHM)
225220
r := H.Sum(nil)
@@ -234,10 +229,7 @@ func sign(signature []byte, privateKey PrivateKey, message, ctx []byte, preHash
234229
}
235230

236231
// 4. Compute SHA512(dom2(F, C) || R || A || PH(M)).
237-
H.Reset()
238-
239232
writeDom(H, ctx, preHash)
240-
241233
_, _ = H.Write(R)
242234
_, _ = H.Write(privateKey[SeedSize:])
243235
_, _ = H.Write(PHM)
@@ -413,7 +405,8 @@ func isLessThanOrder(x []byte) bool {
413405
return x[i] < order[i]
414406
}
415407

416-
func writeDom(h io.Writer, ctx []byte, preHash bool) {
408+
func writeDom(h hash.Hash, ctx []byte, preHash bool) {
409+
h.Reset()
417410
dom2 := "SigEd25519 no Ed25519 collisions"
418411

419412
if len(ctx) > 0 {

sign/ed25519/ed25519_test.go

+4-15
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,12 @@
11
package ed25519_test
22

33
import (
4+
"crypto/rand"
45
"testing"
56

67
"github.com/cloudflare/circl/sign/ed25519"
78
)
89

9-
type zeroReader struct{}
10-
11-
func (zeroReader) Read(buf []byte) (int, error) {
12-
for i := range buf {
13-
buf[i] = 0
14-
}
15-
return len(buf), nil
16-
}
17-
1810
func TestMalleability(t *testing.T) {
1911
// https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test
2012
// that s be in [0, order). This prevents someone from adding a multiple of
@@ -40,9 +32,8 @@ func TestMalleability(t *testing.T) {
4032
}
4133

4234
func BenchmarkKeyGeneration(b *testing.B) {
43-
var zero zeroReader
4435
for i := 0; i < b.N; i++ {
45-
if _, _, err := ed25519.GenerateKey(zero); err != nil {
36+
if _, _, err := ed25519.GenerateKey(rand.Reader); err != nil {
4637
b.Fatal(err)
4738
}
4839
}
@@ -57,8 +48,7 @@ func BenchmarkNewKeyFromSeed(b *testing.B) {
5748
}
5849

5950
func BenchmarkSigning(b *testing.B) {
60-
var zero zeroReader
61-
_, priv, err := ed25519.GenerateKey(zero)
51+
_, priv, err := ed25519.GenerateKey(rand.Reader)
6252
if err != nil {
6353
b.Fatal(err)
6454
}
@@ -71,8 +61,7 @@ func BenchmarkSigning(b *testing.B) {
7161
}
7262

7363
func BenchmarkVerification(b *testing.B) {
74-
var zero zeroReader
75-
pub, priv, err := ed25519.GenerateKey(zero)
64+
pub, priv, err := ed25519.GenerateKey(rand.Reader)
7665
if err != nil {
7766
b.Fatal(err)
7867
}

sign/ed25519/extra_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ func BenchmarkEd25519Ph(b *testing.B) {
149149
ctx := ""
150150
b.ResetTimer()
151151
for i := 0; i < b.N; i++ {
152-
_ = ed25519.SignPh(key, msg, ctx)
152+
ed25519.SignPh(key, msg, ctx)
153153
}
154154
})
155155
b.Run("Verify", func(b *testing.B) {
@@ -171,7 +171,7 @@ func BenchmarkEd25519Ctx(b *testing.B) {
171171
_, priv, _ := ed25519.GenerateKey(rand.Reader)
172172
b.ResetTimer()
173173
for i := 0; i < b.N; i++ {
174-
_ = ed25519.SignWithCtx(priv, msg, ctx)
174+
ed25519.SignWithCtx(priv, msg, ctx)
175175
}
176176
})
177177
b.Run("Verify", func(b *testing.B) {

sign/ed448/ed448.go

+29-38
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,8 @@ import (
2828
"crypto"
2929
cryptoRand "crypto/rand"
3030
"crypto/subtle"
31-
"errors"
3231
"fmt"
3332
"io"
34-
"strconv"
3533

3634
sha3 "github.com/cloudflare/circl/internal/shake"
3735
"github.com/cloudflare/circl/sign/ed448/internal/goldilocks"
@@ -65,7 +63,8 @@ type SignerOptions struct {
6563
// Its length must be less or equal than 255 bytes.
6664
Context string
6765

68-
// Scheme is an identifier for choosing a signature scheme.
66+
// Scheme is an identifier for choosing a signature scheme. The zero value
67+
// is ED448.
6968
Scheme SchemeID
7069
}
7170

@@ -83,10 +82,7 @@ type PublicKey []byte
8382
// Equal reports whether pub and x have the same value.
8483
func (pub PublicKey) Equal(x crypto.PublicKey) bool {
8584
xx, ok := x.(PublicKey)
86-
if !ok {
87-
return false
88-
}
89-
return bytes.Equal(pub, xx)
85+
return ok && bytes.Equal(pub, xx)
9086
}
9187

9288
// PrivateKey is the type of Ed448 private keys. It implements crypto.Signer.
@@ -95,17 +91,14 @@ type PrivateKey []byte
9591
// Equal reports whether priv and x have the same value.
9692
func (priv PrivateKey) Equal(x crypto.PrivateKey) bool {
9793
xx, ok := x.(PrivateKey)
98-
if !ok {
99-
return false
100-
}
101-
return subtle.ConstantTimeCompare(priv, xx) == 1
94+
return ok && subtle.ConstantTimeCompare(priv, xx) == 1
10295
}
10396

10497
// Public returns the PublicKey corresponding to priv.
10598
func (priv PrivateKey) Public() crypto.PublicKey {
106-
publicKey := make([]byte, PublicKeySize)
99+
publicKey := make(PublicKey, PublicKeySize)
107100
copy(publicKey, priv[SeedSize:])
108-
return PublicKey(publicKey)
101+
return publicKey
109102
}
110103

111104
// Seed returns the private key seed corresponding to priv. It is provided for
@@ -143,7 +136,7 @@ func (priv PrivateKey) Sign(
143136
case scheme == ED448Ph && opts.HashFunc() == crypto.Hash(0):
144137
return SignPh(priv, message, ctx), nil
145138
default:
146-
return nil, errors.New("ed448: bad hash algorithm")
139+
return nil, fmt.Errorf("ed448: bad hash algorithm")
147140
}
148141
}
149142

@@ -159,10 +152,9 @@ func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
159152
return nil, nil, err
160153
}
161154

162-
privateKey := NewKeyFromSeed(seed)
163-
publicKey := make([]byte, PublicKeySize)
164-
copy(publicKey, privateKey[SeedSize:])
165-
155+
privateKey := make(PrivateKey, PrivateKeySize)
156+
publicKey := make(PublicKey, PublicKeySize)
157+
newKeyFromSeed(privateKey, publicKey, seed)
166158
return publicKey, privateKey, nil
167159
}
168160

@@ -171,14 +163,14 @@ func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
171163
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
172164
// package.
173165
func NewKeyFromSeed(seed []byte) PrivateKey {
174-
privateKey := make([]byte, PrivateKeySize)
175-
newKeyFromSeed(privateKey, seed)
166+
privateKey := make(PrivateKey, PrivateKeySize)
167+
newKeyFromSeed(privateKey, PublicKey(privateKey[SeedSize:]), seed)
176168
return privateKey
177169
}
178170

179-
func newKeyFromSeed(privateKey, seed []byte) {
171+
func newKeyFromSeed(privateKey PrivateKey, publicKey PublicKey, seed []byte) {
180172
if l := len(seed); l != SeedSize {
181-
panic("ed448: bad seed length: " + strconv.Itoa(l))
173+
panic(fmt.Errorf("ed448: bad seed length: %v", l))
182174
}
183175

184176
var h [hashSize]byte
@@ -188,18 +180,21 @@ func newKeyFromSeed(privateKey, seed []byte) {
188180
s := &goldilocks.Scalar{}
189181
deriveSecretScalar(s, h[:paramB])
190182

191-
copy(privateKey[:SeedSize], seed)
192183
var P goldilocks.Point
193184
P.ScalarBaseMult(s)
194-
err := P.Encode(&pair.public)
195-
if err != nil {
185+
var encP [goldilocks.EncodingSize]byte
186+
if err := P.Encode(&encP); err != nil {
196187
panic(err)
197188
}
189+
190+
copy(privateKey[:SeedSize], seed)
191+
copy(privateKey[SeedSize:], encP[:])
192+
copy(publicKey[:PublicKeySize], encP[:])
198193
}
199194

200195
func sign(signature []byte, privateKey PrivateKey, message, ctx []byte, preHash bool) {
201196
if len(ctx) > ContextMaxSize {
202-
panic(fmt.Errorf("ed448: bad context length: " + strconv.Itoa(len(ctx))))
197+
panic(fmt.Errorf("ed448: bad context length: %v", len(ctx)))
203198
}
204199

205200
H := sha3.NewShake256()
@@ -225,10 +220,7 @@ func sign(signature []byte, privateKey PrivateKey, message, ctx []byte, preHash
225220

226221
// 2. Compute SHAKE256(dom4(F, C) || prefix || PH(M), 114).
227222
var rPM [hashSize]byte
228-
H.Reset()
229-
230223
writeDom(&H, ctx, preHash)
231-
232224
_, _ = H.Write(prefix)
233225
_, _ = H.Write(PHM)
234226
_, _ = H.Read(rPM[:])
@@ -239,15 +231,14 @@ func sign(signature []byte, privateKey PrivateKey, message, ctx []byte, preHash
239231
var R goldilocks.Point
240232
var encR [goldilocks.EncodingSize]byte
241233
R.ScalarBaseMult(r)
242-
err := R.Encode(&encR)
234+
if err := R.Encode(&encR); err != nil {
235+
panic(err)
236+
}
243237

244238
// 4. Compute SHAKE256(dom4(F, C) || R || A || PH(M), 114)
245239
var hRAM [hashSize]byte
246-
H.Reset()
247-
248240
writeDom(&H, ctx, preHash)
249-
250-
_, _ = H.Write(R)
241+
_, _ = H.Write(encR[:])
251242
_, _ = H.Write(privateKey[SeedSize:])
252243
_, _ = H.Write(PHM)
253244
_, _ = H.Read(hRAM[:])
@@ -333,9 +324,8 @@ func verify(public PublicKey, message, signature, ctx []byte, preHash bool) bool
333324
var Q goldilocks.Point
334325
Q.CombinedMult(S, k, P)
335326
var encR [goldilocks.EncodingSize]byte
336-
err = Q.Encode(&encR)
337-
if err != nil {
338-
return false
327+
if err = Q.Encode(&encR); err != nil {
328+
panic(err)
339329
}
340330
return bytes.Equal(R, encR[:])
341331
}
@@ -400,7 +390,8 @@ func isLessThanOrder(x []byte) bool {
400390
return x[paramB-1] == 0 && x[i] < order[i]
401391
}
402392

403-
func writeDom(h io.Writer, ctx []byte, preHash bool) {
393+
func writeDom(h *sha3.Shake, ctx []byte, preHash bool) {
394+
h.Reset()
404395
dom4 := "SigEd448"
405396
_, _ = h.Write([]byte(dom4))
406397

0 commit comments

Comments
 (0)