博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
X509证书中RSA公钥的提取与载入
阅读量:5240 次
发布时间:2019-06-14

本文共 2495 字,大约阅读时间需要 8 分钟。

 

原文链接: http://blog.chinaunix.net/uid-16515626-id-2741894.html

 
由于项目需要,我计划利用openssl开发一个基本的CA,实现证书的发放等功能。在项目模型中公私钥对是用户自己产生的,并且以16进制数的形似提交给CA。我们知道,通常利用openssl颁发证书时,公私钥对往往也是由openssl产生的,比如利用以下三个函数
RSA_generate_key
EVP_PKEY_assign_RSA
X509_set_pubkey
  便可以轻松搞定从密钥产生到载入证书的过程,而提取证书公钥只需
X509_get_pubkey
  如何将16进制形式的rsa公钥载证书的却没有相关介绍,经过几天的研究终于搞定了,贴出来与大家分享,我们可以利用下面的函数
  RSA* d2i_RSAPublicKey(NULL,(const unsigned **) pp,int len)
  其中*pp指向存储公钥的内存单元,len指公钥的长度,请注意这里的公钥是指经过ASN.1编码的公钥,关于此编码方法,要想全面阐述是相当复杂的,但如果仅限于编rsa公钥,则会简单很多,以下是1024位rsa公钥的ASN.1编码的十六进制描述,共占据140bytes:
30 81 89 02 81 81 00 e3 8d 99 06 9f bd 9a c0 e5 
6a 5d 03 b3 cf 09 ca 8e c1 4a 6c f9 90 c2 46 e0 
89 44 69 cd a5 62 91 42 8a 5f e5 8f d3 fb 93 3f 
bc d7 6e 5e f2 80 41 a6 79 78 8e 4d 1d 3d 65 ad 
d4 36 9c c5 83 55 9d f1 bb 20 4c b7 6c 95 37 b0 
37 06 e3 40 fb 8f 74 c3 59 91 a2 bf a2 e1 db 99 
54 29 5f 9b a5 57 f5 40 7a 54 82 9c 84 d4 35 86 
14 38 69 14 60 f3 c6 c7 11 75 f2 43 2c 34 ed 89 
4a ae e1 9d 57 3e a1 02 03 01 00 01
  ASN.1采用Tag,Lenth,Value,编码方式,在此将整个编为一个sequence,可以理解为结构体,以30作为开始标志,第二位81代表后面有1字节代表长度,即89代表长度(若为82则代表后面有两字节代表长度,依次类推),转化成十进制为137,正好与后面的字节数吻合,从第四位02开始便是此sequence的内涵,相当于结构体的元素,一般来说sequence往往需要嵌套,相当于结构体嵌结构体,但对公钥的sequence来说,此处仅有一层。
  第四位02代表一下的内容为bit流,同样紧随其后的81代表有一字节代表长度,第六位的81代表长度为129,即从00开始直到最后一行a1此为129字节,去掉前面的00,余下128位便是rsa公钥的N值,最后5个字节同样是bit流,以02开始,03表示长度为3,最后的01 00 01 便是rsa公钥的E值。
  关于为什么要在N值前补00,这可能是ASN.1的规定,若bit流的前四bit十六进制值小于8就要在在最前补零,看下面的例子
30 81 88 02 81 80 32 8d 99 06 9f bd 9a c0 e5 6a 
5d 03 b3 cf 09 ca 8e c1 4a 6c f9 90 c2 46 e0 89 
44 69 cd a5 62 91 42 8a 5f e5 8f d3 fb 93 3f bc 
d7 6e 5e f2 80 41 a6 79 78 8e 4d 1d 3d 65 ad d4 
36 9c c5 83 55 9d f1 bb 20 4c b7 6c 95 37 b0 37 
06 e3 40 fb 8f 74 c3 59 91 a2 bf a2 e1 db 99 54 
29 5f 9b a5 57 f5 40 7a 54 82 9c 84 d4 35 86 14 
38 69 14 60 f3 c6 c7 11 75 f2 43 2c 34 ed 89 4a 
ae e1 9d 57 3e a1 02 03 01 00 01
N的前四bit为0x3小于8,因此无需补零。
  关于什么情况下要在tag值之后用8X标明有几位代表length,我的理解是,如果length的前四bit大于8或超过一字节,则必需用8X标明,否则不用。
  言规正传,了解了rsa公钥的编码规则,我们便可以方便的将用其他工具产生的rsa公钥编为openssl可接受的码型,从而完成公钥的导入,对于公钥的提取,同样有函数
  int i2d_RSAPublicKey(RSA *,(const char **))
  返回值为公钥的长度,当然是经ASN.1编码后的。
  完成了bit流与RSA的转化,剩下的工作便有很轻松了,在此在介绍几种简便方法,可以直接在bit与EVP_PKEY之间转化
  导出:
  len=i2d_RSAPublicKey(pkey->pkey.rsa,(const char**)pp);
  导入要多几步:
  pkey->save_type=6;
  pkey->type=EVP_PKEY_type(6);
  pkey->pkey.rsa=d2i_RSAPublicKey(NULL,(const char**)pp,len);
  其中pkey的定义为EVP_PKEY *pkey;
  导入过程中前两行的作用是设定采用的密码算法为rsa,若采用bit-〉rsa-〉pkey模式,这个工作由EVP_PKEY_assign_RSA替我们做了。
  我接触openssl4个月了,以上我的经验总结,欢迎大家批评指正。
 
 
 
 
 

 

转载于:https://www.cnblogs.com/huhu0013/p/4794593.html

你可能感兴趣的文章
安全删除安卓系统自带软件
查看>>
抓包工具PowerSniff-0.1
查看>>
旅游项目问题以及解决汇总
查看>>
R in action读书笔记(21)第十六章 高级图形进阶(上)
查看>>
IIS项目发布完整流程
查看>>
Eclipse 安装插件
查看>>
国外常见互联网盈利创新模式
查看>>
Oracle-05
查看>>
servlet-01
查看>>
关于C语言交换两个数的实现方法以及个人心得
查看>>
值类和引用类的区别
查看>>
J2EE的体系结构
查看>>
CocoaPods的安装和使用
查看>>
第六周学习总结
查看>>
使窗口订在桌面上,显示桌面也不会最小化
查看>>
Android批量图片载入经典系列——使用LruCache、AsyncTask缓存并异步载入图片
查看>>
基于 OAuth 安全协议的 Java 应用编程1
查看>>
BroadcastReceiver(接收广播)
查看>>
安卓自己定义日历控件
查看>>
android下文件下载
查看>>