GCM定义的GF(2¹²⁸)乘法实现问题求助
GF(2¹²⁸)域乘法实现问题排查
我正在实现NIST SP 800-38d文档6.3节的算法1,用于GCM定义下GF(2¹²⁸)域的乘法,但C#实现结果与BouncyCastle的BasicGcmMultiplier不符,无法定位问题,寻求帮助。
测试用例
- a =
acbef20579b4b8ebce889bac8732dad7 - b =
ed95f8e164bf3213febc740f0bd9c4af - 预期输出:
4DB870D37CB75FCB46097C36230D1612 - 我的输出:
B57DEFF66E5E0AC75DA46B601ED12E49
原实现代码
private static byte[] gf_mul_be(byte[] a, byte[] b) { var V = new byte[16]; b.CopyTo(V, 0); var Z = Enumerable.Repeat((byte)0, 16).ToArray(); // 0^128 var X = new byte[16]; a.CopyTo(X, 0); for (var i = 127; i >= 0; i--) { var j = i / 8; var k = i % 8; var xi = (X[j] >> (8-k-1)) & 1; if (xi == 1) { Z = Z.Zip(V, (z, v) => (byte)(z ^ v)).ToArray(); // Z XOR V } var lsbV = V[0] & 0x80; // LSBn is the rightmost n bits from LE bit representation as per spec; so for our BE representation, it's the leftmost LeftShiftByteArray(V); // left-shift because we have the bitstring is reverse order (MSB first) if (lsbV != 0) { V[15] ^= 0x87; // bit pattern 1000 0111 in last byte } } return Z; } private static void LeftShiftByteArray(byte[] bytes) // assumes bytes are in BE order { var carry = 0; for (var l = bytes.Length - 1; l >= 0; l--) { var byteCopy = bytes[l]; bytes[l] = (byte)(bytes[l] << 1); if (carry == 1) { bytes[l] = (byte)(bytes[l] | 0x01); } carry = (byteCopy & 0x80) >> 7; } }
问题分析与修正
原代码存在3个核心错误:
1. 比特索引计算错误
大端字节数组中,最高位字节在数组头部,最低位字节在数组尾部。原代码对X的比特位索引逻辑完全颠倒,导致错误选取X的位参与运算。
2. LSB判断与多项式异或位置错误
NIST算法中,V的LSB是比特串的最后一位(对应大端数组的最后一个字节最低位),原代码错误取了数组第一个字节的最高位;同时,不可约多项式x¹²⁸ + x⁷ + x² + x + 1对应的大端字节是0xE1,应异或到数组头部,而非尾部。
3. 移位函数逻辑错误
大端字节数组左移应从头部(最高字节)开始处理进位,原代码从尾部开始,实际实现的是右移逻辑。
修正后的代码
private static byte[] gf_mul_be(byte[] a, byte[] b) { byte[] V = new byte[16]; b.CopyTo(V, 0); byte[] Z = Enumerable.Repeat((byte)0, 16).ToArray(); byte[] X = new byte[16]; a.CopyTo(X, 0); for (int i = 127; i >= 0; i--) { // 大端存储下,比特i(0为LSB,127为MSB)对应的字节和位索引 int byteIndex = 15 - (i / 8); int bitPos = i % 8; int xi = (X[byteIndex] >> bitPos) & 1; if (xi == 1) { Z = Z.Zip(V, (z, v) => (byte)(z ^ v)).ToArray(); } // 取V的LSB(大端数组最后一个字节的最低位) int lsbV = V[15] & 0x01; LeftShiftByteArray(V); if (lsbV != 0) { // 异或不可约多项式对应的大端字节 V[0] ^= 0xE1; } } return Z; } private static void LeftShiftByteArray(byte[] bytes) // 大端字节数组左移一位 { int carry = 0; for (int l = 0; l < bytes.Length; l++) { int newCarry = (bytes[l] & 0x80) >> 7; bytes[l] = (byte)((bytes[l] << 1) | carry); carry = newCarry; } }
内容的提问来源于stack exchange,提问作者rabindra
相关产品推荐
相关产品推荐

