当前位置: 首页 > news >正文

PEM_密钥对生成与读取方法

 PS:欢迎转载,但请注明出处,谢谢配合。

前言:

PEMOpenSSL和许多其他SSL工具的标准格式,OpenSSL 使用PEM 文件格式存储证书和密钥。这种格式被设计用来安全的包含在ascii甚至富文本文档中,如电子邮件。这意味着您可以简单的复制和粘贴pem文件的内容到另一个文档中。

PEM文件Base64编码的证书。PEM证书通常用于web服务器,因为他们可以通过一个简单的文本编辑器,很容易地转换成可读的数据。通常当一个PEM编码在文本编辑器中打开文件,它会包含不同的页眉和页脚。

-----BEGIN CERTIFICATE REQUEST----- and -----END CERTIFICATEREQUEST-----

CSR(证书签名请求)

-----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATEKEY-----

私钥

-----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----

证书文件

PKCS #8: Private-Key Information Syntax(语法) Standard(标准)

OpenSSL:是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用。

OpenSSL整个软件包大概可以分成三个主要的功能部分:密码算法库、SSL协议库以及应用程序。OpenSSL的目录结构自然也是围绕这三个功能部分进行规划的。

一、OpenSSL生成pem格式公私钥

1、生成RSA私钥

openssl genrsa -out rsa_private_key.pem1024

 

该命令会生成1024位的私钥,运行,如下图:

 

生成私钥文件rsa_private_key.pem,内容如下:


用记事本方式打开它,可以看到-----BEGIN RSA PRIVATE KEY-----开头,-----END RSA PRIVATE KEY-----结尾的字符串,这个就是原始的私钥。

 

备注:

         若运行openssl.exe,会进入OpenSSL命令行界面,此时输入命令时,则无需再写openssl。(只是该命令行界面中,暂时无法拷贝,本人太懒,不太喜欢)

 

2、RSA私钥转换成PKCS8格式

openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem-outform PEM -nocrypt

 

可以看到,控制台打印出的内容,-----BEGIN PRIVATE KEY-----开头,-----END PRIVATE KEY-----结尾的字符串,这个就是PKCS#8格式的私钥。


备注:

使用该命令,将私钥转成PKCS#8格式,但原rsa_private_key.pem文件中的私钥字符串并没有任何变化。但控制台输出的private key,跟rsa_private_key.pem文件中的private key,不一样。若需使用PKCS8格式的私钥,即控制台中显示的私钥,将其拷贝出来即可。


切记:

opensslpkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM nocrypt

“-”书写正确,上述nocrypt,因为前面的不是英文的,导致nocrypt失效,所以还需要输入密码。需要输入两次密码,运行,如下图:


       可以看到,控制台打印出的内容,-----BEGIN ENCRYPTED PRIVATE KEY-----开头,-----END ENCRYPTED PRIVATE KEY-----结尾的字符串,这个就是加了密的PKCS#8格式的私钥。

       因为输入了密码,转换后的字符串不一样,会比加了-nocrypt的长一些,所以原来的程序解析不了该私钥字符串,会出错。

 

3、生成RSA公钥

openssl rsa -in rsa_private_key.pem-pubout -out rsa_public_key.pem

 

运行,如下图:

 


生成公钥文件rsa_public_key.pem内容如下:


         用记事本方式打开它,可以看到-----BEGIN PUBLIC KEY-----开头,-----END PUBLIC KEY-----结尾的字符串,这个就是公钥。

 

4、Java使用pem文件内容,示例代码

1)私钥签名

a)获取私钥

//获取KeyFactory,指定RSA算法

KeyFactorykeyFactory = KeyFactory.getInstance("RSA");

//BASE64编码的私钥字符串进行解码

BASE64Decoderdecoder = newBASE64Decoder();

byte[] encodeByte = decoder.decodeBuffer(priKey);

//BASE64解码后的字节数组,构造成PKCS8EncodedKeySpec对象,生成私钥对象

