14

我正在将此行从 C++ 移植到 C#,而且我不是经验丰富的 C++ 程序员:

 unsigned int nSize = BN_num_bytes(this); 

在 .NET 中,我使用 System.Numerics.BigInteger

 BigInteger num = originalBigNumber;
 byte[] numAsBytes = num.ToByteArray();
 uint compactBitsRepresentation = 0;
 uint size2 = (uint)numAsBytes.Length;

我认为它们在内部的操作方式存在根本差异,因为如果 BigInt 等于,源的单元测试结果不匹配:

  • 0
  • 任何负数
  • 0x00123456

我对BN_num_bytes编辑:评论刚刚告诉我它是 BN_num_bits 的宏)一无所知

问题

你会验证这些关于代码的猜测吗:

  • 我需要移植BN_num_bytes一个宏((BN_num_bits(bn)+7)/8)(谢谢@WhozCraig)

  • 我需要端口BN_num_bitsfloor(log2(w))+1

那么,如果存在不计算前导字节和尾随字节的可能性,那么在大/小端机器上会发生什么?有关系吗?

基于Security.StackExchange 上的这些答案,并且我的应用程序不是性能关键,我可以使用 .NET 中的默认实现,而不使用可能已经实现类似解决方法的备用库。


编辑:到目前为止,我的实现看起来像这样,但我不确定评论中提到的“LookupTable”是什么。

   private static int BN_num_bytes(byte[] numAsBytes)
    {
        int bits = BN_num_bits(numAsBytes);
        return (bits + 7) / 8; 
    }

    private static int BN_num_bits(byte[] numAsBytes)
    {
        var log2 = Math.Log(numAsBytes.Length, 2);
        var floor = Math.Floor(log2);
        return (uint)floor + 1;
    }

编辑2:

经过一番搜索,我发现:

BN_num_bits 不返回给定 bignum 的有效位数,而是返回最高有效 1 位的位置,不一定是同一件事

虽然我仍然不知道它的来源是什么......

4

2 回答 2

8

BN_num_bits的手册页(OpenSSL 项目)说“基本上,除了零,它返回floor(log2(w))+1.”。所以这些是.Net 的BN_num_bytes和函数的正确实现。BN_num_bitsBigInteger

public static int BN_num_bytes(BigInteger number) {
    if (number == 0) {
        return 0;
    }
    return 1 + (int)Math.Floor(BigInteger.Log(BigInteger.Abs(number), 2)) / 8;
}

public static int BN_num_bits(BigInteger number) {
    if (number == 0) {
        return 0;
    }
    return 1 + (int)Math.Floor(BigInteger.Log(BigInteger.Abs(number), 2));
}

为了方便起见,您可能应该将它们更改为扩展方法。

您应该了解,这些函数测量表达给定整数所需的最小位/字节数。int声明为( ) 的变量System.Int32占用 4 个字节的内存,但您只需要 1 个字节(或 3 位)来表示整数 7。这是 BN_num_bytes 和 BN_num_bits 计算的 - 具体数字所需的最小存储大小。

您可以在官方 OpenSSL 存储库中找到函数的原始实现的源代码。

于 2013-03-09T19:58:48.790 回答
-2

将评论中的 WhozCraig 与解释 BN_num_bits 的链接结合起来:

http://www.openssl.org/docs/crypto/BN_num_bytes.html

你最终会得到这样的东西,它应该告诉你大量的字节:

public static int NumberOfBytes(BigInteger bigInt)
{
    if (bigInt == 0)
    {
        return 0; //you need to check what BN_num_bits actually does here as not clear from docs, probably returns 0
    }

    return (int)Math.Ceiling(BigInteger.Log(bigInt + 1, 2) + 7) / 8;
}
于 2013-03-09T19:30:42.140 回答