一.openssl简介

  openssl 是目前最流行的 SSL 密码库工具,其提供了一个通用、健壮、功能完备的工具套件,用以支持SSL/TLS 协议的实现。
官网:openssl官网

1.1 主要构成部分

1.密码算法库(对称加密、非对称加密、HASH运算等)
2.密钥和证书封装管理功能(证书申请、颁发、撤销)
3.SSL通信API接口(https通信SSL接口)

1.2 openssl用途

1.建立 RSA、DH、DSA key 参数
2.建立 X.509 证书、证书签名请求(CSR)和CRLs(证书撤销列表)
3.计算消息摘要HASH
4.使用各种 Cipher加密/解密
5.SSL/TLS 客户端以及服务器的测试
6.处理S/MIME 或者加密邮件

1.3 证书、密钥、CSR请求文件、CRL列表 查看命令

证书查看:

openssl x509 -in cert.crt -noout -text

私钥查看:

openssl rsa -text -in server.key

公钥查看:

openssl rsa -pubin -in pcapubkey.pem -text -noout

CSR查看:

openssl req -text -in server.csr -noout

CRL列表查看:

openssl crl -in testca.crl -text -noout

二.RSA密钥操作

2.1密钥生成

默认情况下,openssl 输出格式为 PKCS#1-PEM
生成RSA私钥(无加密):

openssl genrsa -out rsa_private.key 2048

生成RSA公钥:

openssl rsa -in rsa_private.key -pubout -out rsa_public.key

生成RSA私钥(使用aes256加密):

openssl genrsa -aes256 -passout pass:123456 -out rsa_aes_private.key 2048

其中 passout 代替shell 进行密码输入,否则会提示输入密码;
生成加密后的内容如:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,5584D000DDDD53DD5B12AE935F05A007
Base64 Encoded Data
-----END RSA PRIVATE KEY-----

此时若生成公钥,需要提供密码

openssl rsa -in rsa_aes_private.key -passin pass:111111 -pubout -out rsa_public.key

其中 passin 代替shell 进行密码输入,否则会提示输入密码;

将需要输入密码使用的.key私钥文件转成不需要输入密码的.key文件(其实就是使用passin将密码提前输入了):

openssl rsa -in client.key -passin pass:222222 -out client.key

从证书中提取私钥:

openssl x509 -in rca.cer -pubkey -noout > rcapubkey.pem

2.2 转换命令

私钥转非加密:

openssl rsa -in rsa_aes_private.key -passin pass:111111 -out rsa_private.key

私钥转加密:

openssl rsa -in rsa_private.key -aes256 -passout pass:111111 -out rsa_aes_private.key

私钥PEM转DER:

openssl rsa -in rsa_private.key -outform der-out rsa_aes_private.der

-inform和-outform 参数制定输入输出格式,由der转pem格式同理。

pem转crt格式:

openssl x509 -in fullchain.pem -out fullchain.crt

pem转key格式:

openssl rsa -in privkey.pem -out privkey.key

查看私钥明细(使用-pubin参数可查看公钥明细):

openssl rsa -in rsa_private.key -noout -text

私钥PKCS#1转PKCS#8

openssl pkcs8 -topk8 -in rsa_private.key -passout pass:111111 -out pkcs8_private.key

其中-passout指定了密码,输出的pkcs8格式密钥为加密形式,pkcs8默认采用des3 加密算法,内容如下:

-----BEGIN ENCRYPTED PRIVATE KEY-----
Base64 Encoded Data
-----END ENCRYPTED PRIVATE KEY-----

使用-nocrypt参数可以输出无加密的pkcs8密钥,如下:

-----BEGIN PRIVATE KEY-----
Base64 Encoded Data
-----END PRIVATE KEY-----

2.3 使用公私钥进行密码学运算

1.私钥的生成

openssl genras -out private.pem 2048

2.使用私钥生成公钥

openssl rsa -in ./private.pem -pubout -out public.pem

3.使用公钥对文件进行加密

openssl rsautl -encrypt -in ./a.txt -inkey public.pem -pubin -out message.en

4.使用私钥对加密文件进行解密

openssl rsautl -decrypt -in ./message.en -inkey private.pem -out message.txt

5.使用私钥对文件进行签名

openssl dgst -sign private.pem -md5 -out message.sign a.txt

6.使用公钥对签名后的文件进行验签

openssl dgst -verify public.pem -md5 -signature message.sign a.txt

7.摘要算法

