mirror of
https://dev.narayana.im/narayana/telegabber.git
synced 2026-08-05 04:07:07 +00:00
119 lines
3.2 KiB
Go
119 lines
3.2 KiB
Go
package omemo
|
|
|
|
import (
|
|
"bytes"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"dev.narayana.im/narayana/telegabber/e2ee/omemo/libsignal"
|
|
)
|
|
|
|
func TestEncryptOuterRoundTrip(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name string
|
|
version int
|
|
}{
|
|
{"legacy", libsignal.ProtocolVersionLegacy},
|
|
{"modern", libsignal.ProtocolVersionModern},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
plaintext := []byte("hello from telegram")
|
|
|
|
payload, err := EncryptOuter(tc.version, plaintext, "gateway@example.com")
|
|
if err != nil {
|
|
t.Fatalf("EncryptOuter: %v", err)
|
|
}
|
|
if len(payload.Ciphertext) == 0 {
|
|
t.Fatalf("expected non-empty ciphertext")
|
|
}
|
|
if tc.version == libsignal.ProtocolVersionLegacy && len(payload.IV) != legacyIVLen {
|
|
t.Fatalf("expected a %d-byte IV for legacy, got %d", legacyIVLen, len(payload.IV))
|
|
}
|
|
if tc.version == libsignal.ProtocolVersionModern && payload.IV != nil {
|
|
t.Fatalf("expected no IV for modern (receiver re-derives it), got %d bytes", len(payload.IV))
|
|
}
|
|
|
|
got, err := DecryptOuter(tc.version, payload)
|
|
if err != nil {
|
|
t.Fatalf("DecryptOuter: %v", err)
|
|
}
|
|
if !bytes.Equal(got, plaintext) {
|
|
t.Fatalf("round trip mismatch: got %q, want %q", got, plaintext)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestEncryptOuterTamperDetection(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name string
|
|
version int
|
|
}{
|
|
{"legacy", libsignal.ProtocolVersionLegacy},
|
|
{"modern", libsignal.ProtocolVersionModern},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
payload, err := EncryptOuter(tc.version, []byte("secret"), "gateway@example.com")
|
|
if err != nil {
|
|
t.Fatalf("EncryptOuter: %v", err)
|
|
}
|
|
|
|
tampered := *payload
|
|
tampered.Ciphertext = append([]byte{}, payload.Ciphertext...)
|
|
tampered.Ciphertext[0] ^= 0xFF
|
|
|
|
if _, err := DecryptOuter(tc.version, &tampered); err == nil {
|
|
t.Fatalf("expected DecryptOuter to reject tampered ciphertext")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSCERoundTrip(t *testing.T) {
|
|
plaintext := []byte("hello sce")
|
|
xmlBytes, err := sceEncode(plaintext, "alice@example.com")
|
|
if err != nil {
|
|
t.Fatalf("sceEncode: %v", err)
|
|
}
|
|
got, err := sceDecode(xmlBytes)
|
|
if err != nil {
|
|
t.Fatalf("sceDecode: %v", err)
|
|
}
|
|
if !bytes.Equal(got, plaintext) {
|
|
t.Fatalf("got %q, want %q", got, plaintext)
|
|
}
|
|
}
|
|
|
|
func TestWireEnvelopeEncodeDecode(t *testing.T) {
|
|
env := &WireEnvelope{
|
|
Version: libsignal.ProtocolVersionModern,
|
|
SenderSID: 12345,
|
|
Payload: []byte("ciphertext-bytes"),
|
|
Keys: []WireKey{
|
|
{RecipientJID: "bob@example.com", DeviceID: 1, IsPreKey: true, Ciphertext: []byte("key-ciphertext-1")},
|
|
{RecipientJID: "bob@example.com", DeviceID: 2, IsPreKey: false, Ciphertext: []byte("key-ciphertext-2")},
|
|
},
|
|
}
|
|
|
|
raw, err := env.Encode()
|
|
if err != nil {
|
|
t.Fatalf("Encode: %v", err)
|
|
}
|
|
|
|
got, err := DecodeWireEnvelope(raw)
|
|
if err != nil {
|
|
t.Fatalf("DecodeWireEnvelope: %v", err)
|
|
}
|
|
|
|
if got.Version != env.Version || got.SenderSID != env.SenderSID || !bytes.Equal(got.Payload, env.Payload) {
|
|
t.Fatalf("round trip mismatch: got %+v", got)
|
|
}
|
|
if len(got.Keys) != len(env.Keys) {
|
|
t.Fatalf("expected %d keys, got %d", len(env.Keys), len(got.Keys))
|
|
}
|
|
for i := range env.Keys {
|
|
if !reflect.DeepEqual(got.Keys[i], env.Keys[i]) {
|
|
t.Fatalf("key %d mismatch: got %+v, want %+v", i, got.Keys[i], env.Keys[i])
|
|
}
|
|
}
|
|
}
|