深入解析:基于OpenSSL的RSA编程实践

更新:11-16 名人轶事 我要投稿 纠错 投诉

其实深入解析:基于OpenSSL的RSA编程实践的问题并不复杂,但是又很多的朋友都不太了解,因此呢,今天小编就来为大家分享深入解析:基于OpenSSL的RSA编程实践的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!

RSA密钥信息主要包括[1]:

n:模数

e:公钥索引

d:私钥索引

p:原始大素数

q:原始大素数

dmp1:e*dmp1=1 (mod (p-1))

dmq1:e*dmq1=1 (mod (q-1))

iqmp:q*iqmp=1 (mod p )

其中,公钥为n和e;私钥是n和d。实际应用中,一般采用公钥加密来协商密钥;签名一般采用私钥加密。

17.2 openssl的RSA实现

Openssl的RSA实现源代码位于crypto/rsa目录中。它实现了RSA PKCS1 标准。主要源码如下:

1)rsa.h

定义RSA数据结构和RSA_METHOD,定义RSA的各种函数。

2) rsa_asn1.c

实现了RSA 密钥(包括公钥和私钥)的DER 编码和解码。

3)rsa_chk.c

RSA 密钥检查。

4) rsa_eay.c

Openssl 实现的RSA_METHOD 作为其默认的RSA 计算实现。该文件不实现rsa_sign、rsa_verify 和rsa_keygen 回调函数。

5)rsa_err.c

RSA 错误处理。

6)rsa_gen.c

RSA密钥生成,如果RSA_METHOD中的rsa_keygen回调函数不为空则调用,否则调用其内部实现。

7)rsa_lib.c

主要实现了RSA操作的四个函数(公钥/私钥、加密/解密),它们都调用了RSA_METHOD中对应的回调函数。

8)rsa_none.c

实施了填充和去填充。

9)rsa_null.c

实现了一个空的RSA_METHOD。

10) rsa_oaep.c

实施了oaep 填充和反填充。

11) rsa_pk1。

实现了pkcs1 填充和反填充。

12)rsa_sign.c

实现了RSA签名和验证。

13)rsa_ssl.c

实施了ssl 填充。

14)rsa_x931.c

实施了填充和去填充。

17.3 RSA签名和验证过程

RSA签名过程如下:

1)用户数据汇总;

2)构建X509_SIG结构体并进行DER编码,包括汇总算法和汇总结果。

3) 将2)的结果填充为RSA密钥长度的字节数。例如,1024 位RSA 密钥必须填充128 个字节。具体填充方式由用户指定。

4) 用RSA私钥对3)的结果进行加密。

RSA_eay_private_encrypt函数实现了3)和4)过程。

RSA签名验证过程是上述过程的逆过程,如下:

1) 签名过程中使用RSA公钥对数据进行解密,得到2)的结果。

2) 从1) 的结果中删除填充。

3) 根据2)的结果得到汇总算法和汇总结果。

4) 根据3)中得到的汇总算法对原始数据进行汇总计算。

5) 在签名过程中比较4)和1)的结果。

RSA_eay_public_decrypt 实现1) 和2) 过程。

17.4 数据结构

RSA的主要数据结构定义在crypto/rsa/rsa.h中:

17.4.1 RSA_METHOD

结构体rsa_meth_st

{

const char *名称;

int (*rsa_pub_enc)(int flen,const unsigned char *from,unsigned char *to,RSA *rsa,int padding);

int (*rsa_pub_dec)(int flen,const unsigned char *from,unsigned char *to,RSA *rsa,int padding);

int (*rsa_priv_enc)(int flen,const unsigned char *from,unsigned char *to,RSA *rsa,int padding);

int (*rsa_priv_dec)(int flen,const unsigned char *from,unsigned char *to,RSA *rsa,int padding);

/* 其他函数*/

int (*rsa_sign)(int 类型,const unsigned char *m, unsigned int m_length,unsigned char *sigret, unsigned int *siglen, const RSA *rsa);

int (*rsa_verify)(int dtype,const unsigned char *m, unsigned int m_length,unsigned char *sigbuf, unsigned int siglen, const RSA *rsa);

int (*rsa_keygen)(RSA *rsa, int 位, BIGNUM *e, BN_GENCB *cb);

};