openssl dgst -sha1 file.txt		//只计算摘要,不导出文件
openssl sha1 file.txt			//只计算摘要,不导出文件
openssl sha1 -out digest.txt file.txt	//导出文件

三.生成自签名证书

3.1 生成 RSA 私钥和自签名证书

openssl req -newkey rsa:2048 -nodes -keyout rsa_private.key -x509 -days 365 -out cert.crt

  其中req是证书请求的子命令,-newkey rsa:2048 -keyout private_key.pem 表示生成私钥(PKCS8格式),-nodes 表示私钥不加密,若不带参数将提示输入密码;-x509表示输出证书,-days365 为有效期,此后根据提示输入证书拥有者信息;
若执行自动输入,可使用-subj选项:

openssl req -newkey rsa:2048 -nodes -keyout rsa_private.key -x509 -days 365 -out cert.crt -subj "/C=CN/ST=GD/L=SZ/O=vihoo/OU=dev/CN=vivo.com/emailAddress=yy@vivo.com"

3.2 使用 已有RSA 私钥生成自签名证书

openssl req -new -x509 -days 365 -key rsa_private.key -out cert.crt

-new 指生成证书请求,加上-x509 表示直接输出证书,-key 指定私钥文件,其余选项与上述命令相同。

四.生成签名请求及CA 签名

4.1 使用 RSA私钥生成 CSR 签名请求

openssl genrsa -aes256 -passout pass:111111 -out server.key 2048
openssl req -new -key server.key -out server.csr

此后输入密码、server证书信息完成,也可以命令行指定各类参数

openssl req -new -key server.key -passin pass:111111 -out server.csr -subj "/C=CN/ST=GD/L=SZ/O=vihoo/OU=dev/CN=vivo.com/emailAddress=yy@vivo.com"

*** 此时生成的 csr签名请求文件可提交至 CA进行签发 ***

4.2 查看CSR 的细节

cat server.csr
-----BEGIN CERTIFICATE REQUEST-----
Base64EncodedData
-----END CERTIFICATE REQUEST-----
openssl req -noout -text -in server.csr

4.3 使用 CA 证书及CA密钥 对请求签发证书进行签发,生成 x509证书

openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -passin pass:111111 -CAcreateserial -out server.crt

其中 CAxxx 选项用于指定CA 参数输入

五.证书查看及转换

查看证书细节:

openssl x509 -in cert.crt -noout -text

转换证书编码格式:

openssl x509 -in cert.cer -inform DER -outform PEM -out cert.pem

合成 pkcs#12 证书(含私钥)

将 pem 证书和私钥转 pkcs#12 证书 :

openssl pkcs12 -export -in server.crt -inkey server.key -passin pass:111111 -password pass:111111 -out server.p12

其中-export指导出pkcs#12 证书,-inkey 指定了私钥文件,-passin 为私钥(文件)密码(nodes为无加密),-password 指定 p12文件的密码(导入导出)。

将 pem 证书和私钥/CA 证书 合成pkcs#12 证书:

openssl pkcs12 -export -in server.crt -inkey server.key -passin pass:111111 \
-chain -CAfile ca.crt -password pass:111111 -out server-all.p12

其中-chain指示同时添加证书链,-CAfile 指定了CA证书,导出的p12文件将包含多个证书。(其他选项:-name可用于指定server证书别名;-caname用于指定ca证书别名)

pcks#12 提取PEM文件(含私钥) :

openssl pkcs12 -in server.p12 -password pass:111111 -passout pass:111111 -out out/server.pem

其中-password 指定 p12文件的密码(导入导出),-passout指输出私钥的加密密码(nodes为无加密)。

