《openssl 编程》之大数

来源:互联网 发布:央视网络春晚 编辑:程序博客网 时间:2024/05/29 23:46

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;

              }

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孕妇被降职降薪怎么办 公司降职降薪员工不同意怎么办 企业因为经营不善要降薪该怎么办 调岗不降薪我该怎么办? 怀孕后强制调岗怎么办 有限公司法人变更后债务怎么办 有限公司法人跑路债务怎么办 网上买票身份信息待核验怎么办 微信买票身份核验失败怎么办 买高铁票待核验怎么办 网上购票身份待核验怎么办 b站稿件版权原因怎么办 已离职老板打电话说账有问题怎么办 开到应急刹车道怎么办 自动挡的车刹车失灵怎么办 自动挡的车如果刹车失灵怎么办 手动挡汽车刹车失灵怎么办 车辆没有年检出了交通事故怎么办 跟着大货车闯了红灯怎么办 在万家金服买的电子产品坏了怎么办 汽车被油笔画了怎么办? 挂到别人车跑了怎么办 浪琴手表保修卡掉了怎么办 事故车辆维修和报废怎么办 4.2货车拉缸了怎么办 工作中与同事发生矛盾怎么办 和领导关系闹僵怎么办 内倒窗户卡住了怎么办 支付宝存在安全风险怎么办 地铁车站空调坏了怎么办 面试防汛值班发生灾情你怎么办 怀孕上班路途太远怎么办 硕士错过校招应该怎么办 收银员收多了钱怎么办 商铺贷款批不了怎么办 铁路局的门面乱收房租怎么办 酒店夜审房费多过怎么办 夜审房价录多了怎么办 做工地拿不到钱怎么办 赢了官司拿不到钱怎么办 工地上拿不到钱怎么办