PrivateKeyprivatekey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodeByte));

        

b)使用私钥,对数据进行签名

         //获取Signature实例,指定签名算法(本例使用SHA1WithRSA

Signaturesignature = Signature.getInstance("SHA1WithRSA");

//加载私钥

signature.initSign(privatekey);

//更新待签名的数据

signature.update(plain.getBytes("UTF-8"));

//进行签名

byte[] signed = signature.sign();

//将加密后的字节数组,转换成BASE64编码的字符串,作为最终的签名数据

BASE64Encoderencoder = newBASE64Encoder();

return encoder.encode(signed);

 

2)公钥验签

a)获取公钥

//获取KeyFactory,指定RSA算法

KeyFactorykeyFactory = KeyFactory.getInstance("RSA");

   //BASE64编码的公钥字符串进行解码

BASE64Decoderdecoder = newBASE64Decoder();

byte[] encodeByte = decoder.decodeBuffer(pubKey);

//BASE64解码后的字节数组,构造成X509EncodedKeySpec对象,生成公钥对象

PublicKeypublicKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodeByte));

 

b)使用公钥,进行验签

//获取Signature实例,指定签名算法(与之前一致)

Signaturesignature = Signature.getInstance("SHA1WithRSA");

//加载公钥

signature.initVerify(publicKey);

//更新原数据

signature.update(plain.getBytes("UTF-8"));

//公钥验签(true-验签通过;false-验签失败)

BASE64Decoderdecoder = newBASE64Decoder();

returnsignature.verify(decoder.decodeBuffer(sign));

        

         备注:

验签时,签名数据需要先BASE64解码

 

相关文章:

  • nginx 根据域名和地址跳转
  • go语言渐入佳境[11]-function2
  • (三)从jvm层面了解线程的启动和停止
  • Apache https
  • 项目实战-Api的解决方案
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • 五个举措:现代化Jenkins 和终结“Jenkinsteins”
  • Vue官网教程学习过程中值得记录的一些事情
  • sass安装
  • LGPL与闭源程序
  • 聊聊flink的checkpoint配置
  • 堆的python实现及其应用
  • 创建一种深思熟虑的文化
  • 亚马逊Alexa借助神经网络生成播音员声音
  • 将VCSA 6.5添加到AD域
  • 【Leetcode】101. 对称二叉树
  • [数据结构]链表的实现在PHP中
  • 【翻译】babel对TC39装饰器草案的实现
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • GitUp, 你不可错过的秀外慧中的git工具
  • Git学习与使用心得(1)—— 初始化
  • Javascript 原型链
  • Odoo domain写法及运用
  • Python打包系统简单入门
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • quasar-framework cnodejs社区
  • ViewService——一种保证客户端与服务端同步的方法
  • XML已死 ?
  • 阿里云购买磁盘后挂载
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 实现菜单下拉伸展折叠效果demo
  • nb
  • No resource identifier found for attribute,RxJava之zip操作符
  • 《码出高效》学习笔记与书中错误记录
  • scrapy中间件源码分析及常用中间件大全
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • #{}和${}的区别是什么 -- java面试
  • (16)UiBot:智能化软件机器人(以头歌抓取课程数据为例)
  • (ibm)Java 语言的 XPath API
  • (仿QQ聊天消息列表加载)wp7 listbox 列表项逐一加载的一种实现方式,以及加入渐显动画...
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (五)Python 垃圾回收机制
  • .\OBJ\test1.axf: Error: L6230W: Ignoring --entry command. Cannot find argumen 'Reset_Handler'
  • .equals()到底是什么意思?
  • .form文件_一篇文章学会文件上传
  • .NET Core WebAPI中封装Swagger配置
  • .Net FrameWork总结
  • .NET Standard 支持的 .NET Framework 和 .NET Core
  • .NET/C# 使用 SpanT 为字符串处理提升性能
  • .net中的Queue和Stack
  • @staticmethod和@classmethod的作用与区别
  • [1181]linux两台服务器之间传输文件和文件夹