删除所有测试文件
This commit is contained in:
@@ -1,215 +0,0 @@
|
||||
package mqtpp
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestBuildTextMessageServiceEnvelopeRoundTrip(t *testing.T) {
|
||||
key, err := ExpandPSK("AQ==")
|
||||
if err != nil {
|
||||
t.Fatalf("ExpandPSK() error = %v", err)
|
||||
}
|
||||
|
||||
raw, err := BuildTextMessageServiceEnvelope(TextMessageBuildOptions{
|
||||
PacketBuildOptions: PacketBuildOptions{
|
||||
FromNodeNum: 0x12345678,
|
||||
ToNodeNum: NodeNumBroadcast,
|
||||
PacketID: 0x87654321,
|
||||
ChannelID: "LongFast",
|
||||
GatewayID: "!12345678",
|
||||
PSK: key,
|
||||
Encrypt: true,
|
||||
ViaMQTT: true,
|
||||
},
|
||||
Text: "hello from bot",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("BuildTextMessageServiceEnvelope() error = %v", err)
|
||||
}
|
||||
|
||||
valid, _, record := MQTTPP("msh/2/e/LongFast/!12345678", raw, key, Options{})
|
||||
if !valid {
|
||||
t.Fatalf("MQTTPP() valid = false, record = %#v", record)
|
||||
}
|
||||
if record["type"] != "text_message" {
|
||||
t.Fatalf("record type = %v", record["type"])
|
||||
}
|
||||
if record["text"] != "hello from bot" {
|
||||
t.Fatalf("text = %v", record["text"])
|
||||
}
|
||||
if record["from_num"] != uint32(0x12345678) {
|
||||
t.Fatalf("from_num = %v", record["from_num"])
|
||||
}
|
||||
if record["packet_to_num"] != uint32(NodeNumBroadcast) {
|
||||
t.Fatalf("packet_to_num = %v", record["packet_to_num"])
|
||||
}
|
||||
if record["decrypt_success"] != true {
|
||||
t.Fatalf("decrypt_success = %v", record["decrypt_success"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildTextMessageServiceEnvelopeDirectRoundTrip(t *testing.T) {
|
||||
key, err := ExpandPSK("AQ==")
|
||||
if err != nil {
|
||||
t.Fatalf("ExpandPSK() error = %v", err)
|
||||
}
|
||||
|
||||
raw, err := BuildTextMessageServiceEnvelope(TextMessageBuildOptions{
|
||||
PacketBuildOptions: PacketBuildOptions{
|
||||
FromNodeNum: 0x12345678,
|
||||
ToNodeNum: 0x10203040,
|
||||
PacketID: 0x11111111,
|
||||
ChannelID: "LongFast",
|
||||
GatewayID: "!12345678",
|
||||
PSK: key,
|
||||
Encrypt: true,
|
||||
ViaMQTT: true,
|
||||
},
|
||||
Text: "direct hello",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("BuildTextMessageServiceEnvelope() error = %v", err)
|
||||
}
|
||||
|
||||
valid, _, record := MQTTPP("msh/2/e/LongFast/!12345678", raw, key, Options{})
|
||||
if !valid {
|
||||
t.Fatalf("MQTTPP() valid = false, record = %#v", record)
|
||||
}
|
||||
if record["text"] != "direct hello" {
|
||||
t.Fatalf("text = %v", record["text"])
|
||||
}
|
||||
if record["packet_to"] != "!10203040" {
|
||||
t.Fatalf("packet_to = %v", record["packet_to"])
|
||||
}
|
||||
if record["packet_to_num"] != uint32(0x10203040) {
|
||||
t.Fatalf("packet_to_num = %v", record["packet_to_num"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildNodeInfoServiceEnvelopeRoundTrip(t *testing.T) {
|
||||
key, err := ExpandPSK("AQ==")
|
||||
if err != nil {
|
||||
t.Fatalf("ExpandPSK() error = %v", err)
|
||||
}
|
||||
|
||||
raw, err := BuildNodeInfoServiceEnvelope(NodeInfoBuildOptions{
|
||||
PacketBuildOptions: PacketBuildOptions{
|
||||
FromNodeNum: 0x12345678,
|
||||
ToNodeNum: NodeNumBroadcast,
|
||||
PacketID: 0x22222222,
|
||||
ChannelID: "LongFast",
|
||||
GatewayID: "!12345678",
|
||||
PSK: key,
|
||||
Encrypt: true,
|
||||
ViaMQTT: true,
|
||||
},
|
||||
NodeID: "!12345678",
|
||||
LongName: "MQTT Bot",
|
||||
ShortName: "BT",
|
||||
HWModel: 255,
|
||||
Role: 0,
|
||||
IsLicensed: false,
|
||||
PublicKey: []byte{1, 2, 3},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("BuildNodeInfoServiceEnvelope() error = %v", err)
|
||||
}
|
||||
|
||||
valid, _, record := MQTTPP("msh/2/e/LongFast/!12345678", raw, key, Options{})
|
||||
if !valid {
|
||||
t.Fatalf("MQTTPP() valid = false, record = %#v", record)
|
||||
}
|
||||
if record["type"] != "nodeinfo" {
|
||||
t.Fatalf("record type = %v", record["type"])
|
||||
}
|
||||
if record["long_name"] != "MQTT Bot" {
|
||||
t.Fatalf("long_name = %v", record["long_name"])
|
||||
}
|
||||
if record["short_name"] != "BT" {
|
||||
t.Fatalf("short_name = %v", record["short_name"])
|
||||
}
|
||||
if record["hw_model"] != "PRIVATE_HW" {
|
||||
t.Fatalf("hw_model = %v", record["hw_model"])
|
||||
}
|
||||
if record["role"] != "CLIENT" {
|
||||
t.Fatalf("role = %v", record["role"])
|
||||
}
|
||||
if record["is_licensed"] != false {
|
||||
t.Fatalf("is_licensed = %v", record["is_licensed"])
|
||||
}
|
||||
if record["public_key"] != "010203" {
|
||||
t.Fatalf("public_key = %v", record["public_key"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildNodeInfoTruncatesNanopbStrings(t *testing.T) {
|
||||
key, err := ExpandPSK("AQ==")
|
||||
if err != nil {
|
||||
t.Fatalf("ExpandPSK() error = %v", err)
|
||||
}
|
||||
|
||||
raw, err := BuildNodeInfoServiceEnvelope(NodeInfoBuildOptions{
|
||||
PacketBuildOptions: PacketBuildOptions{FromNodeNum: 0x12345678, ToNodeNum: NodeNumBroadcast, PacketID: 0x33333333, ChannelID: "LongFast", GatewayID: "!12345678", PSK: key, Encrypt: true, ViaMQTT: true},
|
||||
NodeID: "!12345678",
|
||||
LongName: "这是一个非常非常非常非常长的机器人节点名称",
|
||||
ShortName: "机器人",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("BuildNodeInfoServiceEnvelope() error = %v", err)
|
||||
}
|
||||
valid, _, record := MQTTPP("msh/2/e/LongFast/!12345678", raw, key, Options{})
|
||||
if !valid {
|
||||
t.Fatalf("MQTTPP() valid = false, record = %#v", record)
|
||||
}
|
||||
if len([]byte(record["long_name"].(string))) > 40 {
|
||||
t.Fatalf("long_name byte length = %d", len([]byte(record["long_name"].(string))))
|
||||
}
|
||||
if len([]byte(record["short_name"].(string))) > 5 {
|
||||
t.Fatalf("short_name byte length = %d", len([]byte(record["short_name"].(string))))
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildAckServiceEnvelopeRoundTrip(t *testing.T) {
|
||||
key, err := ExpandPSK("AQ==")
|
||||
if err != nil {
|
||||
t.Fatalf("ExpandPSK: %v", err)
|
||||
}
|
||||
const requestID uint32 = 0xabcd1234
|
||||
raw, err := BuildAckServiceEnvelope(AckBuildOptions{
|
||||
PacketBuildOptions: PacketBuildOptions{
|
||||
FromNodeNum: 0x10101010,
|
||||
ToNodeNum: 0x20202020,
|
||||
PacketID: 0x30303030,
|
||||
ChannelID: "LongFast",
|
||||
GatewayID: "!10101010",
|
||||
PSK: key,
|
||||
Encrypt: true,
|
||||
ViaMQTT: true,
|
||||
},
|
||||
RequestID: requestID,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("BuildAckServiceEnvelope: %v", err)
|
||||
}
|
||||
valid, _, record := MQTTPP("msh/2/e/LongFast/!10101010", raw, key, Options{})
|
||||
if !valid {
|
||||
t.Fatalf("MQTTPP not valid: %#v", record)
|
||||
}
|
||||
if record["portnum"] != "ROUTING_APP" {
|
||||
t.Fatalf("portnum = %v", record["portnum"])
|
||||
}
|
||||
if record["type"] != "routing" {
|
||||
t.Fatalf("type = %v", record["type"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseNodeID(t *testing.T) {
|
||||
num, err := ParseNodeID("!1234abcd")
|
||||
if err != nil {
|
||||
t.Fatalf("ParseNodeID() error = %v", err)
|
||||
}
|
||||
if num != 0x1234abcd {
|
||||
t.Fatalf("num = %#x", num)
|
||||
}
|
||||
if NodeNumToID(num) != "!1234abcd" {
|
||||
t.Fatalf("NodeNumToID() = %s", NodeNumToID(num))
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package mqtpp
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"google.golang.org/protobuf/encoding/protowire"
|
||||
)
|
||||
|
||||
func TestMQTTPPEncryptedPacketDefaultRejected(t *testing.T) {
|
||||
raw := encryptedServiceEnvelopeTestPayload()
|
||||
valid, payload, record := MQTTPP("msh/test", raw, nil, Options{})
|
||||
if valid {
|
||||
t.Fatalf("valid = true, want false")
|
||||
}
|
||||
if payload != nil {
|
||||
t.Fatalf("payload = %v, want nil", payload)
|
||||
}
|
||||
if record["type"] != "encrypted_packet" {
|
||||
t.Fatalf("type = %v, want encrypted_packet", record["type"])
|
||||
}
|
||||
if record["error"] != "cannot be decrypted" {
|
||||
t.Fatalf("error = %v, want cannot be decrypted", record["error"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestMQTTPPEncryptedPacketAllowed(t *testing.T) {
|
||||
raw := encryptedServiceEnvelopeTestPayload()
|
||||
valid, payload, record := MQTTPP("msh/test", raw, nil, Options{AllowEncryptedForwarding: true})
|
||||
if !valid {
|
||||
t.Fatalf("valid = false, want true: %+v", record)
|
||||
}
|
||||
if string(payload) != string(raw) {
|
||||
t.Fatalf("payload = %v, want raw payload", payload)
|
||||
}
|
||||
if record["type"] != "encrypted_packet" {
|
||||
t.Fatalf("type = %v, want encrypted_packet", record["type"])
|
||||
}
|
||||
if record["error"] != nil {
|
||||
t.Fatalf("error = %v, want nil", record["error"])
|
||||
}
|
||||
}
|
||||
|
||||
func encryptedServiceEnvelopeTestPayload() []byte {
|
||||
packet := protowire.AppendTag(nil, 5, protowire.BytesType)
|
||||
packet = protowire.AppendBytes(packet, []byte{1, 2, 3, 4})
|
||||
envelope := protowire.AppendTag(nil, 1, protowire.BytesType)
|
||||
return protowire.AppendBytes(envelope, packet)
|
||||
}
|
||||
@@ -1,273 +0,0 @@
|
||||
package mqtpp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ecdh"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
|
||||
"google.golang.org/protobuf/encoding/protowire"
|
||||
)
|
||||
|
||||
func TestBuildPKITextMessageRoundTrip(t *testing.T) {
|
||||
curve := ecdh.X25519()
|
||||
senderPriv, err := curve.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatalf("generate sender key: %v", err)
|
||||
}
|
||||
recipientPriv, err := curve.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatalf("generate recipient key: %v", err)
|
||||
}
|
||||
|
||||
const text = "hello over PKI 你好"
|
||||
const fromNum uint32 = 0x12345678
|
||||
const toNum uint32 = 0xa1b2c3d4
|
||||
const packetID uint32 = 0xdeadbeef
|
||||
|
||||
raw, err := BuildPKITextMessageServiceEnvelope(PKITextMessageBuildOptions{
|
||||
FromNodeNum: fromNum,
|
||||
ToNodeNum: toNum,
|
||||
PacketID: packetID,
|
||||
GatewayID: NodeNumToID(fromNum),
|
||||
ViaMQTT: true,
|
||||
SenderPrivate: senderPriv.Bytes(),
|
||||
RecipientPub: recipientPriv.PublicKey().Bytes(),
|
||||
SenderPublic: senderPriv.PublicKey().Bytes(),
|
||||
Text: text,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("BuildPKITextMessageServiceEnvelope: %v", err)
|
||||
}
|
||||
|
||||
env, err := parseServiceEnvelope(raw)
|
||||
if err != nil {
|
||||
t.Fatalf("parseServiceEnvelope: %v", err)
|
||||
}
|
||||
if env.ChannelID != PKIChannelID {
|
||||
t.Fatalf("channel_id = %q want %q", env.ChannelID, PKIChannelID)
|
||||
}
|
||||
if env.GatewayID != NodeNumToID(fromNum) {
|
||||
t.Fatalf("gateway_id = %q", env.GatewayID)
|
||||
}
|
||||
pkt := env.Packet
|
||||
if pkt.From != fromNum || pkt.To != toNum || pkt.ID != packetID {
|
||||
t.Fatalf("packet header mismatch: %+v", pkt)
|
||||
}
|
||||
if !pkt.PKIEncrypted {
|
||||
t.Fatalf("pki_encrypted = false")
|
||||
}
|
||||
if !pkt.ViaMQTT {
|
||||
t.Fatalf("via_mqtt = false")
|
||||
}
|
||||
if pkt.Channel != 0 {
|
||||
t.Fatalf("channel = %d want 0", pkt.Channel)
|
||||
}
|
||||
if pkt.PayloadVariant != "encrypted" || len(pkt.Encrypted) <= pkcOverhead {
|
||||
t.Fatalf("encrypted payload missing: %+v", pkt)
|
||||
}
|
||||
|
||||
// 收件人用对端私钥 + 发件人公钥推导共享密钥并解密
|
||||
sharedKey, err := pkiSharedKey(recipientPriv.Bytes(), senderPriv.PublicKey().Bytes())
|
||||
if err != nil {
|
||||
t.Fatalf("pkiSharedKey: %v", err)
|
||||
}
|
||||
encryptedLen := len(pkt.Encrypted) - pkcOverhead
|
||||
ciphertext := pkt.Encrypted[:encryptedLen]
|
||||
auth := pkt.Encrypted[encryptedLen : encryptedLen+8]
|
||||
extraNonce := binary.LittleEndian.Uint32(pkt.Encrypted[encryptedLen+8:])
|
||||
plaintext, err := aesCCMDecrypt(sharedKey, pkiNonce(packetID, fromNum, extraNonce), ciphertext, auth)
|
||||
if err != nil {
|
||||
t.Fatalf("aesCCMDecrypt: %v", err)
|
||||
}
|
||||
data, err := parseDataPacket(plaintext)
|
||||
if err != nil {
|
||||
t.Fatalf("parseDataPacket: %v", err)
|
||||
}
|
||||
if data.Portnum != textMessageApp {
|
||||
t.Fatalf("portnum = %d", data.Portnum)
|
||||
}
|
||||
if string(data.Payload) != text {
|
||||
t.Fatalf("text = %q want %q", string(data.Payload), text)
|
||||
}
|
||||
|
||||
// 同样用 MQTTPP 解析路径:PKI 包对外应被识别为 encrypted_packet(无法解密),
|
||||
// 但用错的 PSK 不应误报“channel hash mismatch” 之外的奇怪错误。
|
||||
dummyPSK, _ := ExpandPSK("AQ==")
|
||||
_, _, record := MQTTPP("msh/2/e/PKI/!12345678", raw, dummyPSK, Options{AllowEncryptedForwarding: true})
|
||||
if record["channel_id"] != PKIChannelID {
|
||||
t.Fatalf("MQTTPP record channel_id = %v", record["channel_id"])
|
||||
}
|
||||
if record["pki_encrypted"] != true {
|
||||
t.Fatalf("pki_encrypted record = %v", record["pki_encrypted"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestPKINonceLayoutMatchesFirmware(t *testing.T) {
|
||||
// 复刻 firmware initNonce(fromNode, packetId, extraNonce) 期望的字节布局:
|
||||
// nonce[0..8) = packetId(uint64 LE)
|
||||
// nonce[4..8) 被 extraNonce(uint32 LE) 覆盖(当 extraNonce != 0)
|
||||
// nonce[8..12) = fromNode(uint32 LE)
|
||||
// nonce[12] = 0
|
||||
got := pkiNonce(0xaabbccdd, 0x11223344, 0x55667788)
|
||||
want := []byte{
|
||||
0xdd, 0xcc, 0xbb, 0xaa, // packetId low 4 bytes,未被 extraNonce 覆盖前
|
||||
0x88, 0x77, 0x66, 0x55, // extraNonce 覆盖 nonce[4..8)
|
||||
0x44, 0x33, 0x22, 0x11, // fromNode
|
||||
0x00,
|
||||
}
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Fatalf("pkiNonce = % x\nwant % x", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildPKITextMessageRejectsBroadcast(t *testing.T) {
|
||||
curve := ecdh.X25519()
|
||||
priv, _ := curve.GenerateKey(rand.Reader)
|
||||
pub, _ := curve.GenerateKey(rand.Reader)
|
||||
if _, err := BuildPKITextMessageServiceEnvelope(PKITextMessageBuildOptions{
|
||||
FromNodeNum: 0x1,
|
||||
ToNodeNum: NodeNumBroadcast,
|
||||
PacketID: 0x2,
|
||||
SenderPrivate: priv.Bytes(),
|
||||
RecipientPub: pub.PublicKey().Bytes(),
|
||||
Text: "hi",
|
||||
}); err == nil {
|
||||
t.Fatalf("expected error for broadcast destination")
|
||||
}
|
||||
}
|
||||
|
||||
// 确认 MeshPacket 中确实带上 pki_encrypted (tag 17) 与 public_key (tag 16)
|
||||
func TestBuildPKIMeshPacketTags(t *testing.T) {
|
||||
encrypted := []byte{0x01, 0x02, 0x03}
|
||||
pub := make([]byte, 32)
|
||||
for i := range pub {
|
||||
pub[i] = byte(i)
|
||||
}
|
||||
raw := buildPKIMeshPacket(0x11, 0x22, 0x33, true, encrypted, pub)
|
||||
tags := map[protowire.Number]bool{}
|
||||
if err := walkFields(raw, func(num protowire.Number, _ protowire.Type, _ any) error {
|
||||
tags[num] = true
|
||||
return nil
|
||||
}); err != nil {
|
||||
t.Fatalf("walkFields: %v", err)
|
||||
}
|
||||
for _, want := range []protowire.Number{1, 2, 5, 6, 14, 16, 17} {
|
||||
if !tags[want] {
|
||||
t.Fatalf("missing tag %d", want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 端到端:发送方构造 PKI 包,接收方通过 PKIKeyResolver 解密并还原文本消息记录。
|
||||
func TestMQTTPPDecryptsPKIWithResolver(t *testing.T) {
|
||||
curve := ecdh.X25519()
|
||||
senderPriv, _ := curve.GenerateKey(rand.Reader)
|
||||
recipientPriv, _ := curve.GenerateKey(rand.Reader)
|
||||
|
||||
const text = "hello PKI inbound"
|
||||
const fromNum uint32 = 0xaaaa1111
|
||||
const toNum uint32 = 0xbbbb2222
|
||||
const packetID uint32 = 0x77777777
|
||||
|
||||
raw, err := BuildPKITextMessageServiceEnvelope(PKITextMessageBuildOptions{
|
||||
FromNodeNum: fromNum,
|
||||
ToNodeNum: toNum,
|
||||
PacketID: packetID,
|
||||
GatewayID: NodeNumToID(fromNum),
|
||||
ViaMQTT: true,
|
||||
SenderPrivate: senderPriv.Bytes(),
|
||||
RecipientPub: recipientPriv.PublicKey().Bytes(),
|
||||
SenderPublic: senderPriv.PublicKey().Bytes(),
|
||||
Text: text,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("build: %v", err)
|
||||
}
|
||||
|
||||
resolver := func(to, from uint32) ([]byte, []byte, bool) {
|
||||
if to != toNum || from != fromNum {
|
||||
return nil, nil, false
|
||||
}
|
||||
return recipientPriv.Bytes(), senderPriv.PublicKey().Bytes(), true
|
||||
}
|
||||
dummyPSK, _ := ExpandPSK("AQ==")
|
||||
valid, _, record := MQTTPP("msh/2/e/PKI/!aaaa1111", raw, dummyPSK, Options{PKIKeyResolver: resolver})
|
||||
if !valid {
|
||||
t.Fatalf("MQTTPP not valid: %#v", record)
|
||||
}
|
||||
if record["type"] != "text_message" {
|
||||
t.Fatalf("type = %v, want text_message", record["type"])
|
||||
}
|
||||
if record["text"] != text {
|
||||
t.Fatalf("text = %v", record["text"])
|
||||
}
|
||||
if record["pki_encrypted"] != true {
|
||||
t.Fatalf("pki_encrypted = %v", record["pki_encrypted"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildPKIAckRoundTrip(t *testing.T) {
|
||||
curve := ecdh.X25519()
|
||||
botPriv, _ := curve.GenerateKey(rand.Reader)
|
||||
devicePriv, _ := curve.GenerateKey(rand.Reader)
|
||||
|
||||
const fromNum uint32 = 0x0000beef // bot
|
||||
const toNum uint32 = 0xfeed0000 // 原 device
|
||||
const ackPacketID uint32 = 0xaaaa5555
|
||||
const requestID uint32 = 0xdeadbeef
|
||||
|
||||
raw, err := BuildPKIAckServiceEnvelope(PKIAckBuildOptions{
|
||||
FromNodeNum: fromNum,
|
||||
ToNodeNum: toNum,
|
||||
PacketID: ackPacketID,
|
||||
RequestID: requestID,
|
||||
GatewayID: NodeNumToID(fromNum),
|
||||
ViaMQTT: true,
|
||||
SenderPrivate: botPriv.Bytes(),
|
||||
RecipientPub: devicePriv.PublicKey().Bytes(),
|
||||
SenderPublic: botPriv.PublicKey().Bytes(),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("BuildPKIAckServiceEnvelope: %v", err)
|
||||
}
|
||||
|
||||
// 设备侧解密
|
||||
env, err := parseServiceEnvelope(raw)
|
||||
if err != nil {
|
||||
t.Fatalf("parse: %v", err)
|
||||
}
|
||||
if env.ChannelID != PKIChannelID {
|
||||
t.Fatalf("channel_id = %q", env.ChannelID)
|
||||
}
|
||||
pkt := env.Packet
|
||||
if !pkt.PKIEncrypted || pkt.From != fromNum || pkt.To != toNum || pkt.ID != ackPacketID {
|
||||
t.Fatalf("ack header mismatch: %+v", pkt)
|
||||
}
|
||||
encryptedLen := len(pkt.Encrypted) - pkcOverhead
|
||||
cipher := pkt.Encrypted[:encryptedLen]
|
||||
auth := pkt.Encrypted[encryptedLen : encryptedLen+8]
|
||||
extraNonce := binary.LittleEndian.Uint32(pkt.Encrypted[encryptedLen+8:])
|
||||
sharedKey, err := pkiSharedKey(devicePriv.Bytes(), botPriv.PublicKey().Bytes())
|
||||
if err != nil {
|
||||
t.Fatalf("shared: %v", err)
|
||||
}
|
||||
plain, err := aesCCMDecrypt(sharedKey, pkiNonce(ackPacketID, fromNum, extraNonce), cipher, auth)
|
||||
if err != nil {
|
||||
t.Fatalf("decrypt: %v", err)
|
||||
}
|
||||
data, err := parseDataPacket(plain)
|
||||
if err != nil {
|
||||
t.Fatalf("data: %v", err)
|
||||
}
|
||||
if data.Portnum != routingApp {
|
||||
t.Fatalf("portnum = %d, want ROUTING_APP(%d)", data.Portnum, routingApp)
|
||||
}
|
||||
|
||||
// Routing payload 解析: 期望 oneof error_reason=NONE(0),即 wire 字节 0x18 0x00
|
||||
wantRouting := []byte{0x18, 0x00}
|
||||
if !bytes.Equal(data.Payload, wantRouting) {
|
||||
t.Fatalf("routing payload = % x, want % x", data.Payload, wantRouting)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user