《openssl 编程》之大数

11.1   介绍

              大数一般指的是位数很多的数。计算机表示的数的大小是有限的,精度也是有限的,它不能支持大数运算。密码学中采用了很多大数计算,为了让计算机实现大数运算,用户需要定义自己的大数表示方式并及实现各种大数运算。Openssl为我们提供了这些功能,主要用于非对称算法。

11.2   openssl大数表示

crypto/bn.h中定义了大数的表示方式,如下:

struct bignum_st

{

       BN_ULONG *d;

       int top;   

       int dmax;

       int neg;

       int flags;

};

各项意义如下:

d:BN_ULONG(应系统而异,win32下为4个字节)数组指针首地址,大数就存放在这里面,不过是倒放的。比如,用户要存放的大数为12345678000(通过BN_bin2bn放入),则d的内容如下:0x30 0x30 0x30 0x38 0x37 0x36 0x35 0x34 0x33 0x32 0x31;

top:用来指明大数占多少个BN_ULONG空间,上例中top为3。

dmax:d数组的大小。

neg:是否为负数,如果为1,则是负数,为0,则为正数。

flags:用于存放一些标记,比如flags含有BN_FLG_STATIC_DATA时,表明d的内存是静态分配的;含有BN_FLG_MALLOCED时,d的内存是动态分配的。

11.3   大数函数

大数函数一般都能根据函数名字知道其实现的功能。下面简单介绍了几个函数。

1)  BN_rand/BN_pseudo_rand

生成一个随机的大数。

2) BN_rand_range/BN_pseudo_rand_range

生成随机数,但是给出了随机数的范围。

3) BN_dup

大数复制。

4)   BN_generate_prime

生成素数。

       5)  int BN_add_word(BIGNUM *a, BN_ULONG w)

给大数a加上w,如果成功,返回1。

示例:

include <openssl/bn.h>

 

int     main()

{

int                  ret;

BIGNUM        *a;

BN_ULONG   w;

 

a=BN_new();

BN_one(a);

w=2685550010;

ret=BN_add_word(a,w);

if(ret!=1)

{

        printf(“a+=w err!\n”);

        BN_free(a);

        return -1;

}

BN_free(a);

return 0;

}

6)    BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)

将内存中的数据转换为大数,为内存地址,len为数据长度,ret为返回值。

示例:

#include <openssl/bn.h>

int main()

{

    BIGNUM *ret1,*ret2;

 

    ret1=BN_new();

    ret1=BN_bin2bn(“242424ab”,8, ret1);

    ret2=BN_bin2bn(“242424ab”,8,NULL);

    BN_free(ret1);

    BN_free(ret2);

    return 0;

}

注意:输入参数“242424ab”是asc码,对应的大数值为16进制的0x3234323432346162

7)  int BN_bn2bin(const BIGNUM *a, unsigned char *to)

将大数转换为内存形式。输入参数为大数a,to为输出缓冲区地址,缓冲区需要预先分配,返回值为缓冲区的长度。

示例:

#include <openssl/bn.h>

int    main()

{

       BIGNUM *ret1=NULL;

       char bin[50],*buf=NULL;

       int           len;

 

       ret1=BN_bin2bn(“242424ab”,8, NULL);

       len=BN_bn2bin(ret1,bin);

       len=BN_num_bytes(ret1);

       buf=malloc(len);

       len=BN_bn2bin(ret1,buf);

       free(buf);

       BN_free(ret1);

       return 0;

}

本例的缓冲区分配有两种方法:静态分配和动态分配。动态分配时,先调用

BN_num_bytes函数获取大数对应的缓冲区的大小。

8)  char *BN_bn2dec(const BIGNUM *a)

将大数转换成整数字符串。返回值中存放整数字符串,它由内部分配空间,用户必须在外部用OPENSSL_free函数释放该空间。

示例:

#include <openssl/bn.h>

#include <openssl/crypto.h>

int main()

{

    BIGNUM *ret1=NULL;

    char   *p=NULL;

    int    len=0;

 

    ret1=BN_bin2bn(“242424ab”,8, NULL);

    p=BN_bn2dec(ret1);

    printf(“%s\n”,p); /* 3617571600447332706 */

    BN_free(ret1);

OPENSSL_free(p);

    getchar();

    return 0;

}

    9) char *BN_bn2hex(const BIGNUM *a)

将大数转换为十六进制字符串。返回值为生成的十六进制字符串,外部需要用OPENSSL_free函数释放

示例:

