671 lines
20 KiB
Go
671 lines
20 KiB
Go
package noise
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/rand"
|
|
"encoding/binary"
|
|
"testing"
|
|
|
|
"github.com/go-i2p/go-i2p/lib/crypto"
|
|
"github.com/go-i2p/go-i2p/lib/transport/obfs"
|
|
|
|
"github.com/flynn/noise"
|
|
"github.com/samber/oops"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func (ns *NoiseSession) testEncryptPacket(plaintext []byte) (int, []byte, error) {
|
|
if ns.CipherState == nil {
|
|
return 0, nil, oops.Errorf("CipherState is nil")
|
|
}
|
|
|
|
// Encrypt the data
|
|
ciphertext, err := ns.CipherState.Encrypt(nil, nil, plaintext)
|
|
if err != nil {
|
|
log.Fatalf("unimplemented\nerror:%v\n", err)
|
|
}
|
|
|
|
// Prepend the length of the ciphertext as a 2-byte big-endian value
|
|
packetLength := uint16(len(ciphertext))
|
|
packet := make([]byte, 2+len(ciphertext))
|
|
binary.BigEndian.PutUint16(packet[:2], packetLength)
|
|
copy(packet[2:], ciphertext)
|
|
|
|
return len(packet), packet, nil
|
|
}
|
|
|
|
func (ns *NoiseSession) testPacketDeux(packet []byte) (int, []byte, error) {
|
|
if ns.CipherState == nil {
|
|
return 0, nil, oops.Errorf("CipherState is nil")
|
|
}
|
|
|
|
if len(packet) < 2 {
|
|
return 0, nil, oops.Errorf("Packet too short to contain length prefix")
|
|
}
|
|
|
|
// Extract the length prefix
|
|
packetLength := binary.BigEndian.Uint16(packet[:2])
|
|
|
|
if len(packet[2:]) < int(packetLength) {
|
|
return 0, nil, oops.Errorf("Packet data is shorter than indicated length")
|
|
}
|
|
|
|
ciphertext := packet[2 : 2+packetLength]
|
|
|
|
// Decrypt the data
|
|
plaintext, err := ns.CipherState.Decrypt(nil, nil, ciphertext)
|
|
if err != nil {
|
|
return 0, nil, err
|
|
}
|
|
|
|
return len(plaintext), plaintext, nil
|
|
}
|
|
|
|
func TestEncryptDecryptPacketOffline(t *testing.T) {
|
|
// Generate static keypairs
|
|
initiatorStatic, err := noise.DH25519.GenerateKeypair(rand.Reader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to generate initiator static keypair: %v", err)
|
|
}
|
|
responderStatic, err := noise.DH25519.GenerateKeypair(rand.Reader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to generate responder static keypair: %v", err)
|
|
}
|
|
|
|
pattern := noise.HandshakeXK
|
|
cipherSuite := noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256)
|
|
|
|
// Negotiation
|
|
negData := initNegotiationData(nil)
|
|
prologue := make([]byte, 2, uint16Size+len(negData))
|
|
binary.BigEndian.PutUint16(prologue, uint16(len(negData)))
|
|
prologue = append(prologue, negData...)
|
|
|
|
// Handshake
|
|
initiatorHS, err := noise.NewHandshakeState(noise.Config{
|
|
StaticKeypair: initiatorStatic,
|
|
Initiator: true,
|
|
Pattern: pattern,
|
|
CipherSuite: cipherSuite,
|
|
Prologue: prologue,
|
|
PeerStatic: responderStatic.Public, // Must set this
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Failed to create initiator handshake state: %v", err)
|
|
}
|
|
|
|
responderHS, err := noise.NewHandshakeState(noise.Config{
|
|
StaticKeypair: responderStatic,
|
|
Initiator: false,
|
|
Pattern: pattern,
|
|
CipherSuite: cipherSuite,
|
|
Prologue: prologue,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Failed to create responder handshake state: %v", err)
|
|
}
|
|
|
|
var (
|
|
initiatorSendCS *noise.CipherState
|
|
initiatorRecvCS *noise.CipherState
|
|
responderSendCS *noise.CipherState
|
|
responderRecvCS *noise.CipherState
|
|
)
|
|
|
|
// Simulate the handshake message exchange
|
|
|
|
// Message 1: Initiator -> Responder
|
|
msg1, cs0, cs1, err := initiatorHS.WriteMessage(nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("Initiator failed to write handshake message 1: %v", err)
|
|
}
|
|
if cs0 != nil || cs1 != nil {
|
|
t.Fatalf("Initiator should not have CipherStates after message 1")
|
|
}
|
|
|
|
// Responder processes message 1
|
|
_, cs0, cs1, err = responderHS.ReadMessage(nil, msg1)
|
|
if err != nil {
|
|
t.Fatalf("Responder failed to read handshake message 1: %v", err)
|
|
}
|
|
if cs0 != nil || cs1 != nil {
|
|
t.Fatalf("Responder should not have CipherStates after reading message 1")
|
|
}
|
|
|
|
// Responder writes message 2
|
|
msg2, cs0, cs1, err := responderHS.WriteMessage(nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("Responder failed to write handshake message 2: %v", err)
|
|
}
|
|
if cs0 != nil || cs1 != nil {
|
|
t.Fatalf("Responder should not have CipherStates after writing message 2")
|
|
}
|
|
|
|
// Initiator processes message 2
|
|
_, cs0, cs1, err = initiatorHS.ReadMessage(nil, msg2)
|
|
if err != nil {
|
|
t.Fatalf("Initiator failed to read handshake message 2: %v", err)
|
|
}
|
|
if cs0 != nil || cs1 != nil {
|
|
t.Fatalf("Initiator should not have CipherStates after reading message 2")
|
|
}
|
|
|
|
// Initiator writes message 3
|
|
msg3, cs0, cs1, err := initiatorHS.WriteMessage(nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("Initiator failed to write handshake message 3: %v", err)
|
|
}
|
|
if cs0 == nil || cs1 == nil {
|
|
t.Fatalf("Initiator did not receive CipherStates after writing message 3")
|
|
}
|
|
initiatorSendCS = cs0
|
|
initiatorRecvCS = cs1
|
|
|
|
// Responder processes message 3
|
|
_, cs0, cs1, err = responderHS.ReadMessage(nil, msg3)
|
|
if err != nil {
|
|
t.Fatalf("Responder failed to read handshake message 3: %v", err)
|
|
}
|
|
if cs0 == nil || cs1 == nil {
|
|
t.Fatalf("Responder did not receive CipherStates after reading message 3")
|
|
}
|
|
responderRecvCS = cs0
|
|
responderSendCS = cs1
|
|
|
|
// Now both parties have the CipherStates
|
|
|
|
// Initiator sends a message to Responder
|
|
initiatorSession := &NoiseSession{
|
|
CipherState: initiatorSendCS,
|
|
}
|
|
responderSession := &NoiseSession{
|
|
CipherState: responderRecvCS,
|
|
}
|
|
|
|
originalData := []byte("This is a test message.")
|
|
_, encryptedPacket, err := initiatorSession.encryptPacket(originalData)
|
|
if err != nil {
|
|
t.Fatalf("Encryption failed: %v", err)
|
|
}
|
|
|
|
_, decryptedData, err := responderSession.decryptPacket(encryptedPacket[2:])
|
|
if err != nil {
|
|
t.Fatalf("Decryption failed: %v", err)
|
|
}
|
|
|
|
assert.Equal(t, originalData, decryptedData, "Decrypted data does not match the original data")
|
|
|
|
// Responder sends a message to Initiator
|
|
responderSession = &NoiseSession{
|
|
CipherState: responderSendCS,
|
|
}
|
|
initiatorSession = &NoiseSession{
|
|
CipherState: initiatorRecvCS,
|
|
}
|
|
|
|
responseData := []byte("This is a response message.")
|
|
_, encryptedResponse, err := responderSession.encryptPacket(responseData)
|
|
if err != nil {
|
|
t.Fatalf("Responder encryption failed: %v", err)
|
|
}
|
|
|
|
_, decryptedResponse, err := initiatorSession.decryptPacket(encryptedResponse[2:])
|
|
if err != nil {
|
|
t.Fatalf("Initiator decryption failed: %v", err)
|
|
}
|
|
|
|
assert.Equal(t, responseData, decryptedResponse, "Decrypted response does not match original data")
|
|
}
|
|
|
|
func TestEncryptDecryptPacketObfsOffline(t *testing.T) {
|
|
// Simulate Bob's Router Hash (RH_B)
|
|
bobRouterHash := make([]byte, 32)
|
|
rand.Read(bobRouterHash)
|
|
|
|
// Simulate Bob's IV (ri.IV)
|
|
bobIV := make([]byte, 16)
|
|
rand.Read(bobIV)
|
|
|
|
// Create AES cipher block
|
|
aesBlock, err := aes.NewCipher(bobRouterHash)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create AES cipher block: %v", err)
|
|
}
|
|
|
|
// Create AES CBC encrypter and decrypter
|
|
aesEncrypter := cipher.NewCBCEncrypter(aesBlock, bobIV)
|
|
aesDecrypter := cipher.NewCBCDecrypter(aesBlock, bobIV)
|
|
|
|
// Generate static keypairs
|
|
initiatorStatic, err := noise.DH25519.GenerateKeypair(rand.Reader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to generate initiator static keypair: %v", err)
|
|
}
|
|
responderStatic, err := noise.DH25519.GenerateKeypair(rand.Reader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to generate responder static keypair: %v", err)
|
|
}
|
|
|
|
pattern := noise.HandshakeXK
|
|
cipherSuite := noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256)
|
|
|
|
// Negotiation
|
|
negData := initNegotiationData(nil)
|
|
prologue := make([]byte, 2, uint16Size+len(negData))
|
|
binary.BigEndian.PutUint16(prologue, uint16(len(negData)))
|
|
prologue = append(prologue, negData...)
|
|
|
|
// Alice's Handshake State
|
|
initiatorHS, err := noise.NewHandshakeState(noise.Config{
|
|
StaticKeypair: initiatorStatic,
|
|
Initiator: true,
|
|
Pattern: pattern,
|
|
CipherSuite: cipherSuite,
|
|
Prologue: prologue,
|
|
PeerStatic: responderStatic.Public, // Bob's static public key
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Failed to create initiator handshake state: %v", err)
|
|
}
|
|
|
|
// Bob's Handshake State
|
|
responderHS, err := noise.NewHandshakeState(noise.Config{
|
|
StaticKeypair: responderStatic,
|
|
Initiator: false,
|
|
Pattern: pattern,
|
|
CipherSuite: cipherSuite,
|
|
Prologue: prologue,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Failed to create responder handshake state: %v", err)
|
|
}
|
|
|
|
var (
|
|
initiatorSendCS *noise.CipherState
|
|
initiatorRecvCS *noise.CipherState
|
|
responderSendCS *noise.CipherState
|
|
responderRecvCS *noise.CipherState
|
|
)
|
|
|
|
// Simulate the handshake message exchange
|
|
|
|
// -------------------------------
|
|
// Message 1: Initiator -> Responder
|
|
// -------------------------------
|
|
|
|
// Alice writes message 1
|
|
msg1, cs0, cs1, err := initiatorHS.WriteMessage(nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("Initiator failed to write handshake message 1: %v", err)
|
|
}
|
|
if cs0 != nil || cs1 != nil {
|
|
t.Fatalf("Initiator should not have CipherStates after message 1")
|
|
}
|
|
|
|
// Encrypt Alice's ephemeral public key using AES-256-CBC
|
|
if len(msg1) < 32 {
|
|
t.Fatalf("Message 1 is too short to contain ephemeral public key")
|
|
}
|
|
aliceEphemeralPubKey := msg1[:32] // First 32 bytes
|
|
encryptedX := make([]byte, len(aliceEphemeralPubKey))
|
|
aesEncrypter.CryptBlocks(encryptedX, aliceEphemeralPubKey)
|
|
|
|
// Construct the modified message 1
|
|
fullMsg1 := append(encryptedX, msg1[32:]...)
|
|
|
|
// -------------------------------
|
|
// Responder processes message 1
|
|
// -------------------------------
|
|
|
|
// Extract encrypted ephemeral public key
|
|
encryptedXReceived := fullMsg1[:32]
|
|
// Decrypt the ephemeral public key
|
|
decryptedX := make([]byte, len(encryptedXReceived))
|
|
aesDecrypter.CryptBlocks(decryptedX, encryptedXReceived)
|
|
|
|
// Replace the encrypted ephemeral key with the decrypted one
|
|
modifiedMsg1 := append(decryptedX, fullMsg1[32:]...)
|
|
|
|
// Bob reads message 1
|
|
_, cs0, cs1, err = responderHS.ReadMessage(nil, modifiedMsg1)
|
|
if err != nil {
|
|
t.Fatalf("Responder failed to read handshake message 1: %v", err)
|
|
}
|
|
if cs0 != nil || cs1 != nil {
|
|
t.Fatalf("Responder should not have CipherStates after reading message 1")
|
|
}
|
|
|
|
// -------------------------------
|
|
// Message 2: Responder -> Initiator
|
|
// -------------------------------
|
|
|
|
// Bob writes message 2
|
|
msg2, cs0, cs1, err := responderHS.WriteMessage(nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("Responder failed to write handshake message 2: %v", err)
|
|
}
|
|
if cs0 != nil || cs1 != nil {
|
|
t.Fatalf("Responder should not have CipherStates after writing message 2")
|
|
}
|
|
|
|
// Encrypt Bob's ephemeral public key using AES-256-CBC
|
|
if len(msg2) < 32 {
|
|
t.Fatalf("Message 2 is too short to contain ephemeral public key")
|
|
}
|
|
bobEphemeralPubKey := msg2[:32] // First 32 bytes
|
|
encryptedY := make([]byte, len(bobEphemeralPubKey))
|
|
aesEncrypter.CryptBlocks(encryptedY, bobEphemeralPubKey)
|
|
|
|
// Construct the modified message 2
|
|
fullMsg2 := append(encryptedY, msg2[32:]...)
|
|
|
|
// -------------------------------
|
|
// Initiator processes message 2
|
|
// -------------------------------
|
|
|
|
// Extract encrypted ephemeral public key
|
|
encryptedYReceived := fullMsg2[:32]
|
|
// Decrypt the ephemeral public key
|
|
decryptedY := make([]byte, len(encryptedYReceived))
|
|
aesDecrypter.CryptBlocks(decryptedY, encryptedYReceived)
|
|
|
|
// Replace the encrypted ephemeral key with the decrypted one
|
|
modifiedMsg2 := append(decryptedY, fullMsg2[32:]...)
|
|
|
|
// Alice reads message 2
|
|
_, cs0, cs1, err = initiatorHS.ReadMessage(nil, modifiedMsg2)
|
|
if err != nil {
|
|
t.Fatalf("Initiator failed to read handshake message 2: %v", err)
|
|
}
|
|
if cs0 != nil || cs1 != nil {
|
|
t.Fatalf("Initiator should not have CipherStates after reading message 2")
|
|
}
|
|
|
|
// -------------------------------
|
|
// Message 3: Initiator -> Responder
|
|
// -------------------------------
|
|
|
|
// Alice writes message 3
|
|
msg3, cs0, cs1, err := initiatorHS.WriteMessage(nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("Initiator failed to write handshake message 3: %v", err)
|
|
}
|
|
if cs0 == nil || cs1 == nil {
|
|
t.Fatalf("Initiator did not receive CipherStates after writing message 3")
|
|
}
|
|
initiatorSendCS = cs0
|
|
initiatorRecvCS = cs1
|
|
|
|
// Responder processes message 3
|
|
_, cs0, cs1, err = responderHS.ReadMessage(nil, msg3)
|
|
if err != nil {
|
|
t.Fatalf("Responder failed to read handshake message 3: %v", err)
|
|
}
|
|
if cs0 == nil || cs1 == nil {
|
|
t.Fatalf("Responder did not receive CipherStates after reading message 3")
|
|
}
|
|
responderRecvCS = cs0
|
|
responderSendCS = cs1
|
|
|
|
// Now both parties have the CipherStates
|
|
|
|
// Initiator sends a message to Responder
|
|
initiatorSession := &NoiseSession{
|
|
CipherState: initiatorSendCS,
|
|
}
|
|
responderSession := &NoiseSession{
|
|
CipherState: responderRecvCS,
|
|
}
|
|
|
|
originalData := []byte("This is a test message.")
|
|
_, encryptedPacket, err := initiatorSession.encryptPacket(originalData)
|
|
if err != nil {
|
|
t.Fatalf("Encryption failed: %v", err)
|
|
}
|
|
|
|
_, decryptedData, err := responderSession.decryptPacket(encryptedPacket[2:])
|
|
if err != nil {
|
|
t.Fatalf("Decryption failed: %v", err)
|
|
}
|
|
|
|
assert.Equal(t, originalData, decryptedData, "Decrypted data does not match the original data")
|
|
|
|
// Responder sends a message to Initiator
|
|
responderSession = &NoiseSession{
|
|
CipherState: responderSendCS,
|
|
}
|
|
initiatorSession = &NoiseSession{
|
|
CipherState: initiatorRecvCS,
|
|
}
|
|
|
|
responseData := []byte("This is a response message.")
|
|
_, encryptedResponse, err := responderSession.encryptPacket(responseData)
|
|
if err != nil {
|
|
t.Fatalf("Responder encryption failed: %v", err)
|
|
}
|
|
|
|
_, decryptedResponse, err := initiatorSession.decryptPacket(encryptedResponse[2:])
|
|
if err != nil {
|
|
t.Fatalf("Initiator decryption failed: %v", err)
|
|
}
|
|
|
|
assert.Equal(t, responseData, decryptedResponse, "Decrypted response does not match original data")
|
|
}
|
|
|
|
// TestEncryptDecryptPacketObfsOffline tests the encryption and decryption with AES obfuscation
|
|
func TestEncryptDecryptPacketObfsOfflineWithFunc(t *testing.T) {
|
|
// Simulate Bob's Router Hash (RH_B)
|
|
bobRouterHash := make([]byte, 32)
|
|
rand.Read(bobRouterHash)
|
|
|
|
// Simulate Bob's IV (ri.IV)
|
|
bobIV := make([]byte, 16)
|
|
rand.Read(bobIV)
|
|
|
|
// Create AES symmetric key
|
|
aesKey := &crypto.AESSymmetricKey{
|
|
Key: bobRouterHash,
|
|
IV: bobIV,
|
|
}
|
|
|
|
// Generate static keypairs
|
|
initiatorStatic, err := noise.DH25519.GenerateKeypair(rand.Reader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to generate initiator static keypair: %v", err)
|
|
}
|
|
responderStatic, err := noise.DH25519.GenerateKeypair(rand.Reader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to generate responder static keypair: %v", err)
|
|
}
|
|
|
|
pattern := noise.HandshakeXK
|
|
cipherSuite := noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashSHA256)
|
|
|
|
// Negotiation
|
|
negData := initNegotiationData(nil)
|
|
prologue := make([]byte, 2+len(negData))
|
|
binary.BigEndian.PutUint16(prologue, uint16(len(negData)))
|
|
copy(prologue[2:], negData)
|
|
|
|
// Alice's Handshake State
|
|
initiatorHS, err := noise.NewHandshakeState(noise.Config{
|
|
StaticKeypair: initiatorStatic,
|
|
Initiator: true,
|
|
Pattern: pattern,
|
|
CipherSuite: cipherSuite,
|
|
Prologue: prologue,
|
|
PeerStatic: responderStatic.Public, // Bob's static public key
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Failed to create initiator handshake state: %v", err)
|
|
}
|
|
|
|
// Bob's Handshake State
|
|
responderHS, err := noise.NewHandshakeState(noise.Config{
|
|
StaticKeypair: responderStatic,
|
|
Initiator: false,
|
|
Pattern: pattern,
|
|
CipherSuite: cipherSuite,
|
|
Prologue: prologue,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Failed to create responder handshake state: %v", err)
|
|
}
|
|
|
|
var (
|
|
initiatorSendCS *noise.CipherState
|
|
initiatorRecvCS *noise.CipherState
|
|
responderSendCS *noise.CipherState
|
|
responderRecvCS *noise.CipherState
|
|
)
|
|
|
|
// Simulate the handshake message exchange
|
|
|
|
// -------------------------------
|
|
// Message 1: Initiator -> Responder
|
|
// -------------------------------
|
|
|
|
// Alice writes message 1
|
|
msg1, cs0, cs1, err := initiatorHS.WriteMessage(nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("Initiator failed to write handshake message 1: %v", err)
|
|
}
|
|
if cs0 != nil || cs1 != nil {
|
|
t.Fatalf("Initiator should not have CipherStates after message 1")
|
|
}
|
|
|
|
// Obfuscate Alice's ephemeral public key in message 1
|
|
obfuscatedMsg1, err := obfs.ObfuscateEphemeralKey(msg1, aesKey)
|
|
if err != nil {
|
|
t.Fatalf("Failed to obfuscate message 1: %v", err)
|
|
}
|
|
|
|
// -------------------------------
|
|
// Responder processes message 1
|
|
// -------------------------------
|
|
|
|
// Deobfuscate Alice's ephemeral public key in message 1
|
|
deobfuscatedMsg1, err := obfs.DeobfuscateEphemeralKey(obfuscatedMsg1, aesKey)
|
|
if err != nil {
|
|
t.Fatalf("Failed to deobfuscate message 1: %v", err)
|
|
}
|
|
|
|
// Bob reads message 1
|
|
_, cs0, cs1, err = responderHS.ReadMessage(nil, deobfuscatedMsg1)
|
|
if err != nil {
|
|
t.Fatalf("Responder failed to read handshake message 1: %v", err)
|
|
}
|
|
if cs0 != nil || cs1 != nil {
|
|
t.Fatalf("Responder should not have CipherStates after reading message 1")
|
|
}
|
|
|
|
// -------------------------------
|
|
// Message 2: Responder -> Initiator
|
|
// -------------------------------
|
|
|
|
// Bob writes message 2
|
|
msg2, cs0, cs1, err := responderHS.WriteMessage(nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("Responder failed to write handshake message 2: %v", err)
|
|
}
|
|
if cs0 != nil || cs1 != nil {
|
|
t.Fatalf("Responder should not have CipherStates after writing message 2")
|
|
}
|
|
|
|
// Obfuscate Bob's ephemeral public key in message 2
|
|
obfuscatedMsg2, err := obfs.ObfuscateEphemeralKey(msg2, aesKey)
|
|
if err != nil {
|
|
t.Fatalf("Failed to obfuscate message 2: %v", err)
|
|
}
|
|
|
|
// -------------------------------
|
|
// Initiator processes message 2
|
|
// -------------------------------
|
|
|
|
// Deobfuscate Bob's ephemeral public key in message 2
|
|
deobfuscatedMsg2, err := obfs.DeobfuscateEphemeralKey(obfuscatedMsg2, aesKey)
|
|
if err != nil {
|
|
t.Fatalf("Failed to deobfuscate message 2: %v", err)
|
|
}
|
|
|
|
// Alice reads message 2
|
|
_, cs0, cs1, err = initiatorHS.ReadMessage(nil, deobfuscatedMsg2)
|
|
if err != nil {
|
|
t.Fatalf("Initiator failed to read handshake message 2: %v", err)
|
|
}
|
|
if cs0 != nil || cs1 != nil {
|
|
t.Fatalf("Initiator should not have CipherStates after reading message 2")
|
|
}
|
|
|
|
// -------------------------------
|
|
// Message 3: Initiator -> Responder
|
|
// -------------------------------
|
|
|
|
// Alice writes message 3
|
|
msg3, cs0, cs1, err := initiatorHS.WriteMessage(nil, nil)
|
|
if err != nil {
|
|
t.Fatalf("Initiator failed to write handshake message 3: %v", err)
|
|
}
|
|
if cs0 == nil || cs1 == nil {
|
|
t.Fatalf("Initiator did not receive CipherStates after writing message 3")
|
|
}
|
|
initiatorSendCS = cs0
|
|
initiatorRecvCS = cs1
|
|
|
|
// Responder processes message 3
|
|
_, cs0, cs1, err = responderHS.ReadMessage(nil, msg3)
|
|
if err != nil {
|
|
t.Fatalf("Responder failed to read handshake message 3: %v", err)
|
|
}
|
|
if cs0 == nil || cs1 == nil {
|
|
t.Fatalf("Responder did not receive CipherStates after reading message 3")
|
|
}
|
|
responderRecvCS = cs0
|
|
responderSendCS = cs1
|
|
|
|
// Now both parties have the CipherStates
|
|
|
|
// Initiator sends a message to Responder
|
|
initiatorSession := &NoiseSession{
|
|
CipherState: initiatorSendCS,
|
|
}
|
|
responderSession := &NoiseSession{
|
|
CipherState: responderRecvCS,
|
|
}
|
|
|
|
originalData := []byte("This is a test message.")
|
|
_, encryptedPacket, err := initiatorSession.testEncryptPacket(originalData)
|
|
if err != nil {
|
|
t.Fatalf("Encryption failed: %v", err)
|
|
}
|
|
|
|
_, decryptedData, err := responderSession.testPacketDeux(encryptedPacket)
|
|
if err != nil {
|
|
t.Fatalf("Decryption failed: %v", err)
|
|
}
|
|
|
|
assert.Equal(t, originalData, decryptedData, "Decrypted data does not match the original data")
|
|
|
|
// Responder sends a message to Initiator
|
|
responderSession = &NoiseSession{
|
|
CipherState: responderSendCS,
|
|
}
|
|
initiatorSession = &NoiseSession{
|
|
CipherState: initiatorRecvCS,
|
|
}
|
|
|
|
responseData := []byte("This is a response message.")
|
|
_, encryptedResponse, err := responderSession.testEncryptPacket(responseData)
|
|
if err != nil {
|
|
t.Fatalf("Responder encryption failed: %v", err)
|
|
}
|
|
|
|
_, decryptedResponse, err := initiatorSession.testPacketDeux(encryptedResponse)
|
|
if err != nil {
|
|
t.Fatalf("Initiator decryption failed: %v", err)
|
|
}
|
|
|
|
assert.Equal(t, responseData, decryptedResponse, "Decrypted response does not match original data")
|
|
}
|