《openssl 编程》之大数
11.1???介紹
????????????? 大數(shù)一般指的是位數(shù)很多的數(shù)。計(jì)算機(jī)表示的數(shù)的大小是有限的,精度也是有限的,它不能支持大數(shù)運(yùn)算。密碼學(xué)中采用了很多大數(shù)計(jì)算,為了讓計(jì)算機(jī)實(shí)現(xiàn)大數(shù)運(yùn)算,用戶需要定義自己的大數(shù)表示方式并及實(shí)現(xiàn)各種大數(shù)運(yùn)算。Openssl為我們提供了這些功能,主要用于非對(duì)稱算法。
11.2?? openssl大數(shù)表示
crypto/bn.h中定義了大數(shù)的表示方式,如下:
struct bignum_st
{
?????? BN_ULONG *d;
?????? int top;???
?????? int dmax;
?????? int neg;
?????? int flags;
};
各項(xiàng)意義如下:
d:BN_ULONG(應(yīng)系統(tǒng)而異,win32下為4個(gè)字節(jié))數(shù)組指針首地址,大數(shù)就存放在這里面,不過是倒放的。比如,用戶要存放的大數(shù)為12345678000(通過BN_bin2bn放入),則d的內(nèi)容如下:0x30 0x30 0x30 0x38 0x37 0x36 0x35 0x34 0x33 0x32 0x31;
top:用來(lái)指明大數(shù)占多少個(gè)BN_ULONG空間,上例中top為3。
dmax:d數(shù)組的大小。
neg:是否為負(fù)數(shù),如果為1,則是負(fù)數(shù),為0,則為正數(shù)。
flags:用于存放一些標(biāo)記,比如flags含有BN_FLG_STATIC_DATA時(shí),表明d的內(nèi)存是靜態(tài)分配的;含有BN_FLG_MALLOCED時(shí),d的內(nèi)存是動(dòng)態(tài)分配的。
11.3???大數(shù)函數(shù)
大數(shù)函數(shù)一般都能根據(jù)函數(shù)名字知道其實(shí)現(xiàn)的功能。下面簡(jiǎn)單介紹了幾個(gè)函數(shù)。
1)? BN_rand/BN_pseudo_rand
生成一個(gè)隨機(jī)的大數(shù)。
2) BN_rand_range/BN_pseudo_rand_range
生成隨機(jī)數(shù),但是給出了隨機(jī)數(shù)的范圍。
3) BN_dup
大數(shù)復(fù)制。
4)?? BN_generate_prime
生成素?cái)?shù)。
?????? 5)? int BN_add_word(BIGNUM *a, BN_ULONG w)
給大數(shù)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)
將內(nèi)存中的數(shù)據(jù)轉(zhuǎn)換為大數(shù),為內(nèi)存地址,len為數(shù)據(jù)長(zhǎng)度,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;
}
注意:輸入?yún)?shù)“242424ab”是asc碼,對(duì)應(yīng)的大數(shù)值為16進(jìn)制的0x3234323432346162
7)? int BN_bn2bin(const BIGNUM *a, unsigned char *to)
將大數(shù)轉(zhuǎn)換為內(nèi)存形式。輸入?yún)?shù)為大數(shù)a,to為輸出緩沖區(qū)地址,緩沖區(qū)需要預(yù)先分配,返回值為緩沖區(qū)的長(zhǎng)度。
示例:
#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;
}
本例的緩沖區(qū)分配有兩種方法:靜態(tài)分配和動(dòng)態(tài)分配。動(dòng)態(tài)分配時(shí),先調(diào)用
BN_num_bytes函數(shù)獲取大數(shù)對(duì)應(yīng)的緩沖區(qū)的大小。
8)? char *BN_bn2dec(const BIGNUM *a)
將大數(shù)轉(zhuǎn)換成整數(shù)字符串。返回值中存放整數(shù)字符串,它由內(nèi)部分配空間,用戶必須在外部用OPENSSL_free函數(shù)釋放該空間。
示例:
#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)
將大數(shù)轉(zhuǎn)換為十六進(jìn)制字符串。返回值為生成的十六進(jìn)制字符串,外部需要用OPENSSL_free函數(shù)釋放
示例:
#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;
}
輸出的結(jié)果為:323432346162
10)? BN_cmp
比較兩個(gè)大數(shù)。
11)BIGNUM *BN_mod_inverse(BIGNUM *in,? const BIGNUM *a,
const BIGNUM *n, BN_CTX *ctx)
計(jì)算ax=1(mod n)。
用戶使用openssl函數(shù)編程時(shí),一般用不著進(jìn)行大數(shù)運(yùn)算。BN_bin2bn、BN_hex2bn、BN_dec2bn、BN_bin2bn、BN_bn2bin、BN_bn2hex和BN_bn2dec比較常用。比如給定RSA密鑰的內(nèi)存形式,用戶可以調(diào)用BN_bin2bn來(lái)構(gòu)造RSA密鑰的大數(shù)元素來(lái)進(jìn)行RSA運(yùn)算,或者已經(jīng)生成了RSA密鑰,用戶調(diào)用BN_bn2bin將RSA各個(gè)元素導(dǎo)出到內(nèi)存中再寫入密鑰文件。
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
????????????? 加法運(yùn)算
????????????? #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???????????
????????????? 減法運(yùn)算
????????????? #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
????????????? 乘法運(yùn)算
????????????? #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
????????????? 除法運(yùn)算
????????????? #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
????????????? 平方運(yùn)算
????????????? #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
????????????? 次方運(yùn)算
????????????? #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;
????????????? }
總結(jié)
以上是生活随笔為你收集整理的《openssl 编程》之大数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《openssl 编程》之文本数据库
- 下一篇: 《openssl 编程》之数据压缩