AX Principle 1 — predictable names over short names. The variable reader is ambiguous; frameReader states exactly what is being read. Co-Authored-By: Charon <charon@lethean.io>
95 lines
3.1 KiB
Go
95 lines
3.1 KiB
Go
package ueps
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"testing"
|
|
)
|
|
|
|
// builder := NewPacketBuilder(0x01, []byte("hello")); frame, _ := builder.MarshalAndSign(sharedSecret)
|
|
// packet, err := ReadAndVerify(bufio.NewReader(bytes.NewReader(frame)), sharedSecret)
|
|
// packet.Header.IntentID == 0x01; packet.Payload == []byte("hello")
|
|
func TestReader_ReadAndVerify_Good(t *testing.T) {
|
|
sharedSecret := []byte("test-shared-secret")
|
|
payload := []byte("hello world")
|
|
intentID := uint8(0x01)
|
|
|
|
builder := NewPacketBuilder(intentID, payload)
|
|
frame, err := builder.MarshalAndSign(sharedSecret)
|
|
if err != nil {
|
|
t.Fatalf("MarshalAndSign failed: %v", err)
|
|
}
|
|
|
|
frameReader := bufio.NewReader(bytes.NewReader(frame))
|
|
packet, err := ReadAndVerify(frameReader, sharedSecret)
|
|
|
|
if err != nil {
|
|
t.Fatalf("ReadAndVerify failed: %v", err)
|
|
}
|
|
if packet == nil {
|
|
t.Fatal("ReadAndVerify returned nil packet")
|
|
}
|
|
if packet.Header.IntentID != intentID {
|
|
t.Errorf("expected IntentID 0x%02x, got 0x%02x", intentID, packet.Header.IntentID)
|
|
}
|
|
if packet.Header.Version != 0x09 {
|
|
t.Errorf("expected Version 0x09, got 0x%02x", packet.Header.Version)
|
|
}
|
|
if !bytes.Equal(packet.Payload, payload) {
|
|
t.Errorf("expected Payload %q, got %q", payload, packet.Payload)
|
|
}
|
|
}
|
|
|
|
// frame, _ := NewPacketBuilder(0x02, []byte("sensitive data")).MarshalAndSign(sharedSecret)
|
|
// corrupted := append([]byte(nil), frame...); corrupted[len(corrupted)-1] ^= 0xFF
|
|
// packet, err := ReadAndVerify(bufio.NewReader(bytes.NewReader(corrupted)), sharedSecret)
|
|
// err == errIntegrityViolation (HMAC mismatch on tampered payload)
|
|
func TestReader_ReadAndVerify_Bad(t *testing.T) {
|
|
sharedSecret := []byte("test-shared-secret")
|
|
|
|
builder := NewPacketBuilder(0x02, []byte("sensitive data"))
|
|
frame, err := builder.MarshalAndSign(sharedSecret)
|
|
if err != nil {
|
|
t.Fatalf("MarshalAndSign failed: %v", err)
|
|
}
|
|
|
|
corrupted := make([]byte, len(frame))
|
|
copy(corrupted, frame)
|
|
corrupted[len(corrupted)-1] ^= 0xFF
|
|
|
|
frameReader := bufio.NewReader(bytes.NewReader(corrupted))
|
|
packet, err := ReadAndVerify(frameReader, sharedSecret)
|
|
|
|
if err == nil {
|
|
t.Fatal("expected errIntegrityViolation for corrupted frame, got nil")
|
|
}
|
|
if err != errIntegrityViolation {
|
|
t.Errorf("expected errIntegrityViolation, got %v", err)
|
|
}
|
|
if packet != nil {
|
|
t.Error("expected nil packet for corrupted frame")
|
|
}
|
|
}
|
|
|
|
// frameWithoutHMAC := []byte{TagVersion, 0x01, 0x09, TagPayload, 'x'}
|
|
// packet, err := ReadAndVerify(bufio.NewReader(bytes.NewReader(frameWithoutHMAC)), sharedSecret)
|
|
// err == errMissingHMAC (no 0x06 HMAC tag present in stream)
|
|
func TestReader_ReadAndVerify_Ugly(t *testing.T) {
|
|
frameWithoutHMAC := []byte{
|
|
TagVersion, 0x01, 0x09, // version TLV
|
|
TagPayload, 'x', // payload tag + data; no HMAC TLV precedes it
|
|
}
|
|
|
|
frameReader := bufio.NewReader(bytes.NewReader(frameWithoutHMAC))
|
|
packet, err := ReadAndVerify(frameReader, []byte("any-secret"))
|
|
|
|
if err == nil {
|
|
t.Fatal("expected errMissingHMAC for frame with no HMAC tag, got nil")
|
|
}
|
|
if err != errMissingHMAC {
|
|
t.Errorf("expected errMissingHMAC, got %v", err)
|
|
}
|
|
if packet != nil {
|
|
t.Error("expected nil packet when HMAC tag is absent")
|
|
}
|
|
}
|