这篇文章上次修改于 523 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

OpenSSL 是一个强大的安全套接字层密码库,包括了加密算法,常用密钥和证书管理,SSL协议等功能。OpenSSL提供的命令非常多,这里只简单列出OpenSSL生成密钥和证书的一些操作(Window需要以管理员身份运行cmd)。

v1.0.1+密钥默认采用PKCS#8格式(之前版本为PEM)。

1.密钥生成(genrsa,genpkey,req在证书请求时同时生成密钥, gendh, gendsa)

(1) openssl genrsa [options] [bits_num]

  • -out 指定输出文件,不指定时在终端显示密钥内容
  • -passout pass: 设置私钥文件密码
  • -f4 使用F4(0x10001)作为公钥的E参数(默认)
  • -3 使用3作为公钥的E参数
  • -des , -des3, -aes128, -aes192, -aes256 指定加密算法(默认不加密)

    默认生产的密钥格式为PEM。openssl默认只生成了私钥文件,当需要提取公钥时使用rsa命令。
    示例:
    #生成RSA密钥对。位长度为2048,保持到rsakey0.pem文件中。
    openssl genrsa -out rsakey0.pem 2048

    #生成RSA密钥对。使用DES3加密,密钥使用密码保护,位长度为1024
    openssl genrsa -des3 -out rootca.key -passout pass:123456 1024

(2) openssl genpkey [options] v1.0.1+

示例

#生成RSA密钥,位长度为2048,格式为DER
openssl genpkey -algorithm RSA -out rsapriKey.pem -pkeyopt rsa_keygen_bits:2048 -outform DER
 

(3) openssl req请求时生成新的密钥对

openssl req -x509  -days 365 -newkey rsa:2048 -keyout private.pem -out public.pem -nodes

2.密钥文件管理和转换(rsa, pkey)

(1) openssl rsa [options] outfile

  • -in 输入密钥文件
  • -passin pass: 输入密钥保护密码
  • -inform <DER|NET|PEM> 输入密钥格式,默认为PEM
  • -out 输出密钥文件
  • -outform <DER|NET|PEM> 输出密钥格式,默认为PEM
  • -passout pass: 输出密钥保护密码
  • -pubin 指示输入的是公钥,默认输出的是密钥对或私钥
  • -pubout 输出公钥到文件(公钥一般无需加密)
  • -des, -des3, -aes128, -aes192, -aes256 指定密钥加密算法
  • -text 明文输出密钥参数
  • -noout 不输出密钥到文件
  • -check 验证一致性
  • -modulus 显示RSA密钥模值

示例

#生成pkcs8公钥到单独的文件
openssl rsa -in rsakey0.pem -pubout -out pkcs8_public.pub  

#生成pkcs1公钥到单独的文件
openssl rsa -in rsakey0.pem -RSAPublicKey_out -out pkcs1_public.pem

#转换密钥格式(DER->PEM)
openssl rsa -in rsakeypair.der -inform DER -out rsakeypair.pem 

#改加密算法,移除密码保护
openssl rsa -in rsakeypair.pem -passin pass:123456  -des3 -out rsakeypair1.pem

(2) 将PEM格式密钥转换成Java JCE 能使用的DER格式密钥的另一种方式

openssl pkcs8 -topk8 -inform PEM -outform DER -in <rsa_pem.key> -out <pkcs8_der.key> -nocrypt

(3) OpenSSL公钥和OpenSSH公钥格式转换

OpenSSL生成的公钥格式和OpenSSH公钥格式不一致,把OpenSSL生成的公钥用于配置SSH连接,验证会失败。

OpenSSL公钥(PEM)格式为:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7vbqajDw4o6gJy8UtmIbkcpnk
O3Kwc4qsEnSZp/TR+fQi62F79RHWmwKOtFmwteURgLbj7D/WGuNLGOfa/2vse3G2
eHnHl5CB8ruRX9fBl/KgwCVr2JaEuUm66bBQeP5XeBotdR4cvX38uPYivCDdPjJ1
QWPdspTBKcxeFbccDwIDAQAB
-----END PUBLIC KEY-----

OpenSSH公钥格式为:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC7vbqajDw4o6gJy8UtmIbkcpnkO3Kwc4qsEnSZp/TR+fQi62F79RHWmwKOtFmwteURgLbj7D/WGuNLGOfa/2vse3G2eHnHl5CB8ruRX9fBl/KgwCVr2JaEuUm66bBQeP5XeBotdR4cvX38uPYivCDdPjJ1QWPdspTBKcxeFbccDw==
  • 从私钥重新生成OpenSSH格式公钥
