я портирование этой строки из 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 равен:
Я буквально ничего не знаю о BN_num_bytes
(редактировать: комментарии только что сказали мне, что это макрос для BN_num_bits).
Вопрос
Не могли бы вы проверить эти предположения о коде:
Мне нужно портировать BN_num_bytes
который является макросом для ((BN_num_bits(bn)+7)/8)
(Спасибо, @WhozCraig)
Мне нужно портировать BN_num_bits
который floor(log2(w))+1
Тогда, если существует вероятность того, что ведущие и конечные байты не учитываются, то что происходит на машинах Big / Little endian? Это имеет значение?
На основе эти ответы на 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 бита, что необязательно является тем же самым
Хотя я до сих пор не знаю, как это выглядит …
справочная страница (Проект OpenSSL) BN_num_bits говорит, что «в основном, кроме нуля, он возвращает floor(log2(w))+1
. «.
Так что это правильные реализации BN_num_bytes
а также BN_num_bits
функции для .Net BigInteger
,
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.
Объедините то, что сказал 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;
}