主要项目描述:

名称:RSA_METHOD 名称;

rsa_pub_enc:公钥加密函数,padding是它的填充方式,输入的数据不能太长,否则无法填充;

rsa_pub_dec:公钥解密函数,padding是去掉padding的方式,输入数据长度为RSA密钥长度的字节数;

rsa_priv_enc:私钥加密函数,padding是它的填充方式,输入的数据长度不能太长,否则无法填充;

rsa_priv_dec:私钥解密函数,padding是去掉padding的方式,输入数据长度为RSA密钥长度的字节数;

rsa_sign:签名函数;

rsa_verify:签名验证函数;

rsa_keygen:RSA密钥对生成函数。

用户可以实现自己的RSA_METHOD来替换openssl提供的默认方法。

17.4.2 RSA

RSA数据结构包含公钥/私钥信息(如果只有n和e,则表示公钥),定义如下:

结构体rsa_st

{

/* 其他*/

const RSA_METHOD *meth;

发动机*发动机;

大数*n;

大数*e;

大数*d;

大数*p;

BIGNUM *q;

BIGNUM *dmp1;

BIGNUM *dmq1;

BIGNUM *iqmp;

CRYPTO_EX_DATA ex_data;

整数参考文献;

/* 其他数据项*/

};

各种含义:

meth:RSA_METHOD结构体,指定该RSA密钥的各种操作函数的地址;

引擎:硬件引擎;

n、e、d、p、q、dmp1、dmq1、iqmp:RSA密钥的每个值;

ex_data:扩展数据结构,用于存储用户数据;

引用:RSA 结构引用的数量。

17.5 主要功能

1)RSA_check_key

检查RSA 密钥。

2)RSA_新

生成RSA 密钥结构并使用默认的rsa_pkcs1_eay_meth RSA_METHOD 方法。

3)RSA_free

释放RSA结构。

4) RSA *RSA_generate_key(int 位, unsigned long e_value,

void (*callback)(int,int,void *), void *cb_arg)

生成RSA密钥,bits为模位数,e_value为公钥指数e,回调函数由用户实现,用于干预密钥生成过程中的一些操作,可以为空。

5)RSA_get_default_method

获取默认的RSA_METHOD,即rsa_pkcs1_eay_meth。

6)RSA_get_ex_data

获取扩展数据。

7) RSA_get_方法

获取RSA 结构的RSA_METHOD。

8)RSA_padding_add_none

RSA_padding_add_PKCS1_OAEP

RSA_padding_add_PKCS1_type_1(私钥加密的填充)

RSA_padding_add_PKCS1_type_2(公钥加密的填充)

RSA_padding_add_SSLv23

多种灌装方式功能。

9)RSA_padding_check_none

RSA_padding_check_PKCS1_OAEP

RSA_padding_check_PKCS1_type_1

RSA_padding_check_PKCS1_type_2

RSA_padding_check_SSLv23

RSA_PKCS1_SSLeay

各种去除填充功能。

10) int RSA_print(BIO *bp, const RSA *x, int off)

将RSA信息输出到BIO中。 Off是BIO中输出信息的偏移量。例如,如果是屏幕BIO,则表示打印信息的位置与屏幕左边缘之间的距离。

11) int DSA_print_fp(FILE *fp, const DSA *x, int off)

将RSA信息输出到FILE中,off为输出偏移量。

12)RSA_public_解密

RSA 公钥解密。

13)RSA_public_加密

RSA 公钥加密。

14) RSA_set_default_method/RSA_set_method

在RSA 结构中设置方法。当用户实现RSA_METHOD时,调用该函数进行设置,以便RSA操作使用用户的方法。

15)RSA_set_ex_data

设置扩展数据。

16)RSA_sign

RSA 签名。

17)RSA_sign_ASN1_OCTET_STRING

另一种RSA签名不涉及摘要算法。它通过DER将输入数据编码为ASN1_OCTET_STRING,然后直接调用RSA_private_encrypt进行计算。

18)RSA_大小

获取RSA 密钥长度(以字节为单位)。

19)RSA_up_ref

添加对RSA 密钥的引用。

20)RSA_验证

RSA 认证。

21)RSA_verify_ASN1_OCTET_STRING