ssh-keygen -y -f priKey.pem   > sshPubkey.pub
  • 将OpenSSL格式公钥转换成OpenSSH格式
ssh-keygen -i -m PKCS8 -f sslPubKey.pub 〉 sshPubKey.pub    #-m支持 PEM,PKCS8,RFC4716
  • 将OpenSSH格式公钥转换成OpenSSL格式公钥
ssh-keygen -e -m PEM -f sshPubKey.pub >sslPubKey.pub        #-m支持 PEM,PKCS8,RFC4716

3.使用密钥(rsautl),不支持大文件

openssl rsautl [options]

  • -in 输入需加密解密文件
  • -out 输出加密或解密后的文件
  • -inkey 输入密钥文件
  • -passin pass: 输入密钥文件的保护密码
  • -keyform <PEM|DER|NET> 输入密钥文件格式,默认为PEM
  • -pubin 指明输入的是公钥文件
  • -certin 指明输入的是包含公钥的证书
  • -sign 使用私钥签名签名(加密)
  • -verify 似乎用公钥验证签名(解密)
  • -encrypt 使用公钥加密
  • -decrypt 使用私钥解密
  • -hexdump 输出十六进制
  • -pkcs, -ssl, -raw, -oaep 数据补齐方式,默认为pkcs

使用RSA加密时,要求被加密的数据长度与RSA密钥长度一致,数据过短时会补齐。过长时会分段加密。实际应用中很少会使用非对称加密算法对大的文件进行加密操作,而是使用对称加密算法加密文件,然后再使用<非对称加密算法>对<对称算法的密钥>进行加密。
示例:

#使用公钥加密
openssl rsautl -in test.txt  -out test_enc.txt -inkey rsakeypair.pub -pubin -encrypt

#使用私钥解密
openssl rsautl -in test_enc.txt -out text_dec.txt -inkey rsakeypair.pem -decrypt

#使用私钥签名
openssl rsautl -in test.txt -out test_sign.txt -inkey rsakeypair.pem -sign

#使用公钥验证签名
openssl rsautl -in test_sign.txt -out test_unsign.txt -inkey rsakeypari.pub -pubin -verify

4.证书管理

  • 生成X509格式的自签名证书
openssl req -x509 -new -days 365 -key rsakey.pem -out cert0.crt

会要求输入区别名DN的各项信息(国家,城市,组织,姓名,email等)。

根证书是认证中心机构(Certificate Authority)给自己签发的证书,签发者就是自身,是信任链的起点。里面包含了CA信息、CA公钥、用自身的私钥对这些信息的签名。下载并使用根证书就表示你信任它的来源机构,自然也信任证书以下签发的所有证书。某个证书可以用签发他的证书中的公钥验证,签发他的证书又需要上一层签发证书来验证,直到通过根证书中的公钥验证,那么这个证书就是可信任的。

  • 生成要求根证书签发子证书的请求文件
openssl req -new -key rsakey1.pem -out subcertreq.csr

会要求输入区别名DN的各项信息(国家,城市,组织,姓名,email等),还需要额外属性:密码 和 可选公司名。

使用根证书签发子证书

openssl x509 -req -in subcertreq.csr -CA cert0.crt -CAkey rsakey0.pem -CAcreateserial -days 365 -out subcert.crt

也可创建一个ca的配置文件,通过ca管理子命令来签发子证书(未试验)

openssl ca -config ca.config -out user.crt -infiles user.csr
  • 将证书和密钥打包为pkcs12格式的库中
openssl pkcs12 -export -in subcert.crt -inkey rsakey1.pem -out subcert.p12

需要输入pkcs12文件密码。

  • 查看证书内容
openssl x509 -noout -text -in rootca.crt 
  • 验证证书
openssl verify -CAfile rootca.crt subcert.crt

用rootca.crt的公钥验证subcert.crt中的签名
从证书中提取公钥

openssl x509 -in cert.pem  -noout -pubkey > pubkey.pem

提取密钥对

openssl pkcs12 -in cert.pfx  -nocerts -nodes -out keypari.pem

从PKCS#8提取公钥

openssl req -in public.pem -noout -pubkey

查看pkcs7签名内容的证书信息

openssl pkcs7 -in  <pkcs7singedFile>  -inform DER  -print_certs