c++ - 如何在 openssl 的 BIGNUM 中使用负数?

标签 c++ openssl bignum

我想要以下 Java 代码的 C++ 版本。

BigInteger x = new BigInteger("00afd72b5835ad22ea5d68279ffac0b6527c1ab0fb31f1e646f728d75cbd3ae65d", 16);
BigInteger y = x.multiply(BigInteger.valueOf(-1));

//prints y = ff5028d4a7ca52dd15a297d860053f49ad83e54f04ce0e19b908d728a342c519a3
System.out.println("y = " + new String(Hex.encode(y.toByteArray())));

这是我尝试的解决方案。

BIGNUM* x = BN_new();
BN_CTX* ctx = BN_CTX_new();
std::vector<unsigned char> xBytes = hexStringToBytes(“00afd72b5835ad22ea5d68279ffac0b6527c1ab0fb31f1e646f728d75cbd3ae65d");
BN_bin2bn(&xBytes[0], xBytes.size(), x);

BIGNUM* negative1 = BN_new();
std::vector<unsigned char> negative1Bytes = hexStringToBytes("ff");
BN_bin2bn(&negative1Bytes[0], negative1Bytes.size(), negative1);

BIGNUM* y = BN_new();
BN_mul(y, x, negative1, ctx);

char* yHex = BN_bn2hex(y);
std::string yStr(yHex);
//prints y = AF27542CDD7775C7730ABF785AC5F59C299E964A36BFF460B031AE85607DAB76A3
std::cout <<"y = " << yStr << std::endl;

(忽略大小写。)我做错了什么?如何让我的 C++ 代码输出正确的值“ff5028d4a7ca52dd15a297d860053f49ad83e54f04ce0e19b908d728a342c519a3”。我也尝试通过执行 BN_set_word(negative1, -1) 来设置 negative1,但这也给了我错误的答案。

最佳答案

BN_set_negative 函数设置一个负数。

The negative of afd72b5835ad22ea5d68279ffac0b6527c1ab0fb31f1e646f728d75cbd3ae65d is actually -afd72b5835ad22ea5d68279ffac0b6527c1ab0fb31f1e646f728d75cbd3ae65d , in the same way as -2 is the negative of 2.

ff5028d4a7ca52dd15a297d860053f49ad83e54f04ce0e19b908d728a342c519a3 是一个大的正数。

您在 Java 中看到这个数字的原因是 toByteArray 调用。 According to its documentation ,它选择整数字节的最小字段宽度,并且能够保存负数的二进制补码表示。

换句话说,通过对当前具有 1 个符号位和 256 个值位的数字使用 toByteArray 函数,您最终得到一个 264 位的字段宽度。但是,如果您的负数的第一个半字节是 7,而不是 a,那么(根据此文档 - 我实际上还没有尝试过)您将得到 256 - 位字段宽度输出(即 8028d4...,而不是 ff8028d4

您在代码中使用的前导 00 在 OpenSSL BN 中无关紧要。我不确定它在 BigInteger 中是否重要,尽管该构造函数的文档说“字符串表示形式包含一个可选的减号或加号,后跟指定基数中的一个或多个数字序列。”;所以它接受减号的事实表明,如果不存在减号,那么输入将被视为一个大的正数,即使它的 MSB 已设置。 (希望 Java 程序员能帮我理清这一段)。

请确保您清楚较大的负值与通过对该负值进行模块化运算而获得的较大正数之间的区别,例如 toByteArray 的输出


所以您的问题实际上是:Openssl BN 是否具有模拟 BigInteger.toByteArray() 行为的函数?

我不知道这样的函数是否存在(恕我直言,BN 库的文档相当糟糕,而且我从未听说过它在 OpenSSL 之外使用,尤其是在 C++ 程序中)。我希望它不会,因为 toByteArray 的行为有点奇怪;在任何情况下,所有 BN 输出函数似乎都使用符号幅度格式输出,而不是二进制补码格式。

但要复制该输出,您可以将 2^2562^264 添加到大负数,然后执行 BN_bn2hex 。在这种特殊情况下,添加 2^264,通常您必须测量正在存储的数字的当前位长度并将指数四舍五入到最接近的 8 的倍数。

或者您甚至可以输出符号幅度格式(使用 BN_bn2hexBN_bn2mpi),然后遍历反转每个半字节并修复开始!

注意。您想使用 OpenSSL BN 有什么特别的原因吗? There are many alternatives .

关于c++ - 如何在 openssl 的 BIGNUM 中使用负数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24836903/

相关文章:

c++/boost fusion句柄父类

ssl - 仅允许客户端使用组织 CA 签名的证书进行连接

javascript - javascript中如何处理大数字

c - OpenSSL C API : Certificate chain validation with CRL

linux - 如何向自签名 CA 证书文件添加注释?

c++ - 如何找到一个号码的日志?

c - 大数相加功能导致程序崩溃

c++ - cudaMemcpy 来托管设备分配的内存仍然不可能吗?

c++ - 源和错误运行时组件之间的依赖关系

c++ - 从它自己的虚拟方法间接销毁对象。这是一个定义的行为吗?