《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;
????????????? }
總結
以上是生活随笔為你收集整理的《openssl 编程》之大数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《openssl 编程》之文本数据库
- 下一篇: 《openssl 编程》之数据压缩