如何在C#中实现BN_num_bytes()(和BN_num_bits())?

时间:2021-07-01 16:52:08

I'm porting this line from C++ to C#, and I'm not an experienced C++ programmer:

我将这一行从C ++移植到C#,我不是一个经验丰富的C ++程序员:

 unsigned int nSize = BN_num_bytes(this); 

In .NET I'm using System.Numerics.BigInteger

在.NET中我使用的是System.Numerics.BigInteger

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

I think there is a fundamental difference in how they operate internally, since the sources' unit tests' results don't match if the BigInt equals:

我认为内部运作方式存在根本区别,因为如果BigInt等于:来源的单元测试结果不匹配:

  • 0
  • Any negative number
  • 任何负数

  • 0x00123456

I know literally nothing about BN_num_bytes (edit: the comments just told me that it's a macro for BN_num_bits).

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

Question

Would you verify these guesses about the code:

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

  • I need to port BN_num_bytes which is a macro for ((BN_num_bits(bn)+7)/8) (Thank you @WhozCraig)

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

  • I need to port BN_num_bits which is floor(log2(w))+1

    我需要移植BN_num_bits,它是floor(log2(w))+ 1

Then, if the possibility exists that leading and trailing bytes aren't counted, then what happens on Big/Little endian machines? Does it matter?

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

Based on these answers on Security.StackExchange, and that my application isn't performance critical, I may use the default implementation in .NET and not use an alternate library that may already implement a comparable workaround.

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


Edit: so far my implementation looks something like this, but I'm not sure what the "LookupTable" is as mentioned in the comments.

编辑:到目前为止,我的实现看起来像这样,但我不确定评论中提到的“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;
    }

Edit 2:

After some more searching, I found that:

经过一番搜索后,我发现:

BN_num_bits does not return the number of significant bits of a given bignum, but rather the position of the most significant 1 bit, which is not necessarily the same thing

BN_num_bits不返回给定bignum的有效位数,而是返回最重要的1位的位置,这不一定是同一个东西

Though I still don't know what the source of it looks like...

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

2 个解决方案

#1


8  

The man page (OpenSSL project) of BN_num_bits says that "Basically, except for a zero, it returns floor(log2(w))+1.". So these are the correct implementations of the BN_num_bytes and BN_num_bits functions for .Net's BigInteger.

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

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));
}

You should probably change these into extension methods for convenience.

为方便起见,您可能应将这些更改为扩展方法。

You should understand that these functions measure the minimum number of bits/bytes that are needed to express a given integer number. Variables declared as int (System.Int32) take 4 bytes of memory, but you only need 1 byte (or 3 bits) to express the integer number 7. This is what BN_num_bytes and BN_num_bits calculate - the minimum required storage size for a concrete number.

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

You can find the source code of the original implementations of the functions in the official OpenSSL repository.

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

#2


-2  

Combine what WhozCraig in the comments said with this link explaining BN_num_bits:

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

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

And you end up with something like this, which should tell you the significant number of bytes:

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

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;
}

#1


8  

The man page (OpenSSL project) of BN_num_bits says that "Basically, except for a zero, it returns floor(log2(w))+1.". So these are the correct implementations of the BN_num_bytes and BN_num_bits functions for .Net's BigInteger.

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

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));
}

You should probably change these into extension methods for convenience.

为方便起见,您可能应将这些更改为扩展方法。

You should understand that these functions measure the minimum number of bits/bytes that are needed to express a given integer number. Variables declared as int (System.Int32) take 4 bytes of memory, but you only need 1 byte (or 3 bits) to express the integer number 7. This is what BN_num_bytes and BN_num_bits calculate - the minimum required storage size for a concrete number.

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

You can find the source code of the original implementations of the functions in the official OpenSSL repository.

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

#2


-2  

Combine what WhozCraig in the comments said with this link explaining BN_num_bits:

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

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

And you end up with something like this, which should tell you the significant number of bytes:

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

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;
}