如何在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
相关产品推荐
相关产品推荐