导出的文件为pem格式,同时包含证书和私钥(pkcs#8):

Bag Attributes
localKeyID: 97 DD 46 3D 1E 91 EF 01 3B 2E 4A 75 81 4F 11 A6 E7 	1F 79 40 
subject=/C=CN/ST=GD/L=SZ/O=vihoo/OU=dev/CN=vihoo.com/emailAddress=yy@vihoo.com
issuer=/C=CN/ST=GD/L=SZ/O=viroot/OU=dev/CN=viroot.com/emailAddress=yy@viroot.com
-----BEGIN CERTIFICATE-----
MIIDazCCAlMCCQCIOlA9/dcfEjANBgkqhkiG9w0BAQUFADB5MQswCQYDVQQGEwJD
1LpQCA+2B6dn4scZwaCD
-----END CERTIFICATE-----
Bag Attributes
localKeyID: 97 DD 46 3D 1E 91 EF 01 3B 2E 4A 75 81 4F 11 A6 E7 1F 79 40 
Key Attributes: <No Attributes>
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDC/6rAc1YaPRNf
K9ZLHbyBTKVaxehjxzJHHw==
-----END ENCRYPTED PRIVATE KEY-----

仅提取私钥:

 openssl pkcs12 -in server.p12 -password pass:111111 -passout pass:111111 -nocerts -out out/key.pem

仅提取证书(所有证书):

 openssl pkcs12 -in server.p12 -password pass:111111 -nokeys -out out/key.pem

仅提取ca证书:

openssl pkcs12 -in server-all.p12 -password pass:111111 -nokeys -cacerts -out out/cacert.pem 

仅提取server证书:

openssl pkcs12 -in server-all.p12 -password pass:111111 -nokeys -clcerts -out out/cert.pem 

六.基于OPENSSL自建CA,同时为server,client颁发证书

6.1 自建CA

  在进行https通信时需要做双向认证,我们可以利用自己建立的测试CA来为服务器端颁发服务器数字证书,为客户端(浏览器)生成文件形式的数字证书(可以同时利用openssl生成客户端私钥)。

6.1.1 1 创建CA需要用到的目录和文件

随便找个目录比如/home,在该目录下创建自建CA所需要用的文件夹:

mkdir testca
cd testca
mkdir newcerts private conf    //创建证书、私钥、配置文件夹备用
chmod g-rwx,o-rwx private      //设置private文件夹的操作权限,为group和other均可读写、执行
echo "01" > serial             //用于存放下一个证书的序列号
touch index.txt					//用于存放证书信息数据库
mkdir newcerts private conf    //创建证书、私钥、配置文件夹备用
chmod g-rwx,o-rwx private  	 //设置private文件夹的操作权限,为group和other均可读写、执行
echo "01" > serial            	 //用于存放下一个证书的序列号
touch index.txt					//用于存放证书信息数据库

说明:
  testca为待建CA的主目录。其中newcerts子目录将存放CA签署(颁发)过的数字证书(证书备份目录)。而private目录用于存放CA的私钥。目录conf只是用于存放一些简化参数用的配置文件
  文件serial和index.txt分别用于存放下一个证书的序列号和证书信息数据库。当然,偷懒起见,可以只用按照本文操作即可,不一定需要关心各个目录和文件的作用。

6.1.2 生成CA的私钥和自签名证书(即根证书,自建CA需要生成私钥和CA证书)

创建文件:(在conf文件夹下:)
gedit gentestca.conf
文件内容如下:

####################################
[ req ]
default_keyfile = /home/testca/private/cakey.pem		#需要修改为自己的实际路径
default_md = md5
prompt = no
distinguished_name = ca_distinguished_name
x509_extensions = ca_extensions

[ ca_distinguished_name ]
organizationName = TestOrg          				 #可以自定义CA的信息
organizationalUnitName  = TestDepartment  		 #可以自定义CA的信息
commonName = TestCA								#可以自定义CA的信息
emailAddress = ca_admin@testorg.com   			#可以自定义CA的信息

[ ca_extensions ]
basicConstraints = CA:true
########################################

进入testca目录下然后执行命令如下(生成X509的CA证书):

openssl req -x509 -newkey rsa:2048 -out cacert.pem -outform PEM -days 2190 -config "/home/testca/conf/gentestca.conf"

执行过程中需要输入CA私钥的保护密码,假设我们输入密码:123456。
简单解释:CA使用自己的私钥cakey.pem(在gentestca.conf文件中指定)按照gentestca.conf文件中的规则自签名生成证书。

可以用如下命令查看一下CA自己证书的内容:

openssl x509 -in cacert.pem -text -noout

6.1.3 创建一个配置文件,以便后续CA日常操作中使用(为其他请求签发证书时的配置):

在conf文件夹下创建文件:

gedit testca.conf

文件内容如下:

####################################
[ ca ]
default_ca      = testca                   # 按需修改

[ testca ]										 # 按需修改
dir            	= /home/testca   		# top dir,按实际给出
database       	= $dir/index.txt          # index file.
new_certs_dir  	= $dir/newcerts           # new certs dir

certificate    		= $dir/cacert.pem         	# The CA cert
serial         		= $dir/serial             		# serial no file
private_key    	= $dir/private/cakey.pem  	# CA private key
RANDFILE       	= $dir/private/.rand      	# random number file

default_days   = 365                     	# how long to certify for
default_crl_days= 30                     	# how long before next CRL
default_md     = md5                    	 # message digest method to use
unique_subject = no                      	# Set to 'no' to allow creation of
                                     			# several ctificates with same subject.
policy         = policy_any              	# default policy

[ policy_any ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional
 
########################################

6.2 CA的常规操作

  在我们自建CA完成之后,就相当于有了一个证书颁发机构,可以执行如下的一些常规操作:

6.2.1 根据证书申请请求签发证书(为其他请求签发证书)

  假设收到一个证书请求文件名为req.pem,文件格式应该是PKCS#10格式(标准证书请求格式)。
首先可以查看一下证书请求的内容,执行命令:

openssl req -in req.pem -text -noout

  将看到证书请求的内容,包括请求者唯一的名字(DN)、公钥信息(可能还有一组扩展的可选属性)。

执行签发命令:

openssl ca -in req.pem -out cert.pem -config "/home/testca/conf/testca.conf"

  执行过程中会要求输入访问CA的私钥密码(刚才设置的123456)。
  签发命令简单解释:实际上就是请求方将自己的请求文件req.pem发给CA,CA按照之前写好的配置文件testca.conf中的规则给请求方生成证书cert.pem。

  完成上一步后,签发好的证书就是cert.pem,另外/home/testca/newcerts里也会有一个相同的证书副本(文件名为证书序列号)。

你可以执行以下语句来查看生成的证书的内容:

openssl x509 -in cert.pem -text -noout

6.2.2 吊销证书(作废证书)

  一般由于用户私钥泄露等情况才需要吊销一个未过期的证书。(当然我们用本测试CA时其时很少用到该命令,除非专门用于测试吊销证书的情况)
假设需要被吊销的证书文件为cert.pem,则执行以下命令吊销证书:

openssl ca -revoke cert.pem -config "$HOME/testca/conf/testca.conf"

6.2.3 生成证书吊销列表文件(CRL)

  准备公开被吊销的证书列表时,可以生成证书吊销列表(CRL),执行命令如下:

openssl ca -gencrl -out testca.crl -config "$HOME/testca/conf/testca.conf"

  还可以添加-crldays和-crlhours参数来说明下一个吊销列表将在多少天后(或多少小时候)发布。

  可以用以下命令检查testca.crl的内容:

openssl crl -in testca.crl -text -noout

6.3 CA为server签发证书

任意路径下创建一个文件夹server:

mkdir sever

生成server的私钥server.key及证书申请的请求文件serverreq.pem:

openssl req -newkey rsa:1024 -keyout server.key -out serverreq.pem -subj "/O=ServerCom/OU=ServerOU/CN=server"

设置私钥保护密码为:111111
解释:server生成请求文件serverreq.pem之后就可以将这个文件发送给CA申请证书了,操作如下:

提交serverreq.pem向CA申请证书并生成证书server.crt:

openssl ca -in serverreq.pem -out server.crt -config "/home/testca/conf/testca.conf"

解释:可以看出-in表示提交给CA的文件,就是申请文件,-out表示输出文件就是server的证书server.crt,其中生成证书的规则-config是按照之前CA定义的testca.conf文件,这里路径不要写错。
至此,server证书申请成功,可以看到共有三个文件:
在这里插入图片描述
同时,在CA目录下newcerts目录下也生成了该证书的备份:01.pem,这和备份的内容和生成的证书server.crt完全一致。

6.4 CA为client签发证书

client的证书生成方式和server完全一致,这里就不在赘述。

6.5 server和client基于证书完成https通信

  https通信需要完成证书验证,我们在上面以及自建了CA,并为server和client颁发了证书,因此可以基于证书验证实现https通信测试了。具体代码设计可见下一篇博客。

五. 感谢支持

    完结撒花!密码学实属复杂深奥的问题,不仅在原理上难以理解,在代码实现上更是难的一批,写这篇文章花了我很大精力。希望看到这里的小伙伴能点个关注,我后续会持续更新更多关于密码学原理分析和实现,也欢迎大家广泛交流。
    码字实属不易,如果本文对你有10分帮助,就赏个10分把,感谢各位大佬支持!

在这里插入图片描述

GitHub 加速计划 / ope / openssl
25.13 K
9.99 K
下载
传输层安全性/安全套接层及其加密库
最近提交(Master分支:1 个月前 )
fd39d1c8 Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/25095) 3 个月前
ae87c488 Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/25095) 3 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