|
| 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