要使用BN_add,您需要三个BIGNUM 工件:您尝试添加的两个操作数和一个存储结果的位置。操作数的来源可能会有所不同,这取决于源数据的性质和其中可能的转换。应使用BN_new 获取结果。
下面是一个使用两个十进制数字字符串的简单示例:
#include <stdio.h>
#include <stdlib.h>
#include <openssl/bn.h>
#include <openssl/crypto.h>
int main()
{
const char n1[] = "12345678912345789123456789123456789";
const char n2[] = "12345678912345789123456789123456789";
BIGNUM *bn1 = NULL;
BN_dec2bn(&bn1, n1);
BIGNUM *bn2 = NULL;
BN_dec2bn(&bn2, n2);
BIGNUM *bn3 = BN_new();
BN_add(bn3, bn1, bn2);
char *n3 = BN_bn2dec(bn3);
printf("%s\n%s\n%s\n", n1, n2, n3);
OPENSSL_free(n3); // don't forget to free this.
BN_free(bn1);
BN_free(bn2);
BN_free(bn3);
return 0;
}
输出
12345678912345789123456789123456789
12345678912345789123456789123456789
24691357824691578246913578246913578
请注意,我们确保释放我们获取的所有内容,包括转换为十进制字符字符串的结果,根据BN_bn2dec 文档,必须使用OPENSSL_free 释放。
这不是唯一的方法,不同的方法高度依赖于源数据。例如,我们可以修改上面的程序,将两个 256 位数字从 big-endian 字节八位字节转换为BIGNUM。为此,我们可以使用BN_bin2bn。然而,其余代码看起来相似(除了一些必须释放的额外转换缓冲区)。
#include <stdio.h>
#include <stdlib.h>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/rand.h>
int main()
{
unsigned char n1[32];
unsigned char n2[32];
RAND_bytes(n1, sizeof n1);
RAND_bytes(n2, sizeof n2);
BIGNUM *bn1 = BN_bin2bn(n1, sizeof n1, NULL);
BIGNUM *bn2 = BN_bin2bn(n2, sizeof n2, NULL);
BIGNUM *bn3 = BN_new();
BN_add(bn3, bn1, bn2);
char *s1 = BN_bn2dec(bn1);
char *s2 = BN_bn2dec(bn2);
char *s3 = BN_bn2dec(bn3);
printf("%s\n%s\n%s\n", s1, s2, s3);
OPENSSL_free(s1);
OPENSSL_free(s2);
OPENSSL_free(s3);
BN_free(bn1);
BN_free(bn2);
BN_free(bn3);
return 0;
}
输出(显然不同)
12848991999079618356122471791635779303297173135339588614513279277444395635360
47516096440756489210553139954635811049213722081352926332729551875133172387567
60365088439836107566675611746271590352510895216692514947242831152577568022927
最后,一些操作利用上下文来执行操作。对于我们在这里执行的单次操作,它不会特别有益,但是大量的密码算法代码对大数执行许多复杂的操作。提供临时存储上下文来管理大量内存分配和释放是上下文的主要用途。
您将在下面看到一个示例,该示例生成两个 128 位数字作为随机 blob,然后将它们相乘以产生所需的结果。
#include <stdio.h>
#include <stdlib.h>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/rand.h>
int main()
{
unsigned char n1[16];
unsigned char n2[16];
RAND_bytes(n1, sizeof n1);
RAND_bytes(n2, sizeof n2);
BIGNUM *bn1 = BN_bin2bn(n1, sizeof n1, NULL);
BIGNUM *bn2 = BN_bin2bn(n2, sizeof n2, NULL);
BIGNUM *bn3 = BN_new();
// create context
BN_CTX *ctx = BN_CTX_new();
BN_mul(bn3, bn1, bn2, ctx);
BN_CTX_free(ctx);
char *s1 = BN_bn2dec(bn1);
char *s2 = BN_bn2dec(bn2);
char *s3 = BN_bn2dec(bn3);
printf("%s\n%s\n%s\n", s1, s2, s3);
OPENSSL_free(s1);
OPENSSL_free(s2);
OPENSSL_free(s3);
BN_free(bn1);
BN_free(bn2);
BN_free(bn3);
return 0;
}
输出(显然不同)
132784775043065614238831600062417274250
106732277254089889576391506780872414280
14172421425018434896232647200508450669828492339359021022467696136374376290000
有多种web sites,如果您有任何疑问,可以在其中验证上述产品是否准确;我意识到,与我们之前进行的简单加法运算相比,长期处理要麻烦得多。