c 编程 - 在 openssl 中使用 BIGNUM

c programming - working with BIGNUM in openssl

我正在尝试使用 c 中的 openssl 库将两个大数字相加,但我真的不知道如何使用它。

openssl 的文档 - BN_add() 在这里 https://www.openssl.org/docs/man3.0/man3/BN_add.html

//#include <openssl/bn.h>

//BN_add() adds a and b and places the result in r (r=a+b).
//r may be the same BIGNUM as a or b.

int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);

a & b 对我有什么期望?字节数组?字符串?

有人在 openssl 中使用过添加大数字并且有一个简单的例子吗?

要使用 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可以验证以上产品是否准确,如果您有任何疑问;我意识到长期处理比我们之前做的简单加法操作要麻烦得多。