另一种不涉及摘要算法的RSA验证对应RSA_sign_ASN1_OCTET_STRING。

22)RSAPrivateKey_asn1_meth

获取RSA私钥的ASN1_METHOD,包括i2d、d2i、new和free函数地址。

23)RSAPrivateKey_dup

复制RSA 私钥。

24)RSAPublicKey_dup

复制RSA 公钥。

17.6 编程示例

17.6.1 密钥生成

包括

int main()

{

RSA*r;

整数位=512,ret;

无符号长e=RSA_3;

BIGNUM *bne;

r=RSA_generate_key(位,e,NULL,NULL);

RSA_print_fp(stdout,r,11);

RSA_free(r);

bne=BN_new();

ret=BN_set_word(bne,e);

r=RSA_new();

ret=RSA_generate_key_ex(r,位,bne,NULL);

if(ret!=1)

{

printf("RSA_generate_key_ex 错误!n");

返回-1;

}

RSA_free(r);

返回0;

}

阐明:

调用RSA_generate_key 和RSA_generate_key_ex 函数生成RSA 密钥,

调用RSA_print_fp打印密钥信息。

输出:

私钥:(512位)

模数:

00:d0:93:40:10:21:dd:c2:0b:6a:24:f1:b1:d5:b5:

77:79:ed:a9:a4:10:66:6e:88:d6:9b:0b:4c:91:7f:

23:6f:8f:0d:9e:9a:b6:7c:f9:47:fc:20:c2:12:e4:

b4:d7:ab:66:3e:73:d7:78:00:e6:5c:98:35:29:69:

c2:9b:c7:e2:c3

公共指数: 3 (0x3)

私人指数:

00:8b:0c:d5:60:16:93:d6:b2:46:c3:4b:cb:e3:ce:

4f:a6:9e:71:18:0a:ee:f4:5b:39:bc:b2:33:0b:aa:

17:9f:b3:7e:f0:0f:2a:24:b6:e4:73:40:ba:a0:65:

d3:19:0f:c5:b5:4f:59:51:e2:df:9c:83:47:da:8d:

84:0f:26:df:1b

素1:

00:f7:4c:fb:ed:32:a6:74:5c:2d:6c:c1:c5:fe:3a:

59:27:6a:53:5d:3e:73:49:f9:17:df:43:79:d4:d0:

46:2f:0d

素2:

00:d7:e9:88:0a:13:40:7c:f3:12:3d:60:85:f9:f7:

ba:96:44:29:74:3e:b9:4c:f8:bb:6a:1e:1b:a7:b4:

c7:65:0f

指数1:

00:a4:dd:fd:48:cc:6e:f8:3d:73:9d:d6:83:fe:d1:

90:c4:f1:8c:e8:d4:4c:db:fb:65:3f:82:51:38:8a:

d9:74:b3

指数2:

00:8f:f1:05:5c:0c:d5:a8:a2:0c:28:eb:03:fb:fa:

7c:64:2d:70:f8:29:d0:dd:fb:27:9c:14:12:6f:cd:

da:43:5f

系数:

00:d3:fa:ea:a0:21:7e:8a:e1:ab:c7:fd:e9:3d:cb:

5d:10:96:17:69:75:cd:71:d5:e5:07:26:93:e8:35:

ca:e3:49

17.6.2 RSA加解密操作

包括

包括

int main()

