Skip to content

Commit 6b83027

Browse files
committed
torchwood: add NewCosignatureVerifierFromKey
1 parent e6d4341 commit 6b83027

2 files changed

Lines changed: 58 additions & 53 deletions

File tree

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
- Added ML-DSA-44 cosignature support.
1010

11+
- Added `NewCosignatureVerifierFromKey` to produce a verifier from a
12+
`crypto.PublicKey` instead of a vkey.
13+
1114
### mpt
1215

1316
- New package with a Merkle Patricia Trie implementation.

cosignature.go

Lines changed: 55 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,14 @@ const (
3535
//
3636
// Note that ML-DSA-44 cosigners reject checkpoints with extension lines.
3737
func NewCosignatureSigner(name string, key crypto.Signer) (*CosignatureSigner, error) {
38-
if !isValidName(name) {
39-
return nil, errors.New("invalid name")
38+
pubKey := key.Public()
39+
v, err := NewCosignatureVerifierFromKey(name, pubKey)
40+
if err != nil {
41+
return nil, err
4042
}
41-
42-
s := &CosignatureSigner{}
43-
s.v.name = name
44-
45-
ed25519Key, isEd25519 := key.Public().(ed25519.PublicKey)
46-
mldsaKey, isMLDSA := key.Public().(*mldsa.PublicKey)
47-
48-
switch {
49-
case isEd25519:
50-
s.v.hash = keyHash(name, append([]byte{algCosignatureEd25519}, ed25519Key...))
51-
s.v.key = ed25519Key
43+
s := &CosignatureSigner{v: *v}
44+
switch pubKey.(type) {
45+
case ed25519.PublicKey:
5246
s.sign = func(msg []byte) ([]byte, error) {
5347
t := uint64(time.Now().Unix())
5448
m, err := formatCosignatureV1(t, msg)
@@ -66,21 +60,7 @@ func NewCosignatureSigner(name string, key crypto.Signer) (*CosignatureSigner, e
6660
sig = append(sig, s...)
6761
return sig, nil
6862
}
69-
s.v.verify = func(msg, sig []byte) bool {
70-
if len(sig) != 8+ed25519.SignatureSize {
71-
return false
72-
}
73-
t := binary.BigEndian.Uint64(sig)
74-
sig = sig[8:]
75-
m, err := formatCosignatureV1(t, msg)
76-
if err != nil {
77-
return false
78-
}
79-
return ed25519.Verify(ed25519Key, m, sig)
80-
}
81-
case isMLDSA:
82-
s.v.hash = keyHash(name, append([]byte{algCosignatureMLDSA}, mldsaKey.Bytes()...))
83-
s.v.key = mldsaKey
63+
case *mldsa.PublicKey:
8464
s.sign = func(msg []byte) ([]byte, error) {
8565
t := uint64(time.Now().Unix())
8666
m, err := formatSubtreeV1(name, t, msg)
@@ -98,22 +78,9 @@ func NewCosignatureSigner(name string, key crypto.Signer) (*CosignatureSigner, e
9878
sig = append(sig, s...)
9979
return sig, nil
10080
}
101-
s.v.verify = func(msg, sig []byte) bool {
102-
if len(sig) != 8+mldsa.MLDSA44SignatureSize {
103-
return false
104-
}
105-
t := binary.BigEndian.Uint64(sig)
106-
sig = sig[8:]
107-
m, err := formatSubtreeV1(name, t, msg)
108-
if err != nil {
109-
return false
110-
}
111-
return mldsa.Verify(mldsaKey, m, sig, nil) == nil
112-
}
11381
default:
11482
return nil, errors.New("key type is not supported")
11583
}
116-
11784
return s, nil
11885
}
11986

@@ -206,23 +173,58 @@ func NewCosignatureVerifier(vkey string) (*CosignatureVerifier, error) {
206173
hash16, key64, _ := strings.Cut(vkey, "+")
207174
hash, err1 := strconv.ParseUint(hash16, 16, 32)
208175
key, err2 := base64.StdEncoding.DecodeString(key64)
209-
if len(hash16) != 8 || err1 != nil || err2 != nil || !isValidName(name) || len(key) == 0 {
176+
if len(hash16) != 8 || err1 != nil || err2 != nil || len(key) == 0 {
210177
return nil, errors.New("malformed verifier id")
211178
}
212-
if uint32(hash) != keyHash(name, key) {
213-
return nil, errors.New("invalid verifier hash")
214-
}
215179
alg, key := key[0], key[1:]
180+
var verifier *CosignatureVerifier
216181
switch alg {
217182
case algCosignatureEd25519:
218183
if len(key) != ed25519.PublicKeySize {
219184
return nil, errors.New("malformed verifier public key")
220185
}
221186
k := ed25519.PublicKey(key)
187+
v, err := NewCosignatureVerifierFromKey(name, k)
188+
if err != nil {
189+
return nil, err
190+
}
191+
verifier = v
192+
case algCosignatureMLDSA:
193+
k, err := mldsa.NewPublicKey(mldsa.MLDSA44(), key)
194+
if err != nil {
195+
return nil, fmt.Errorf("malformed verifier public key: %w", err)
196+
}
197+
v, err := NewCosignatureVerifierFromKey(name, k)
198+
if err != nil {
199+
return nil, err
200+
}
201+
verifier = v
202+
default:
203+
return nil, errors.New("unknown verifier algorithm")
204+
}
205+
if uint32(hash) != verifier.KeyHash() {
206+
return nil, errors.New("invalid verifier hash")
207+
}
208+
return verifier, nil
209+
}
210+
211+
// NewCosignatureVerifierFromKey constructs a new [CosignatureVerifier] from a
212+
// public key. It supports [ed25519.PublicKey] and [*mldsa.PublicKey].
213+
func NewCosignatureVerifierFromKey(name string, key crypto.PublicKey) (*CosignatureVerifier, error) {
214+
if !isValidName(name) {
215+
return nil, errors.New("invalid name")
216+
}
217+
218+
switch k := key.(type) {
219+
case ed25519.PublicKey:
220+
if len(k) != ed25519.PublicKeySize {
221+
return nil, errors.New("malformed Ed25519 public key")
222+
}
223+
hash := keyHash(name, append([]byte{algCosignatureEd25519}, k...))
222224
return &CosignatureVerifier{
223225
verifier: verifier{
224226
name: name,
225-
hash: uint32(hash),
227+
hash: hash,
226228
verify: func(msg, sig []byte) bool {
227229
if len(sig) != 8+ed25519.SignatureSize {
228230
return false
@@ -239,17 +241,17 @@ func NewCosignatureVerifier(vkey string) (*CosignatureVerifier, error) {
239241
return ed25519.Verify(k, m, sig)
240242
},
241243
},
242-
key: ed25519.PublicKey(key),
244+
key: k,
243245
}, nil
244-
case algCosignatureMLDSA:
245-
k, err := mldsa.NewPublicKey(mldsa.MLDSA44(), key)
246-
if err != nil {
247-
return nil, fmt.Errorf("malformed verifier public key: %w", err)
246+
case *mldsa.PublicKey:
247+
if k.Parameters() != mldsa.MLDSA44() {
248+
return nil, errors.New("ML-DSA parameters are not ML-DSA-44")
248249
}
250+
hash := keyHash(name, append([]byte{algCosignatureMLDSA}, k.Bytes()...))
249251
return &CosignatureVerifier{
250252
verifier: verifier{
251253
name: name,
252-
hash: uint32(hash),
254+
hash: hash,
253255
verify: func(msg, sig []byte) bool {
254256
if len(sig) != 8+mldsa.MLDSA44SignatureSize {
255257
return false
@@ -269,7 +271,7 @@ func NewCosignatureVerifier(vkey string) (*CosignatureVerifier, error) {
269271
key: k,
270272
}, nil
271273
default:
272-
return nil, errors.New("unknown verifier algorithm")
274+
return nil, errors.New("key type is not supported")
273275
}
274276
}
275277

0 commit comments

Comments
 (0)