关于openssl几个API的一点小收获
来源:互联网 发布:多益网络后 编辑:程序博客网 时间:2024/05/17 04:25
今天心血来潮突然想搞搞openssl了,趁着端午小假,刚好有空可以鼓捣孤岛自己喜欢的东西,出去东奔西跑的实在太造孽了,还是宅起来给自己充充电吧。下载openssl最新代码1.0.1g,修复了“心血漏洞”那个版本。编译安装那些小儿科的东西就不再浪费笔墨了,如果出现头文件或者库文件之类的错误,请在本人博客里寻找相关文章,应该主要集中在动态库那几篇博文。反正我在自己虚拟机里安装的时候是妥妥滴。
因为我主要对非对称加密的RSA算法比较感兴趣,网上最多的就是这么用的:
生成私钥文件(其中已经包含了公钥):[root@localhost release]#openssl genrsa -out plainPrv.key 1024
然后再从这个私钥文件里将公钥提取出来,保存到文件里:[root@localhost release]#openssl rsa -in plainPrv.key -pubout -out plainPub.key
RSA一般有两种应用场景:
1、公钥加密、私钥解密:这是数据安全通信领域最常见情形;
2、私钥加密、公钥解密:这主要用于数字签名。
两种方式,一通百通,本文只看第一种场景。
关于测试代码,网上到处都是,也都基本能用,我就先不摘抄了。大家问的最多的问题就是在读取公钥文件时,PEM_read_RSA_PUBKEY()函数和PEM_read_RSAPublicKEY()的疑惑。为什么读取私钥文件用的PEM_read_RSAPrivateKey(),针对上述openssl命令生成的公钥文件,在读取其内容时用对称的PEM_read_RSAPublicKEY()接口却会报错,必须要用PEM_read_RSA_PUBKEY()才可以。
其实,我们要是看看一两个文件内容就明白了:[root@localhost release]# cat plainPrv.key
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDlGVxzTDVhnC16SW+D0WG8hvm1wztmr0vBh2VK6CU7k90mdrCx
4by1URcZ6iS6KxomxSqWmK9g2C0iRd8xx7OyykBHKttjIx5Diq3wLXDP2qU4mjSI
vHP3MwgrOR2Jwa4mNr1veM2c1pyXn5xIfZs2IFnicMugj+0sXik1pLWwIwIDAQAB
AoGBAKoB5OomfmJ92/2oKxmdsjKN0xY/13++y6/EgrVQifipJG5bm4mVI01F7Ket
ai3AuHpWy+DPUy3BndSWFyfAsyatULiK3cJnIZumxmWP8G9odfO1pH/KcZB2Vi61
HcbioDuJRCcF3jpbGMun3lCwkdG/qVfsFmOElbzSbNMDbwkJAkEA/K9mOSKrP+lu
6bsIuD6/n2XQkz8XE2lPuPwKhVLX+ljXqRyxJZH0n+2EC8pUi694Q2Zhgn0uPdEl
KCYtlBaLXQJBAOgawH01Xc0r63+XVif6rLZfwJGBAP8921e2dRDFYhYLP3riflY8
xvFQsh4n7kbAXt4xZ3pDA/J1INnE01Rk8X8CQCmzyOslDZ4+qE9qzsWZlYZ5BzNF
9kj92GpvLk1SntJyVyVR1uqcbAL48BICEnH7Q53cB7vBbSBGpBs8Mcl+7wECQQCF
Dbjkze/sys2ggd+44WGa1n8sqhgpOYuA1656I7ybyGzmg+pKg2LEOS8yTE+yrVp0
4ztfggVEO1LOo59F1Ov/AkEApfUtgKHB4YCPy70syFaQoAWjiaxOWq/FLM7FBntP
ikz1X7gNsRkb4I/be15ZN8E/2Z0Q95FOpsgqw76Bi4Yynw==
-----END RSA PRIVATE KEY-----
[root@localhost release]# cat plainPub.key
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlGVxzTDVhnC16SW+D0WG8hvm1
wztmr0vBh2VK6CU7k90mdrCx4by1URcZ6iS6KxomxSqWmK9g2C0iRd8xx7OyykBH
KttjIx5Diq3wLXDP2qU4mjSIvHP3MwgrOR2Jwa4mNr1veM2c1pyXn5xIfZs2IFni
cMugj+0sXik1pLWwIwIDAQAB
-----END PUBLIC KEY-----
当我们在用PEM_read_RSAPublicKEY()读取公钥文件plainPub.key时报的错误是酱紫滴:3077879432:error:0906D06C:lib(9):func(109):reason(108):pem_lib.c:698:Expecting: RSA PUBLIC KEY
所以我就天真地将公钥文件头和尾分别改成“-----BEGIN RSA PUBLIC KEY-----”和“-----BEGIN RSA PUBLIC KEY-----”,理想很丰满,显示很骨感。实践证明openssl是不能那么轻易就被忽悠过去的。没办法,查看openssl源码发现,提取公钥文件时除了-pubout参数可以设置外,还有有个参数叫做-RSAPublicKey_out,但是命令行提示和man手册里居然没有任何提及。幸好我还会读C代码,所以提取公钥时我改用下面的命令:[root@localhost release]#openssl rsa -in plainPrv.key -RSAPublicKey_out -out plainPub.key
这样做完的结果是,首先公钥文件的内容有点变化:
[root@localhost test_openssl]# cat plainPub2.key
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAOUZXHNMNWGcLXpJb4PRYbyG+bXDO2avS8GHZUroJTuT3SZ2sLHhvLVR
FxnqJLorGibFKpaYr2DYLSJF3zHHs7LKQEcq22MjHkOKrfAtcM/apTiaNIi8c/cz
CCs5HYnBriY2vW94zZzWnJefnEh9mzYgWeJwy6CP7SxeKTWktbAjAgMBAAE=
-----END RSA PUBLIC KEY-----
其次,当我再用PEM_read_RSAPublicKEY()接口来读取公钥文件plainPub2.key时,居然成功了。说明RSA PUBLIC KEY和PUBLIC KEY的两种公钥文件其存储方式是不一样的,PEM_read_RSAPublicKEY()只能读取RSA PUBLIC KEY形式的公钥文件;而PEM_read_RSA_PUBKEY()只能读取PUBLIC KEY格式的公钥文件。由于本人密码学基础较薄弱,现在还不能说出两者的区别,请各位见谅,还望密码方面的大牛们予以点拨。演示代码如下:
如果开启RSAPUBKEY宏,则用PEM_read_RSA_PUBKEY()来读取公钥文件;否则用PEM_read_RSAPublicKey()读取:
[root@localhost release]#gcc -o pub rsatest.c -lcrypto -g -DRSAPUBKEY
[root@localhost release]#gcc -o nopub rsatest.c -lcrypto -g
测试结果如下:
实际应用中,出于安全考虑我们一般会对私钥文件加密。我们可以用如下的方式来重新生成经3DES加密后私钥文件:
[root@localhost release]#openssl genrsa -des3 -out cipherPrv.key 1024
这样生成的私钥文件使用3DES加过密的,看看内容就晓得和之前的有什么不同了。头部多了一些信息:Proc-Type和DEK-Info,猜想这肯定是某种加密信息(这TM不废话么),但是我看不懂,现阶段“会用”是首要问题:
上述加密私钥文件的口令是123456,分别提取RSA PUBLIC KEY和PUBLIC KEY格式的公钥文件:
[root@localhost release]# openssl rsa -in cipherPrv.key -pubout -out cipherPub.key
[root@localhost release]# openssl rsa -in cipherPrv.key -RSAPublicKey_out -out cipherPub2.key
在代码中我们需要通过下面的方式来读取经3DES加密处理后的私钥文件:
然后将tmp.c中第85行从:
if((p_rsa=PEM_read_RSAPrivateKey(file,NULL,NULL,NULL))==NULL){
替换成:
if((p_rsa=getPRV(path_key,"123456"))==NULL){
重新编译,运行后结果如下:
关于openssl有很多值得学习的地方,空了再慢慢研究。
因为我主要对非对称加密的RSA算法比较感兴趣,网上最多的就是这么用的:
生成私钥文件(其中已经包含了公钥):[root@localhost release]#openssl genrsa -out plainPrv.key 1024
然后再从这个私钥文件里将公钥提取出来,保存到文件里:[root@localhost release]#openssl rsa -in plainPrv.key -pubout -out plainPub.key
RSA一般有两种应用场景:
1、公钥加密、私钥解密:这是数据安全通信领域最常见情形;
2、私钥加密、公钥解密:这主要用于数字签名。
两种方式,一通百通,本文只看第一种场景。
关于测试代码,网上到处都是,也都基本能用,我就先不摘抄了。大家问的最多的问题就是在读取公钥文件时,PEM_read_RSA_PUBKEY()函数和PEM_read_RSAPublicKEY()的疑惑。为什么读取私钥文件用的PEM_read_RSAPrivateKey(),针对上述openssl命令生成的公钥文件,在读取其内容时用对称的PEM_read_RSAPublicKEY()接口却会报错,必须要用PEM_read_RSA_PUBKEY()才可以。
其实,我们要是看看一两个文件内容就明白了:[root@localhost release]# cat plainPrv.key
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDlGVxzTDVhnC16SW+D0WG8hvm1wztmr0vBh2VK6CU7k90mdrCx
4by1URcZ6iS6KxomxSqWmK9g2C0iRd8xx7OyykBHKttjIx5Diq3wLXDP2qU4mjSI
vHP3MwgrOR2Jwa4mNr1veM2c1pyXn5xIfZs2IFnicMugj+0sXik1pLWwIwIDAQAB
AoGBAKoB5OomfmJ92/2oKxmdsjKN0xY/13++y6/EgrVQifipJG5bm4mVI01F7Ket
ai3AuHpWy+DPUy3BndSWFyfAsyatULiK3cJnIZumxmWP8G9odfO1pH/KcZB2Vi61
HcbioDuJRCcF3jpbGMun3lCwkdG/qVfsFmOElbzSbNMDbwkJAkEA/K9mOSKrP+lu
6bsIuD6/n2XQkz8XE2lPuPwKhVLX+ljXqRyxJZH0n+2EC8pUi694Q2Zhgn0uPdEl
KCYtlBaLXQJBAOgawH01Xc0r63+XVif6rLZfwJGBAP8921e2dRDFYhYLP3riflY8
xvFQsh4n7kbAXt4xZ3pDA/J1INnE01Rk8X8CQCmzyOslDZ4+qE9qzsWZlYZ5BzNF
9kj92GpvLk1SntJyVyVR1uqcbAL48BICEnH7Q53cB7vBbSBGpBs8Mcl+7wECQQCF
Dbjkze/sys2ggd+44WGa1n8sqhgpOYuA1656I7ybyGzmg+pKg2LEOS8yTE+yrVp0
4ztfggVEO1LOo59F1Ov/AkEApfUtgKHB4YCPy70syFaQoAWjiaxOWq/FLM7FBntP
ikz1X7gNsRkb4I/be15ZN8E/2Z0Q95FOpsgqw76Bi4Yynw==
-----END RSA PRIVATE KEY-----
[root@localhost release]# cat plainPub.key
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlGVxzTDVhnC16SW+D0WG8hvm1
wztmr0vBh2VK6CU7k90mdrCx4by1URcZ6iS6KxomxSqWmK9g2C0iRd8xx7OyykBH
KttjIx5Diq3wLXDP2qU4mjSIvHP3MwgrOR2Jwa4mNr1veM2c1pyXn5xIfZs2IFni
cMugj+0sXik1pLWwIwIDAQAB
-----END PUBLIC KEY-----
当我们在用PEM_read_RSAPublicKEY()读取公钥文件plainPub.key时报的错误是酱紫滴:3077879432:error:0906D06C:lib(9):func(109):reason(108):pem_lib.c:698:Expecting: RSA PUBLIC KEY
所以我就天真地将公钥文件头和尾分别改成“-----BEGIN RSA PUBLIC KEY-----”和“-----BEGIN RSA PUBLIC KEY-----”,理想很丰满,显示很骨感。实践证明openssl是不能那么轻易就被忽悠过去的。没办法,查看openssl源码发现,提取公钥文件时除了-pubout参数可以设置外,还有有个参数叫做-RSAPublicKey_out,但是命令行提示和man手册里居然没有任何提及。幸好我还会读C代码,所以提取公钥时我改用下面的命令:[root@localhost release]#openssl rsa -in plainPrv.key -RSAPublicKey_out -out plainPub.key
这样做完的结果是,首先公钥文件的内容有点变化:
[root@localhost test_openssl]# cat plainPub2.key
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAOUZXHNMNWGcLXpJb4PRYbyG+bXDO2avS8GHZUroJTuT3SZ2sLHhvLVR
FxnqJLorGibFKpaYr2DYLSJF3zHHs7LKQEcq22MjHkOKrfAtcM/apTiaNIi8c/cz
CCs5HYnBriY2vW94zZzWnJefnEh9mzYgWeJwy6CP7SxeKTWktbAjAgMBAAE=
-----END RSA PUBLIC KEY-----
[root@localhost release]# cat plainPub.key
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlGVxzTDVhnC16SW+D0WG8hvm1
wztmr0vBh2VK6CU7k90mdrCx4by1URcZ6iS6KxomxSqWmK9g2C0iRd8xx7OyykBH
KttjIx5Diq3wLXDP2qU4mjSIvHP3MwgrOR2Jwa4mNr1veM2c1pyXn5xIfZs2IFni
cMugj+0sXik1pLWwIwIDAQAB
-----END PUBLIC KEY-----
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlGVxzTDVhnC16SW+D0WG8hvm1
wztmr0vBh2VK6CU7k90mdrCx4by1URcZ6iS6KxomxSqWmK9g2C0iRd8xx7OyykBH
KttjIx5Diq3wLXDP2qU4mjSIvHP3MwgrOR2Jwa4mNr1veM2c1pyXn5xIfZs2IFni
cMugj+0sXik1pLWwIwIDAQAB
-----END PUBLIC KEY-----
其次,当我再用PEM_read_RSAPublicKEY()接口来读取公钥文件plainPub2.key时,居然成功了。说明RSA PUBLIC KEY和PUBLIC KEY的两种公钥文件其存储方式是不一样的,PEM_read_RSAPublicKEY()只能读取RSA PUBLIC KEY形式的公钥文件;而PEM_read_RSA_PUBKEY()只能读取PUBLIC KEY格式的公钥文件。由于本人密码学基础较薄弱,现在还不能说出两者的区别,请各位见谅,还望密码方面的大牛们予以点拨。演示代码如下:
点击(此处)折叠或打开
- /* filename: tmp.c
- */
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- #include<openssl/rsa.h>
- #include<openssl/pem.h>
- #include<openssl/err.h>
- void hexprint(char *str,int len)
- {
- int i=0;
- for(i=0;i<len;i++){
- printf("%s%02x%s",((i%16==0?"|":"")),*((unsigned char*)str+i),(((i+1)%16==0)?"|\n":" "));
- }
- if(i%16!=0)
- printf("|\n");
- }
- static int do_operation(RSA* rsa_ctx,char *instr,char* path_key,int inlen,char** outstr,int type)
- {
- if(rsa_ctx == NULL || instr == NULL || path_key == NULL)
- {
- perror("input elems error,please check them!");
- return -1;
- }
- int rsa_len,num;
- rsa_len=RSA_size(rsa_ctx);
- *outstr=(unsigned char *)malloc(rsa_len+1);
- memset(*outstr,0,rsa_len+1);
- switch(type){
- case 1: //pub enc
- if(inlen == 0){
- perror("input str len is zero!");
- goto err;
- }
- num = RSA_public_encrypt(inlen,(unsigned char *)instr,(unsigned char*)*outstr,rsa_ctx,RSA_PKCS1_OAEP_PADDING);
- break;
- case 2: //prv dec
- num = RSA_private_decrypt(inlen,(unsigned char *)instr,(unsigned char*)*outstr,rsa_ctx,RSA_PKCS1_OAEP_PADDING);
- default:
- break;
- }
- if(num == -1)
- {
- printf("Got error on enc/dec!\n");
- err:
- free(*outstr);
- *outstr = NULL;
- num = -1;
- }
- return num;
- }
- int rsa_pub_encrypt(char *str,char *path_key,char** outstr){
- RSA *p_rsa;
- FILE *file;
- int flen,rsa_len,num;
- if((file=fopen(path_key,"r"))==NULL){
- perror("open key file error");
- return -1;
- }
- #ifdef RSAPUBKEY
- if((p_rsa=PEM_read_RSA_PUBKEY(file,NULL,NULL,NULL))==NULL){
- #else
- if((p_rsa=PEM_read_RSAPublicKey(file,NULL,NULL,NULL))==NULL){
- #endif
- ERR_print_errors_fp(stdout);
- return -1;
- }
- num = do_operation(p_rsa,str,path_key,strlen(str),outstr,1);
- RSA_free(p_rsa);
- fclose(file);
- return num;
- }
- int rsa_prv_decrypt(char *str,char *path_key,int inlen,char** outstr){
- RSA *p_rsa;
- FILE *file;
- int rsa_len,num;
-
- if((file=fopen(path_key,"r"))==NULL){
- perror("open key file error");
- return -1;
- }
- if((p_rsa=PEM_read_RSAPrivateKey(file,NULL,NULL,NULL))==NULL){
- ERR_print_errors_fp(stdout);
- return -1;
- }
- num = do_operation(p_rsa,str,path_key,inlen,outstr,2);
- RSA_free(p_rsa);
- fclose(file);
- return num;
- }
- int main(int argc,char** argv){
- char *ptr_en,*ptr_de;
- int len;
-
- printf("source is :%s\n",argv[1]);
- len=rsa_pub_encrypt(argv[1],argv[2],&ptr_en);
- printf("pubkey encrypt:\n");
- hexprint(ptr_en,len);
-
- rsa_prv_decrypt(ptr_en,argv[3],len,&ptr_de);
- printf("prvkey decrypt:%s\n",ptr_de==NULL?"NULL":ptr_de);
-
- if(ptr_en!=NULL){
- free(ptr_en);
- }
- if(ptr_de!=NULL){
- free(ptr_de);
- }
-
- return 0;
- }
如果开启RSAPUBKEY宏,则用PEM_read_RSA_PUBKEY()来读取公钥文件;否则用PEM_read_RSAPublicKey()读取:
[root@localhost release]#gcc -o pub rsatest.c -lcrypto -g -DRSAPUBKEY
[root@localhost release]#gcc -o nopub rsatest.c -lcrypto -g
测试结果如下:
实际应用中,出于安全考虑我们一般会对私钥文件加密。我们可以用如下的方式来重新生成经3DES加密后私钥文件:
[root@localhost release]#openssl genrsa -des3 -out cipherPrv.key 1024
这样生成的私钥文件使用3DES加过密的,看看内容就晓得和之前的有什么不同了。头部多了一些信息:Proc-Type和DEK-Info,猜想这肯定是某种加密信息(这TM不废话么),但是我看不懂,现阶段“会用”是首要问题:
上述加密私钥文件的口令是123456,分别提取RSA PUBLIC KEY和PUBLIC KEY格式的公钥文件:
[root@localhost release]# openssl rsa -in cipherPrv.key -pubout -out cipherPub.key
[root@localhost release]# openssl rsa -in cipherPrv.key -RSAPublicKey_out -out cipherPub2.key
在代码中我们需要通过下面的方式来读取经3DES加密处理后的私钥文件:
点击(此处)折叠或打开
- RSA* getPRV(char *path_key_fullname,char* pwd)
- {
- RSA *rsaK=RSA_new();
- OpenSSL_add_all_algorithms();
- BIO *BP = BIO_new_file(path_key_fullname,"rb");
- if(NULL == BP)
- return NULL;
- rsaK=PEM_read_bio_RSAPrivateKey(BP,NULL,NULL,pwd);
- return rsaK;
- }
if((p_rsa=PEM_read_RSAPrivateKey(file,NULL,NULL,NULL))==NULL){
替换成:
if((p_rsa=getPRV(path_key,"123456"))==NULL){
重新编译,运行后结果如下:
关于openssl有很多值得学习的地方,空了再慢慢研究。
3
上一篇:经典排序算法归纳笔记(4)
下一篇:Linux 内核通知链随笔【中】
相关热门文章
- MyBatis 入门(五)--分页查询(...
- 关于内核模块的挂载后的最终虚...
- 关于__init、__initdata和__ex...
- 关于内核模块挂载出现“no sym...
- 关于U-Boot源码顶层Makefile...
- linux 常见服务端口
- xmanager 2.0 for linux配置
- 【ROOTFS搭建】busybox的httpd...
- openwrt中luci学习笔记
- 什么是shell
- linux dhcp peizhi roc
- 关于Unix文件的软链接
- 求教这个命令什么意思,我是新...
- sed -e "/grep/d" 是什么意思...
- 谁能够帮我解决LINUX 2.6 10...
给主人留下些什么吧!~~
4608963392015-12-23 14:05:21
太感谢了,解决了大问题。PEM_read_RSA_PUBKEY 不知道这个地方为什么这么用,有啥研究成果木有
回复 | 举报
popfeng2014-11-25 17:05:41
太棒了,谢谢分享~
回复 | 举报
评论热议
0 0
- 关于openssl几个API的一点小收获
- 关于openssl几个API的一点小收获
- 关于openssl几个API的一点小收获
- 关于采集的一点收获
- 关于置换的一点收获
- 关于openssl加解密文件的几个API
- 面向对象的一点小的收获
- 调试堆的一点小收获
- sql数据库的一点小收获
- 调试堆的一点小收获
- 关于ANSI C标准的一点收获
- 关于SNS编程的一点收获
- 关于弹出框与源页面交互的一点小收获(基于wabacus开发框架)
- 关于CString的一点小收获,CString在控制台程序中输出到屏幕
- 初学UNIX C时的一点小收获
- 实习笔记:记录查询信息的一点小收获(tarot)
- 使用js操作cookie的一点小收获
- for循环中加载数据的一点小收获
- 多媒体技术基础之---色彩空间
- 从新版本系统调用学习宏定义的用法
- 经典排序算法归纳笔记(1)
- 经典排序算法归纳笔记(2)
- 经典排序算法归纳笔记(4)
- 关于openssl几个API的一点小收获
- Linux 内核通知链随笔【中】
- VS code 编辑器(文件或者文件夹的右键打开菜单的显示)
- Linux内核【链表】整理笔记(1)
- Linux内核【链表】整理笔记(2)
- 刨一刨内核container_of()的设计精髓
- 漫谈Linux内核哈希表(1)
- 漫谈Linux内核哈希表(2)
- ubuntu vi备忘
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
墙衣的优缺点
墙衣有市场吗
天鹅绒墙衣价格
品牌墙衣价格
墙衣缺点大揭秘
墙衣市场怎么样
墙衬
墙群
墙裙图片
墙裙是什么
墙裙效果图
墙裙板
客厅墙裙
楼梯墙裙
墙裙材料
儿童房墙裙
楼梯墙裙贴瓷砖方法
幼儿园墙裙
客厅墙裙效果图
墙裙砖
墙裙装修效果图
墙裙装饰板
墙裙多少钱一平方
客厅墙裙装修效果图
客厅墙裙贴瓷砖效果图
墙裙装饰材料
客厅墙裙多高好看
室内墙裙图片
中式墙裙图片
墙裙高度
中国对韩国
韩国对中国
墙角数枝梅
衰鬼撬墙角
墙角
挖墙角
挖墙角意思
墙角线
墙角护角
蹲墙角
墙角的父亲