{

RSA*r;

int 位=1024,ret,len,flen,填充,i;

无符号长e=RSA_3;

BIGNUM *bne;

无符号字符*key,*p;

生物*b;

无符号字符from[500],to[500],out[500];

bne=BN_new();

ret=BN_set_word(bne,e);

r=RSA_new();

ret=RSA_generate_key_ex(r,位,bne,NULL);

if(ret!=1)

{

printf("RSA_generate_key_ex 错误!n");

返回-1;

}

/* 私钥i2d */

b=BIO_new(BIO_s_mem());

ret=i2d_RSAPrivateKey_bio(b,r);

键=malloc(1024);

len=BIO_read(b,键,1024);

BIO_free(b);

b=BIO_new_file("rsa.key","w");

ret=i2d_RSAPrivateKey_bio(b,r);

BIO_free(b);

/* 私钥d2i */

/* 公钥i2d */

/* 公钥d2i */

/* 私钥加密*/

flen=RSA_size(r);

printf("请选择私有enc 填充: n");

printf("1.RSA_PKCS1_PADDINGn");

printf("3.RSA_NO_PADDINGn");

printf("5.RSA_X931_PADDINGn");

scanf("%d",填充);

如果(填充==RSA_PKCS1_PADDING)

弗伦-=11;

否则如果(填充==RSA_X931_PADDING)

弗伦-=2;

否则如果(填充==RSA_NO_PADDING)

弗伦=弗伦;

别的

{

printf("rsa 不支持!n");

返回-1;

}

对于(i=0;i

memset(来自[i],i,1);

len=RSA_private_encrypt(flen,从,到,r,填充);

如果(长度=0)

{

printf("RSA_private_encrypt 错误!n");

返回-1;

}

len=RSA_public_decrypt(len,to,out,r,padding);

如果(长度=0)

{

printf("RSA_public_decrypt 错误!n");

返回-1;

}

如果(memcmp(来自,out,flen))

{

printf("错误!n");

返回-1;

}

/* */

printf("请选择公共编码

padding : n");               printf("1.RSA_PKCS1_PADDINGn");               printf("2.RSA_SSLV23_PADDINGn");               printf("3.RSA_NO_PADDINGn");               printf("4.RSA_PKCS1_OAEP_PADDINGn");               scanf("%d",&padding);               flen=RSA_size(r);               if(padding==RSA_PKCS1_PADDING)                      flen-=11;               else if(padding==RSA_SSLV23_PADDING)                      flen-=11;               else if(padding==RSA_X931_PADDING)                      flen-=2;               else if(padding==RSA_NO_PADDING)                      flen=flen;               else if(padding==RSA_PKCS1_OAEP_PADDING)                      flen=flen-2 * SHA_DIGEST_LENGTH-2 ;               else               {                      printf("rsa not surport !n");                      return -1;               }               for(i=0;i                      memset(&from[i],i+1,1);               len=RSA_public_encrypt(flen,from,to,r,padding);               if(len<=0)               {                      printf("RSA_public_encrypt err!n");                      return -1;               }               len=RSA_private_decrypt(len,to,out,r,padding);               if(len<=0)               {                      printf("RSA_private_decrypt err!n");                      return -1;               }               if(memcmp(from,out,flen))               {                      printf("err!n");                      return -1;               }               printf("test ok!n");               RSA_free(r);

              return 0;        }        上述程序中当采用公钥RSA_SSLV23_PADDING加密,用私钥RSA_SSLV23_PADDING解密时会报错,原因是openssl源代码错误:        rsa_ssl.c函数RSA_padding_check_SSLv23有:        if (k == -1)     /* err */        {        RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23,RSA_R_SSLV3_ROLLBACK_ATTACK);        return (-1);        }        修改为k!=-1即可。        各种padding对输入数据长度的要求:        私钥加密:        RSA_PKCS1_PADDING       RSA_size-11        RSA_NO_PADDING            RSA_size-0        RSA_X931_PADDING         RSA_size-2        公钥加密        RSA_PKCS1_PADDING       RSA_size-11        RSA_SSLV23_PADDING     RSA_size-11        RSA_X931_PADDING         RSA_size-2        RSA_NO_PADDING            RSA_size-0        RSA_PKCS1_OAEP_PADDING          RSA_size-2 * SHA_DIGEST_LENGTH-2    17.6.3签名与验证               签名运算:               #include               #include               #include               int    main()               {               int                         ret;               RSA                      *r;               int                         i,bits=1024,signlen,datalen,alg,nid;               unsigned long  e=RSA_3;               BIGNUM               *bne;               unsigned char data[100],signret[200];               bne=BN_new();               ret=BN_set_word(bne,e);               r=RSA_new();               ret=RSA_generate_key_ex(r,bits,bne,NULL);               if(ret!=1)               {                      printf("RSA_generate_key_ex err!n");                      return -1;               }               for(i=0;i<100;i++)                      memset(&data[i],i+1,1);               printf("please select digest alg: n");               printf("1.NID_md5n");               printf("2.NID_shan");               printf("3.NID_sha1n");               printf("4.NID_md5_sha1n");               scanf("%d",&alg);               if(alg==1)               {                      datalen=55;                      nid=NID_md5;               }               else if(alg==2)               {                      datalen=55;                      nid=NID_sha;               }               else if(alg==3)               {                      datalen=55;                      nid=NID_sha1;               }               else if(alg==4)               {                      datalen=36;                      nid=NID_md5_sha1;               }               ret=RSA_sign(nid,data,datalen,signret,&signlen,r);               if(ret!=1)               {                      printf("RSA_sign err!n");                      RSA_free(r);                      return -1;               }               ret=RSA_verify(nid,data,datalen,signret,signlen,r);               if(ret!=1)               {                      printf("RSA_verify err!n");                      RSA_free(r);                      return -1;               }               RSA_free(r);               printf("test ok!n");               return 0;        }        注意:本示例并不是真正的数据签名示例,因为没有做摘要计算。        ret=RSA_sign(nid,data,datalen,signret,&signlen,r)将需要运算的数据放入X509_ALGOR数据结构并将其DER编码,对编码结果做RSA_PKCS1_PADDING再进行私钥加密。

如果你还想了解更多这方面的信息,记得收藏关注本站。

用户评论

烟花巷陌

听起来很有挑战性!想了解一下RSA算法具体如何应用在openssl库里。

    有16位网友表示赞同!

凉话刺骨

最近在学习加密学,发现openssl是个很实用的工具

    有8位网友表示赞同!

龙卷风卷走爱情

我主要研究的是网络安全,这方面的确很需要用到RSA算法和openssl.

    有18位网友表示赞同!

淡写薰衣草的香

这样看来将来可以用openssl写一些安全的代码了!

    有15位网友表示赞同!

枫无痕

有没有资源可以学习一下openssl编程RSA的细节?

    有15位网友表示赞同!

金橙橙。-

感觉加密算法确实是一门很有意思的学问,能让人更深入地理解信息安全.

    有16位网友表示赞同!

葵雨

想问问RSA算法在实际应用中都有哪些场景?

    有7位网友表示赞同!

陌然淺笑

openssl这款库的安全性怎么样?

    有16位网友表示赞同!

你瞒我瞒

学习编程一直是我的兴趣爱好,这篇文章正好帮助我拓展一下知识面

    有15位网友表示赞同!

高冷低能儿

感觉用openssl编程来实现RSA算法一定能帮助提高代码安全性

    有12位网友表示赞同!

逾期不候

加密技术发展太快了,真是佩服那些研究者!

    有17位网友表示赞同!

屌国女农

我已经尝试过使用openssl的一些基础功能,想要进一步学习更高级的用法。

    有13位网友表示赞同!

凉凉凉”凉但是人心

这篇文章对我的编程思路很有启发作用!

    有10位网友表示赞同!

嘲笑!

RSA算法听起来复杂,但我相信只要努力就能掌握它的应用方法.

    有11位网友表示赞同!

古巷青灯

我很期待了解更多关于openssl和RSA算法的知识

    有16位网友表示赞同!

志平

希望将来有机会能够深入学习这个领域!

    有14位网友表示赞同!

迷路的男人

感谢分享这篇文章!内容很实用。

    有5位网友表示赞同!

留我一人

openssl确实是一个非常重要的工具,掌握它能让我们更好地保护信息安全

    有14位网友表示赞同!

南宫沐风

我需要在项目中使用RSA算法,这本书或许非常有用.

    有9位网友表示赞同!

【深入解析:基于OpenSSL的RSA编程实践】相关文章:

1.蛤蟆讨媳妇【哈尼族民间故事】

2.米颠拜石

3.王羲之临池学书

4.清代敢于创新的“浓墨宰相”——刘墉

5.“巧取豪夺”的由来--米芾逸事

6.荒唐洁癖 惜砚如身(米芾逸事)

7.拜石为兄--米芾逸事

8.郑板桥轶事十则

9.王献之被公主抢亲后的悲惨人生

10.史上真实张三丰:在棺材中竟神奇复活

上一篇:探索未知,感受世界广阔之美——探索之旅 下一篇:周勇:11月22日小雪时节,鹧鸪天·岁末小雪抒怀——雪景与雪意(第一篇)