Skip to content

Commit f4837d4

Browse files
authored
Merge pull request #3 from Mateusvff/MLDSA-tests
feat: add tests for MLDSA
2 parents 6a82248 + d122af3 commit f4837d4

File tree

5 files changed

+401
-78
lines changed

5 files changed

+401
-78
lines changed

device/device_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import (
2121
"time"
2222

2323
"github.com/cloudflare/circl/kem/kyber/kyber1024"
24+
"github.com/cloudflare/circl/sign/dilithium/mode5"
25+
2426

2527
"golang.zx2c4.com/wireguard/conn"
2628
"golang.zx2c4.com/wireguard/conn/bindtest"
@@ -193,6 +195,7 @@ func genTestPair(tb testing.TB, realSocket bool) (pair testPair) {
193195
}
194196

195197
installMLKEMKeys(tb, &pair)
198+
installMLDSAKeys(tb, &pair)
196199

197200
return
198201
}
@@ -508,6 +511,34 @@ func installMLKEMKeys(t testing.TB, pair *testPair) {
508511
if err := pair[1].dev.IpcSet(cfgPeer1); err != nil { t.Fatal(err) }
509512
}
510513

514+
func installMLDSAKeys(t testing.TB, pair *testPair) {
515+
t.Helper()
516+
517+
dil := mode5.Scheme()
518+
pk0, sk0, err := dil.GenerateKey()
519+
if err != nil { t.Fatal(err) }
520+
pk1, sk1, err := dil.GenerateKey()
521+
if err != nil { t.Fatal(err) }
522+
523+
pk0b, _ := pk0.MarshalBinary()
524+
sk0b, _ := sk0.MarshalBinary()
525+
pk1b, _ := pk1.MarshalBinary()
526+
sk1b, _ := sk1.MarshalBinary()
527+
528+
copy(pair[0].dev.staticIdentity.mldsaPrivateKey[:], sk0b)
529+
copy(pair[1].dev.staticIdentity.mldsaPrivateKey[:], sk1b)
530+
531+
var peer0, peer1 *Peer
532+
for _, p := range pair[0].dev.peers.keyMap { peer0 = p; break }
533+
for _, p := range pair[1].dev.peers.keyMap { peer1 = p; break }
534+
if peer0 == nil || peer1 == nil {
535+
t.Fatal("não foi possível localizar peers para configurar MLDSA")
536+
}
537+
538+
copy(peer0.handshake.remoteMLDSAStatic[:], pk1b)
539+
copy(peer1.handshake.remoteMLDSAStatic[:], pk0b)
540+
}
541+
511542
func TestMLKEMKeyGeneration(t *testing.T) {
512543
pub, priv, err := GenerateQuantumKeyPair()
513544
if err != nil { t.Fatal(err) }
@@ -577,6 +608,20 @@ func TestNoiseHandshakeWithMLKEM(t *testing.T) {
577608
if err := devB.IpcSet(uapiCfg("public_key", hex.EncodeToString(peerA.handshake.remoteStatic[:]),
578609
"mlkem_public_key", hex.EncodeToString(pkAb))); err != nil { t.Fatal(err) }
579610

611+
dil := mode5.Scheme()
612+
pkAS, skAS, _ := dil.GenerateKey()
613+
pkBS, skBS, _ := dil.GenerateKey()
614+
pkASb, _ := pkAS.MarshalBinary()
615+
pkBSb, _ := pkBS.MarshalBinary()
616+
skASb, _ := skAS.MarshalBinary()
617+
skBSb, _ := skBS.MarshalBinary()
618+
619+
copy(devA.staticIdentity.mldsaPrivateKey[:], skASb)
620+
copy(devB.staticIdentity.mldsaPrivateKey[:], skBSb)
621+
622+
copy(peerB.handshake.remoteMLDSAStatic[:], pkBSb)
623+
copy(peerA.handshake.remoteMLDSAStatic[:], pkASb)
624+
580625
peerA.Start()
581626
peerB.Start()
582627

device/mldsa_test.go

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package device
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
"encoding/hex"
7+
8+
"github.com/cloudflare/circl/sign/dilithium/mode5"
9+
"github.com/cloudflare/circl/kem/kyber/kyber1024"
10+
)
11+
12+
func TestGenerateMLDSAKeyPair(t *testing.T) {
13+
pub, priv, err := GenerateMLDSAKeyPair()
14+
if err != nil {
15+
t.Fatalf("erro gerando MLDSA: %v", err)
16+
}
17+
if len(pub) != MLDSAPublicKeySize || len(priv) != MLDSAPrivateKeySize {
18+
t.Fatalf("tamanhos inválidos: pub=%d priv=%d", len(pub), len(priv))
19+
}
20+
s := mode5.Scheme()
21+
if _, err := s.UnmarshalBinaryPublicKey(pub); err != nil {
22+
t.Fatalf("publicKey inválida: %v", err)
23+
}
24+
if _, err := s.UnmarshalBinaryPrivateKey(priv); err != nil {
25+
t.Fatalf("privateKey inválida: %v", err)
26+
}
27+
}
28+
29+
func TestMLDSASignVerify(t *testing.T) {
30+
s := mode5.Scheme()
31+
pk, sk, err := s.GenerateKey()
32+
if err != nil {
33+
t.Fatalf("erro gerando par mldsa: %v", err)
34+
}
35+
msg := []byte("wireguard + mldsa test")
36+
sig := s.Sign(sk, msg, nil)
37+
38+
if !s.Verify(pk, msg, sig, nil) {
39+
t.Fatalf("assinatura MLDSA não verificou")
40+
}
41+
if s.Verify(pk, append(msg, 0x01), sig, nil) {
42+
t.Fatalf("assinatura deveria falhar em msg alterada")
43+
}
44+
}
45+
46+
func mustCopy(dst []byte, src []byte) {
47+
if len(dst) != len(src) { panic("tam inválido") }
48+
copy(dst, src)
49+
}
50+
51+
func TestHybridHandshakeWithMLDSASignature(t *testing.T) {
52+
dev1 := randDevice(t)
53+
dev2 := randDevice(t)
54+
defer dev1.Close()
55+
defer dev2.Close()
56+
57+
kyb := kyber1024.Scheme()
58+
pkK1, skK1, _ := kyb.GenerateKeyPair()
59+
pkK2, skK2, _ := kyb.GenerateKeyPair()
60+
pubK1, _ := pkK1.MarshalBinary()
61+
privK1, _ := skK1.MarshalBinary()
62+
pubK2, _ := pkK2.MarshalBinary()
63+
privK2, _ := skK2.MarshalBinary()
64+
65+
mldsa := mode5.Scheme()
66+
pkS1, skS1, _ := mldsa.GenerateKey()
67+
pkS2, skS2, _ := mldsa.GenerateKey()
68+
pubS1, _ := pkS1.MarshalBinary()
69+
privS1, _ := skS1.MarshalBinary()
70+
pubS2, _ := pkS2.MarshalBinary()
71+
privS2, _ := skS2.MarshalBinary()
72+
73+
mustCopy(dev1.staticIdentity.mlkemPrivateKey[:], privK1)
74+
mustCopy(dev2.staticIdentity.mlkemPrivateKey[:], privK2)
75+
mustCopy(dev1.staticIdentity.mldsaPrivateKey[:], privS1)
76+
mustCopy(dev2.staticIdentity.mldsaPrivateKey[:], privS2)
77+
78+
peer1, err := dev2.NewPeer(dev1.staticIdentity.privateKey.publicKey())
79+
if err != nil { t.Fatal(err) }
80+
peer2, err := dev1.NewPeer(dev2.staticIdentity.privateKey.publicKey())
81+
if err != nil { t.Fatal(err) }
82+
83+
mustCopy(peer1.handshake.remoteMLKEMStatic[:], pubK1)
84+
mustCopy(peer2.handshake.remoteMLKEMStatic[:], pubK2)
85+
mustCopy(peer1.handshake.remoteMLDSAStatic[:], pubS1)
86+
mustCopy(peer2.handshake.remoteMLDSAStatic[:], pubS2)
87+
88+
peer1.Start()
89+
peer2.Start()
90+
91+
init, err := dev1.CreateMessageInitiation(peer2)
92+
if err != nil {
93+
t.Fatalf("CreateMessageInitiation falhou: %v", err)
94+
}
95+
if p := dev2.ConsumeMessageInitiation(init); p == nil {
96+
t.Fatalf("ConsumeMessageInitiation falhou (assinatura/MLKEM?)")
97+
}
98+
99+
resp, err := dev2.CreateMessageResponse(peer1)
100+
if err != nil {
101+
t.Fatalf("CreateMessageResponse falhou: %v", err)
102+
}
103+
if p := dev1.ConsumeMessageResponse(resp); p == nil {
104+
t.Fatalf("ConsumeMessageResponse falhou")
105+
}
106+
107+
if err := peer1.BeginSymmetricSession(); err != nil {
108+
t.Fatalf("peer1.BeginSymmetricSession: %v", err)
109+
}
110+
if err := peer2.BeginSymmetricSession(); err != nil {
111+
t.Fatalf("peer2.BeginSymmetricSession: %v", err)
112+
}
113+
114+
key1 := peer1.keypairs.next.Load()
115+
key2 := peer2.keypairs.current
116+
plain := []byte("ok mldsa+mlkem+noise")
117+
var nonce [12]byte
118+
c := key1.send.Seal(nil, nonce[:], plain, nil)
119+
out, err := key2.receive.Open(nil, nonce[:], c, nil)
120+
if err != nil || !bytes.Equal(out, plain) {
121+
t.Fatalf("falha cifrar/decifrar: %v", err)
122+
}
123+
}
124+
125+
func TestHybridHandshake_MLDSAInvalidSignature(t *testing.T) {
126+
dev1 := randDevice(t)
127+
dev2 := randDevice(t)
128+
defer dev1.Close(); defer dev2.Close()
129+
130+
kyb := kyber1024.Scheme()
131+
pkK1, skK1, _ := kyb.GenerateKeyPair()
132+
pkK2, skK2, _ := kyb.GenerateKeyPair()
133+
pubK1, _ := pkK1.MarshalBinary()
134+
privK1, _ := skK1.MarshalBinary()
135+
pubK2, _ := pkK2.MarshalBinary()
136+
privK2, _ := skK2.MarshalBinary()
137+
mustCopy(dev1.staticIdentity.mlkemPrivateKey[:], privK1)
138+
mustCopy(dev2.staticIdentity.mlkemPrivateKey[:], privK2)
139+
140+
s := mode5.Scheme()
141+
pkGood, skGood, _ := s.GenerateKey()
142+
pkWrong, _, _ := s.GenerateKey()
143+
privGood, _ := skGood.MarshalBinary()
144+
pubGood, _ := pkGood.MarshalBinary()
145+
pubWrong, _ := pkWrong.MarshalBinary()
146+
mustCopy(dev1.staticIdentity.mldsaPrivateKey[:], privGood)
147+
148+
peer1, _ := dev2.NewPeer(dev1.staticIdentity.privateKey.publicKey())
149+
peer2, _ := dev1.NewPeer(dev2.staticIdentity.privateKey.publicKey())
150+
peer1.Start(); peer2.Start()
151+
mustCopy(peer1.handshake.remoteMLKEMStatic[:], pubK1)
152+
mustCopy(peer2.handshake.remoteMLKEMStatic[:], pubK2)
153+
154+
mustCopy(peer1.handshake.remoteMLDSAStatic[:], pubWrong)
155+
156+
init, err := dev1.CreateMessageInitiation(peer2)
157+
if err != nil {
158+
t.Fatalf("CreateMessageInitiation falhou: %v", err)
159+
}
160+
if p := dev2.ConsumeMessageInitiation(init); p != nil {
161+
t.Fatalf("assinatura inválida deveria falhar")
162+
}
163+
164+
mustCopy(peer1.handshake.remoteMLDSAStatic[:], pubGood)
165+
if p := dev2.ConsumeMessageInitiation(init); p == nil {
166+
t.Fatalf("deveria aceitar com a pública correta")
167+
}
168+
_ = hex.EncodeToString
169+
}

0 commit comments

Comments
 (0)