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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 07:47:21