You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中实现符合Z-Wave S0的AES-128 OFB加密?

Z-Wave S0规范AES-128 OFB加解密实现问题

测试数据

External Nonce: C7 16 D1 58 7E D2 9F 18
Internal Nonce: 68 DE E6 4A 88 A4 A3 E8
Security Key: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Decrypted Message: 00 98 06 2D C3 51 38 5D D8 4D 25 F5 ED 3B C5 B5 AA E2 36
Encrypted Message: 50 AE 49 A7 88 6C A9 BF E6 DA 36 A0 EF B8 CF D2 AA E2 C1

已知规则

  • 采用AES-128 OFB(输出反馈)模式对载荷加解密
  • IV = 发送方随机数 || 接收方随机数(即外部随机数与内部随机数拼接作为初始化向量)

我的C#实现代码

using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
using System;
using System.IO;
using System.Text;

namespace AesEncryption
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] externalNonce = new byte[] { 0xC7, 0x16, 0xD1, 0x58, 0x7E, 0xD2, 0x9F, 0x18 };
            byte[] internalNonce = new byte[] { 0x68, 0xDE, 0xE6, 0x4A, 0x88, 0xA4, 0xA3, 0xE8 };
            byte[] securityKey = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            byte[] unencryptedMessage = new byte[] { 0x00, 0x98, 0x06, 0x2D, 0xC3, 0x51, 0x38, 0x5D, 0xD8, 0x4D, 0x25, 0xF5, 0xED, 0x3B, 0xC5, 0xB5, 0xAA, 0xE2, 0x36 };
            byte[] initializationVector = InitializationVector(externalNonce, internalNonce);

            var cipher = CipherUtilities.GetCipher("AES/OFB/NoPadding");
            var keyParameter = new KeyParameter(securityKey);
            ICipherParameters cipherParameters = new ParametersWithIV(keyParameter, initializationVector);
            cipher.Init(true, cipherParameters);
            var encryptedMessage = cipher.DoFinal(unencryptedMessage);
            var encryptedMessageAsHexString = ToHexString(encryptedMessage); 
        }

        static byte[] InitializationVector(byte[] externalNonce, byte[] internalNonce)
        {
            byte[] iv = new byte[externalNonce.Length + internalNonce.Length];

            for (int i = 0; i < externalNonce.Length; i++)
                iv[i] = externalNonce[i];

            for (int i=0; i< internalNonce.Length; i++)
                iv[i + externalNonce.Length] = internalNonce[i];

            return iv;
        }

        public static string ToHexString(byte[] buffer)
        {
            StringBuilder stringBuilder = new StringBuilder(64);
            for (int i = 0; i < buffer.Length; i++)
            {
                stringBuilder.Append($"{buffer[i]:x2}");
                if (i < (buffer.Length - 1))
                    stringBuilder.Append(' ');
            }

            return stringBuilder.ToString();
        }

    }
}

问题

我的代码生成的加密结果是:

"6c 60 2b 6f 53 bb 36 74 3f 1a 50 dc fe db dd c7 d4 84 aa"

但正确结果应该是:

"50 AE 49 A7 88 6C A9 BF E6 DA 36 A0 EF B8 CF D2 AA E2 C1"

请问哪里出错了?


问题排查与解决

1. 字节序问题(核心原因)

Z-Wave S0规范中,Nonce的字节序为小端序,你当前代码直接按原始字节顺序拼接IV,未做字节反转处理,这是导致结果不符的关键。

例如:

  • External Nonce C7 16 D1 58 7E D2 9F 18 需要反转为 18 9F D2 7E 58 D1 16 C7
  • Internal Nonce 68 DE E6 4A 88 A4 A3 E8 需要反转为 E8 A3 A4 88 4A E6 DE 68

修改InitializationVector方法,对两个Nonce分别反转字节后再拼接:

static byte[] InitializationVector(byte[] externalNonce, byte[] internalNonce)
{
    // 反转Nonce的字节序
    Array.Reverse(externalNonce);
    Array.Reverse(internalNonce);
    
    byte[] iv = new byte[externalNonce.Length + internalNonce.Length];
    Buffer.BlockCopy(externalNonce, 0, iv, 0, externalNonce.Length);
    Buffer.BlockCopy(internalNonce, 0, iv, externalNonce.Length, internalNonce.Length);
    return iv;
}

2. 其他验证点

  • OFB模式段大小:BouncyCastle的"AES/OFB/NoPadding"默认是OFB-128,符合Z-Wave S0要求,无需调整。
  • 加密方向:cipher.Init(true, ...)表示加密模式,与测试场景匹配,无问题。

修改字节序后重新测试,即可得到正确的加密结果。

内容的提问来源于stack exchange,提问作者OlavT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 04:01:13