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;

}

《openssl 编程》之大数相关推荐

  1. openssl 编程。 证书制作

    首页 博客 学院 下载 GitChat TinyMind 论坛 问答 商城 VIP 活动 写博客 发Chat 登录注册 么刚的专栏 RSS订阅 原 openssl证书制作及编程 2010年07月29日 ...

  2. OpenSSL中的大数接口与基于其的自用RSA加密接口设计

    本文记录了初次接触OpenSSL中的大数模块,重温了RSA加密流程,使用OpenSSL的接口包装成自用RSA加密接口,并且利用自己的接口演示了Alice与Bob通过RSA加密进行通讯的一个示例. 概览 ...

  3. 《openssl 编程》之 DH

    第十九章DH 19.1  DH算法介绍 DH算法是W.Diffie和M.Hellman提出的.此算法是最早的公钥算法.它实质是一个通信双方进行密钥协商的协议:两个实体中的任何一个使用自己的私钥和另一实 ...

  4. OPENSSL编程 第二十章 椭圆曲线

    20.1  ECC介绍 椭圆曲线算法可以看作是定义在特殊集合下数的运算,满足一定的规则.椭圆曲线在如下两个域中定义:Fp域和F2m域. Fp域,素数域,p为素数: F2m域:特征为2的有限域,称之为二 ...

  5. 《openssl 编程》之 RSA(转)

    17.1  RSA介绍 RSA算法是一个广泛使用的公钥算法.其密钥包括公钥和私钥.它能用于数字签名.身份认证以及密钥交换.RSA密钥长度一般使用1024位或者更高.RSA密钥信息主要包括[1]: Ø  ...

  6. 《openssl 编程》之错误处理

    第十四章   错误处理 14.1  概述 程序设计时,一般通过函数的返回值来判断是否调用成功.设计良好的函数以及好的错误处理能帮助调用者快速找到错误原因.错误处理应该尽可能多的包含各种信息,包括: Ø ...

  7. 《openssl 编程》之数据压缩

    16.1 简介 数据压缩是将原有数据通过某种压缩算法计算得到相对数据量小的过程.这种过程是可逆的,即能通过压缩后的数据恢复出原数据.数据压缩能够节省存储空间,减轻网络负载. 在即需要加密又需要压缩的情 ...

  8. 《openssl 编程》之文本数据库

    第十章   文本数据库 10.1  概述 Openss实现了一个简单的文本数据库,它可以从文件读取数据和将数据写到文件中,并且可以根据关键字段来查询数据.Openssl的文本数据库供apps/目录下的 ...

  9. 《openssl编程》之配置文件

    第八章 配置文件 8.1 概述 Openssl采用自定义的配置文件来获取配置信息.Openssl的配置文件主要由如下内容组成: 注释信息,注释信息由#开头: 段信息,段信息由[xxx]来表示,其中xx ...

最新文章

  1. Android EditText的光标的显示与隐藏
  2. XSLT教程 [转]
  3. L0,L1,L2范数
  4. 阿里凑单算法首次公开!打包购商品挖掘系统解析
  5. mysql php释放内存_php mysqli_free_result()函数释放结果集
  6. js取iframe 上级页面_原生js获取iframe中dom元素--父子页面相互获取对方dom元素的方法...
  7. wireshark in text mode: tshark
  8. #C语言#重定义问题
  9. 程序发布出现: 服务器无法处理请求---无法生成临时类(result = 1)。 错误CS2001:未能找到源文件“C:\ Windows \ TEMP \ lph54vwf.0.cs”...
  10. 第二周冲刺第一天个人博客
  11. 看完左耳朵耗子的116篇文章,我给自己定了个5年技术规划
  12. Windows系统访问网络共享文件夹提示没有权限访问网络资源,登录失败:未授予用户XXX等--终极必杀技
  13. 个人独立开发的一款天气app
  14. 多台路由器堆叠_双网多网叠加教程
  15. 51单片机学习笔记之数码管1显示数字0以及使用蜂鸣器
  16. 36岁大数据人被中台问倒,没点架构思维,连面试都过不了?
  17. 更快更稳更高效--Ubuntu Kylin 20.04 Pro SP1 正式发布
  18. SSH、SFTP、FTP、Telnet、SCP、TFTP协议的原理
  19. 握奇携手北京一卡通推SD卡 发力移动支付市场
  20. HTML(2) 实现一个简单的注册页面

热门文章

  1. 类加载器-双亲委派-源码分析1
  2. 进化之路:故事从两个线程说起
  3. 元组-元组变量的循环遍历
  4. SpringCloud与子项目版本兼容说明
  5. php显示评委打分情况代码,评委打分表自动汇总计算得分
  6. Spring @Import源码解析
  7. undertale人物_「undertale」传说之下精美人物图包 (SansGaster篇)
  8. yii2 关掉php notice,yii2关闭错误提示
  9. Spring Boot 整合 Shiro
  10. 【译】无限滚动加载最佳实践