#include <openssl/bn.h>

#include <openssl/crypto.h>

int main()

{

    BIGNUM *ret1=NULL;

    char   *p=NULL;

    int    len=0;

 

    ret1=BN_bin2bn(“242424ab”,8, NULL);

    p=BN_bn2hex(ret1);

    printf(“%s\n”,p);

    BN_free(ret1);

    OPENSSL_free(p);

    getchar();

    return 0;

}

输出的结果为:323432346162

10)  BN_cmp

比较两个大数。

11)BIGNUM *BN_mod_inverse(BIGNUM *in,  const BIGNUM *a,

const BIGNUM *n, BN_CTX *ctx)

计算ax=1(mod n)。

用户使用openssl函数编程时,一般用不着进行大数运算。BN_bin2bn、BN_hex2bn、BN_dec2bn、BN_bin2bn、BN_bn2bin、BN_bn2hex和BN_bn2dec比较常用。比如给定RSA密钥的内存形式,用户可以调用BN_bin2bn来构造RSA密钥的大数元素来进行RSA运算,或者已经生成了RSA密钥,用户调用BN_bn2bin将RSA各个元素导出到内存中再写入密钥文件。

11.4   使用示例

       1)示例1

include <openssl/bn.h>

       #include <string.h>

       #include <openssl/bio.h>

                           

       int    main()

       {

                     BIGNUM *bn;

                     BIO        *b;

                     char a[20];

                     int           ret;

                           

                     bn=BN_new();

                     strcpy(a,”32”);

                     ret=BN_hex2bn(&bn,a);

                     b=BIO_new(BIO_s_file());

                     ret=BIO_set_fp(b,stdout,BIO_NOCLOSE);

                     BIO_write(b,”aaa”,3);

                     BN_print(b,bn);

                     BN_free(bn);

                     return 0;

       }

 

       2)示例2

              加法运算

              #include <openssl/bn.h>

              #include <string.h>

              #include <openssl/bio.h>

                           

              int    main()

              {

                     BIGNUM *a,*b,*add;

                     BIO        *out;

                     char c[20],d[20];

                     int           ret;

                           

                     a=BN_new();

                     strcpy(c,”32”);

                     ret=BN_hex2bn(&a,c);

                     b=BN_new();

                     strcpy(d,”100”);

                     ret=BN_hex2bn(&b,d);

                     out=BIO_new(BIO_s_file());

                     ret=BIO_set_fp(out,stdout,BIO_NOCLOSE);

                     add=BN_new();

                     ret=BN_add(add,a,b);

                     if(ret!=1)

                     {

                            printf(“err.\n”);

                            return -1;

                     }

                     BIO_puts(out,”bn 0x32 + 0x100 = 0x”);

                     BN_print(out,add);

                     BIO_puts(out,”\n”);

                     BN_free(a);

                     BN_free(b);

                     BN_free(add);

                     BIO_free(out);

                     return 0;

              }

       3)  示例3           

              减法运算

              #include <openssl/bn.h>

              #include <string.h>

              #include <openssl/bio.h>

             

              int    main()

              {

                     BIGNUM *a,*b,*sub;

                     BIO        *out;

                     char c[20],d[20];

                     int           ret;

             

                     a=BN_new();

                     strcpy(c,”100”);

                     ret=BN_hex2bn(&a,c);

                     b=BN_new();

                     strcpy(d,”32”);

                     ret=BN_hex2bn(&b,d);

                     out=BIO_new(BIO_s_file());

                     ret=BIO_set_fp(out,stdout,BIO_NOCLOSE);

                     sub=BN_new();

                     ret=BN_sub(sub,a,b);

                     if(ret!=1)

                     {

                            printf(“err.\n”);

                            return -1;

                     }

                     BIO_puts(out,”bn 0x100 - 0x32 = 0x”);

                     BN_print(out,sub);

                     BIO_puts(out,”\n”);

                     BN_free(a);

                     BN_free(b);

                     BN_free(sub);

                     BIO_free(out);

                     return 0;

       }

       4)示例4

              乘法运算

              #include <openssl/bn.h>

              #include <string.h>

              #include <openssl/bio.h>

             

              int    main()

              {

                     BIGNUM *a,*b,*mul;

                     BN_CTX *ctx;

                     BIO        *out;

                     char c[20],d[20];

                     int           ret;

                    

                     ctx=BN_CTX_new();

                     a=BN_new();

                     strcpy(c,”32”);

                     ret=BN_hex2bn(&a,c);

                     b=BN_new();

                     strcpy(d,”100”);

                     ret=BN_hex2bn(&b,d);

                     out=BIO_new(BIO_s_file());

                     ret=BIO_set_fp(out,stdout,BIO_NOCLOSE);

                     mul=BN_new();

                     ret=BN_mul(mul,a,b,ctx);

                     if(ret!=1)

                     {

                            printf(“err.\n”);

                            return -1;

                     }

                     BIO_puts(out,”bn 0x32 * 0x100 = 0x”);

                     BN_print(out,mul);

                     BIO_puts(out,”\n”);

                     BN_free(a);

                     BN_free(b);

                     BN_free(mul);

                     BIO_free(out);

                     BN_CTX_free(ctx);

                     return 0;

              }

       5)示例5

              除法运算

              #include <openssl/bn.h>

              #include <string.h>

              #include <openssl/bio.h>

             

              int    main()

              {

                     BIGNUM *a,*b,*div,*rem;

                     BN_CTX *ctx;

                     BIO        *out;

                     char c[20],d[20];

                     int           ret;

                    

                     ctx=BN_CTX_new();

                     a=BN_new();

                     strcpy(c,”100”);

                     ret=BN_hex2bn(&a,c);

                     b=BN_new();

                     strcpy(d,”17”);

                     ret=BN_hex2bn(&b,d);

                     out=BIO_new(BIO_s_file());

                     ret=BIO_set_fp(out,stdout,BIO_NOCLOSE);

                     div=BN_new();

                     rem=BN_new();

                     ret=BN_div(div,rem,a,b,ctx);

                     if(ret!=1)

                     {

                            printf(“err.\n”);

                            return -1;

                     }

                     BIO_puts(out,”bn 0x100 / 0x17 =0x”);

                     BN_print(out,div);

                     BIO_puts(out,”\n”);

                     BIO_puts(out,”bn 0x100 % 0x17 =0x”);

                     BN_print(out,rem);

                     BIO_puts(out,”\n”);

                     BN_free(a);

                     BN_free(b);

                     BN_free(div);

                     BN_free(rem);

                     BIO_free(out);

                     BN_CTX_free(ctx);

                     return 0;

              }

       6)示例6

              平方运算

              #include <openssl/bn.h>

              #include <string.h>

              #include <openssl/bio.h>

                           

              int    main()

              {

                     BIGNUM *a,*sqr;

                     BN_CTX *ctx;

                     BIO        *out;

                     char c[20];

                     int           ret;

                    

                     ctx=BN_CTX_new();

                     a=BN_new();

                     strcpy(c,”100”);

                     ret=BN_hex2bn(&a,c);

                     sqr=BN_new();

                     out=BIO_new(BIO_s_file());

                     ret=BIO_set_fp(out,stdout,BIO_NOCLOSE);

                     ret=BN_sqr(sqr,a,ctx);

                     if(ret!=1)

                     {

                            printf(“err.\n”);

                            return -1;

                     }

                     BIO_puts(out,”bn 0x100 sqr  =0x”);

                     BN_print(out,sqr);

                     BIO_puts(out,”\n”);

                     BN_free(a);

                     BN_free(sqr);

                     BIO_free(out);

                     BN_CTX_free(ctx);

                     return 0;

              }           

       7)示例7

              次方运算

              #include <openssl/bn.h>

              #include <string.h>

              #include <openssl/bio.h>

                           

              int    main()

              {

                     BIGNUM *a,*exp,*b;

                     BN_CTX *ctx;

                     BIO        *out;

                     char c[20],d[20];

                     int           ret;

                    

                     ctx=BN_CTX_new();

                     a=BN_new();

                     strcpy(c,”100”);

                     ret=BN_hex2bn(&a,c);

                     b=BN_new();

                     strcpy(d,”3”);

                     ret=BN_hex2bn(&b,d);

                     exp=BN_new();

                     out=BIO_new(BIO_s_file());

                     ret=BIO_set_fp(out,stdout,BIO_NOCLOSE);

                     ret=BN_exp(exp,a,b,ctx);

                     if(ret!=1)

                     {

                            printf(“err.\n”);

                            return -1;

                     }

                     BIO_puts(out,”bn 0x100 exp 0x3  =0x”);

                     BN_print(out,exp);

                     BIO_puts(out,”\n”);

                     BN_free(a);

                     BN_free(b);

                     BN_free(exp);

                     BIO_free(out);

                     BN_CTX_free(ctx);

                     return 0;

              }

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值