一、OpenSSL 简介
OpenSSL包含一个命令行工具用来完成OpenSSL库中的所有功能,更好的是,它可能已经安装到你的系统中了。
OpenSSL是一个强大的安全套接字层密码库,Apache使用它加密HTTPS,OpenSSH使用它加密SSH,但是,你不应该只将其作为一个库来使用,它还是一个多用途的、跨平台的密码工具。
OpenSSL有许多的特征,而且还有SSL客户端和服务端特征,OpenSSL还有:
美国联邦政府NIST FIPS 140-2一级评估确认
TLS,下一代SSL协议
X.509密钥和证书的生成
X.509证书权力
S/MIME加密
文件加密和粉碎
打乱UNIX密码
9个不同的商业密码硬件设备
密码性能测试
36个命令
6个消息摘要算法
9个密码算法
多个加密协议
OpenSSL一共实现了4种非对称加密算法:
DH算法
:一般用于密钥交换。
RSA算法
:既可以用于密钥交换,也可以用于数字签名,当然,如果你能够忍受其缓慢的速度,那么也可以用于数据加密。
DSA算法
:一般只用于数字签名。
椭圆曲线算法(ECC)
:ECC的这些特点使它必将取代RSA,成为通用的公钥加密算法。
信息摘要
OpenSSL实现了5种信息摘要算法:MD2、MD5、MDC2、SHA(SHA1)和RIPEMD。SHA算法事实上包括了SHA和SHA1两种信息摘要算法。
此外,OpenSSL还实现了DSS标准中规定的两种信息摘要算法DSS和DSS1。
密钥证书管理
密钥和证书管理是PKI的一个重要组成部分 。PKI:Public Key Infrastructure的首字母缩写,翻译过来就是公钥基础设施;PKI是一种遵循标准的利用公钥加密技术为电子商务的开展提供一套安全基础平台的技术和规范。
OpenSSL 是一个开源项目,其组成主要包括一下三个组件:
openssl:多用途的命令行工具
libcrypto:加密算法库
libssl:加密模块应用库,实现了ssl及tls
openssl可以实现:秘钥证书管理、对称加密和非对称加密等功能。
二、对称加密
- 创建文件:
[root@manager ~]# vi file.txt
# 内容为
123
对称加密需要使用的标准命令为 enc ,用法如下:
openssl enc -ciphername [-in filename] [-out filename] [-pass arg] [-e] [-d] [-a/-base64]
[-A] [-k password] [-kfile filename] [-K key] [-iv IV] [-S salt] [-salt] [-nosalt] [-z] [-md]
[-p] [-P] [-bufsize number] [-nopad] [-debug] [-none] [-engine id]
常用选项有:
-in filename:指定要加密的文件存放路径
-out filename:指定加密后的文件存放路径
-salt:自动插入一个随机数作为文件内容加密,默认选项
-e:可以指明一种加密算法,若不指的话将使用默认加密算法
-d:解密,解密时也可以指定算法,若不指定则使用默认算法,但一定要与加密时的算法一致
-a/-base64:使用-base64位编码格式
- 简单示例:
加密:
[root@manager ~]# openssl dgst -sha1 file.txt
SHA1(file.txt)= a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd0
[root@manager ~]# openssl enc -e -des3 -a -salt -in file.txt -out jiami
# 输入加密密钥
enter des-ede3-cbc encryption password:
# 再次输入加密密钥
Verifying - enter des-ede3-cbc encryption password:
解密:
[root@manager ~]# openssl enc -d -des3 -a -salt -in jiami -out result.txt
enter des-ede3-cbc decryption password:
[root@manager ~]# cat result.txt
123
- 对称加密应用
用DES3算法的CBC模式加密文件plaintext.txt,#加密结果输出到文件ciphertext.txt。
# 创建文件
[root@node2 ~]# echo "123456">>plaintext.txt
[root@node2 ~]# cat plaintext.txt
123456
[root@node2 ~]# openssl enc -des3 -salt -in plaintext.txt -out ciphertext.txt
enter des-ede3-cbc encryption password:
Verifying - enter des-ede3-cbc encryption password:
# 解密 加参数-d,加密密钥为1234
[root@node2 ~]# openssl enc -des3 -salt -d -in ciphertext.txt -out result.txt -pass pass:1234
[root@node2 ~]# cat result.txt
123456
用DES3算法的OFB模式解密文件ciphertext.txt,提供的口令为1234,输出到文件result.txt
注意:因为模式不同,该命令不能对以上的文件进行解密
# 加密
[root@node2 ~]# openssl enc -des-ede3-ofb -in plaintext.txt -out ciphertext.txt
enter des-ede3-ofb encryption password:
Verifying - enter des-ede3-ofb encryption password:
# 解密
[root@node2 ~]# rm -f result.txt
[root@node2 ~]# openssl enc -des-ede3-ofb -d -in ciphertext.txt -out result.txt -pass pass:1234
[root@node2 ~]# cat result.txt
123456
用Blowfish的CFB模式加密plaintext.txt,口令为1234,输出到文件ciphertext.txt
# 加密
[root@node2 ~]# rm -f ciphertext.txt
[root@node2 ~]# openssl bf-cfb -salt -in plaintext.txt -out ciphertext.txt -pass pass:1234
# 解密
[root@node2 ~]# rm -f result.txt
[root@node2 ~]# openssl bf-cfb -salt -d -in ciphertext.txt -out result.txt -pass pass:1234
[root@node2 ~]# cat result.txt
123456
给文件result.txt用base64编码,输出到文件base64.txt
[root@node2 ~]# openssl base64 -in result.txt -out base64.txt
[root@node2 ~]# cat base64.txt
MTIzNDU2Cg==
用RC4算法的CBC模式加密文件plaintext.txt, 输出到文件ciphertext.txt
# salt、key和初始化向量(iv)在命令行指定
[root@node2 ~]# openssl rc4 -in plaintext.txt -out ciphertext.txt -S C62CB1D49F158ADC -iv E9EDACA1BD7090C6 -K 89D4B1678D604FAA3DBFFD030A314B29
[root@node2 ~]# cat ciphertext.txt
# 解密
[root@node2 ~]# openssl rc4 -d -in ciphertext.txt -out result.txt -S C62CB1D49F158ADC -iv E9EDACA1BD7090C6 -K 89D4B1678D604FAA3DBFFD030A314B29
[root@node2 ~]# cat result.txt
123456
三、单向加密
单向加密需要使用的标准命令为 dgst
用法如下:
openssl dgst [-md5|-md4|-md2|-sha1|-sha|-mdc2|-ripemd160|-dss1] [-c] [-d] [-hex] [-binary]
[-out filename] [-sign filename] [-keyform arg] [-passin arg] [-verify filename] [-prverify
filename] [-signature filename] [-hmac key] [file...]
常用选项有:
[-md5|-md4|-md2|-sha1|-sha|-mdc2|-ripemd160|-dss1] :指定一种加密算法
-out filename:将加密的内容保存到指定文件中。
用SHA1算法计算文件file.txt的哈西值,输出到stdout
[root@node2 ~]# openssl dgst -sha1 plaintext.txt
SHA1(plaintext.txt)= c4f9375f9834b4e7f0a528cc65c055702bf5f24a
用SHA1算法计算文件plaintext.txt的哈西值,输出到文件digest.txt
[root@node2 ~]# openssl sha1 -out digest.txt plaintext.txt
[root@node2 ~]# cat digest.txt
SHA1(plaintext.txt)= c4f9375f9834b4e7f0a528cc65c055702bf5f24a
用DSS1(SHA1)算法为文件plaintext.txt签名,输出到文件dsasign.txt
必须有dsakey.pem文件
# 签名的private key必须为DSA算法产生的,保存在文件dsakey.pem中
# openssl dgst -dss1 -sign dsakey.pem -out dsasign.txt plaintext.txt
# 用dss1算法验证plaintext.txt的数字签名dsasign. txt ,
# 验证的private key为DSA算法产生的文件dsakey.pem
# openssl dgst -dss1 -prverify dsakey.pem -signature dsasign.txt plaintext.txt
用sha1算法为文件plaintext.txt签名,输出到文件rsasign.txt
# 签名的private key为RSA算法产生的文件rsaprivate.pem
# openssl sha1 -sign rsaprivate.pem -out rsasign.txt plaintext.txt
# 用sha1算法验证plaintext.txt的数字签名rsasign.txt,
# 验证的public key为RSA算法生成的rsapublic.pem
# openssl sha1 -verify rsapublic.pem -signature rsasign.txt plaintext.txt
单向加密除了 openssl dgst 工具还有:
md5sum,sha1sum,sha224sum,sha256sum ,sha384sum,sha512sum
四、生成密码
生成密码需要使用的标准命令为 passwd ,用法如下:
openssl passwd [-crypt] [-1] [-apr1] [-salt string] [-in file] [-stdin] [-noverify] [-quiet] [-table] {password}
常用选项有:
-1:使用md5加密算法
-salt string:加入随机数,最多8位随机数
-in file:对输入的文件内容进行加密
-stdion:对标准输入的内容进行加密
# 生成MD5的加密
[root@node2 ~]# openssl passwd -1 -salt '12345678'
Password:
$1$12345678$a4ge4d5iJ5vwvbFS88TEN0
五、生成随机数
生成随机数需要用到的标准命令为 rand ,用法如下:
openssl rand [-out file] [-rand file(s)] [-base64] [-hex] num
常用选项有:
-out file:将生成的随机数保存至指定文件中
-base64:使用base64 编码格式
-hex:使用16进制编码格式
使用生成因子2和随机的1024-bit的素数产生D0ffie-Hellman参数,输出保存到文件dhparam.pem。
[root@node2 ~]# openssl dhparam -out dhparam.pem -2 1024
Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time
从dhparam.pem中读取Diffie-Hell参数,以C代码的形式输出到stdout
[root@node2 ~]# openssl dhparam -in dhparam.pem -noout -C
#ifndef HEADER_DH_H
#include <openssl/dh.h>
#endif
DH *get_dh1024()
{
static unsigned char dh1024_p[]={
0x9A,0xD7,0xBF,0x77,0xBD,0x3C,0x46,0x39,0xBB,0xD7,0x33,0xC4,
0x87,0xF2,0x4F,0xC6,0xA7,0xC6,0xD4,0xFA,0x9D,0x9F,0x8F,0x7A,
0x38,0x5F,0xEE,0xDD,0xDE,0xE6,0xE7,0x70,0x44,0xA1,0x49,0xDF,
0x71,0x53,0xBA,0x03,0x32,0xEC,0xEB,0x26,0x81,0xBB,0xD5,0x6A,
0xF3,0x89,0xF7,0x77,0x33,0x10,0x2E,0x2D,0x69,0xED,0x8E,0x03,
0x8A,0xDF,0x07,0xBF,0xF8,0xD9,0x88,0x9C,0x5C,0x74,0x81,0x21,
0xD3,0xC1,0x16,0x85,0xBD,0x1F,0x0E,0x83,0x85,0xA0,0x30,0x4A,
0xF1,0x41,0x61,0x88,0x31,0x2C,0x50,0x2C,0x68,0xEA,0xA7,0xF3,
0xD3,0x59,0xEF,0x98,0xD3,0xC0,0x89,0x4E,0x61,0xE0,0xFD,0x3A,
0xFE,0x0A,0x6E,0xF3,0x80,0x3B,0x04,0x44,0x5D,0xD4,0x1B,0x40,
0x9C,0x10,0xAB,0x9E,0x5B,0xAE,0xAB,0x03,
};
static unsigned char dh1024_g[]={
0x02,
};
DH *dh;
if ((dh=DH_new()) == NULL) return(NULL);
dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),NULL);
dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),NULL);
if ((dh->p == NULL) || (dh->g == NULL))
{ DH_free(dh); return(NULL); }
return(dh);
}
六、生成秘钥对
首先需要先使用 genrsa 标准命令生成私钥,然后再使用 rsa 标准命令从私钥中提取公钥。
genrsa 的用法如下:
openssl genrsa [-out filename] [-passout arg] [-des] [-des3] [-idea] [-f4] [-3] [-rand file(s)] [-engine id] [numbits]
常用选项有:
-out filename:将生成的私钥保存至指定的文件中
-des|-des3|-idea:不同的加密算法
numbits:指定生成私钥的大小,默认是2048
一般情况下秘钥文件的权限一定要控制好,只能自己读写,因此可以使用 umask 命令设置生成的私钥权限。
ras 的用法如下:
openssl rsa [-inform PEM|NET|DER] [-outform PEM|NET|DER] [-in filename] [-passin arg] [-out filename] [-passout arg]
[-sgckey] [-des] [-des3] [-idea] [-text] [-noout] [-modulus] [-check] [-pubin] [-pubout] [-engine id]
常用选项:
-in filename:指明私钥文件
-out filename:指明将提取出的公钥保存至指定文件中
-pubout:根据私钥提取出公钥
- 生成1024位RSA私匙,用3DES加密它,口令为1234,输出到文件rsaprivatekey.pem
[root@localhost ~]# openssl genrsa -out rsaprivatekey.pem -passout pass:trousers -des3 1024
Generating RSA private key, 1024 bit long modulus
.......++++++
.............++++++
e is 65537 (0x10001)
[root@localhost ~]# cat rsaprivatekey.pem
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,3785CCA5BA2BE5A2
btDUdAcmSUnS9w96QXaYJu9CoyqkqK1fpDEwApPjfKym/KFVWSiGjZ0PgpG8Ig7M
DYXoyXUSwTB5Q7ivbW4HSCGH2JO+CGFf+YwPzfUo0ecAxx132guM8FBYovoP2zbJ
n4hPUBTuWeZUpdrg77fb6DvxbIXuO5hrpsRuVpD2jPiMHIFLNX3G24xl4dt78NMv
MdHitD7rp/zXLnzbcTYJp/x78Qihy0uZaenOaRqyET4U7nXKevd8B8McM2L2Od2B
CSugx9dUl5Wx4xH3L7a8eenLjXlL2L7K1zpkYqvbIBaMH0qgAz8UxpPlkQIrDCa3
dhBr4pcPT6d4mQbUOq97w29OTYAY/Kt6t4uDoEpUi2G1G2j86MdtzckYpo8Pytdz
1Nal8Rt4BI/hFJh1EZI21W+DOPViD6sPPHR+V//Q39ZnwwBfKp6ICvLMHg88nxtp
FDZv2mRQ4JGMiJ1Q/rbOpQ07o6kARnxYMTKEg1Hixb2x1sXFfO+44AUoK1GtHVOd
3+dwO9q1qijeypfq+fvCnUgyS1bgVV/Cl2EpqGWMbBFlT3xXXES2+W/wJHSu63b6
XiWI47pwa5CkdutPzL5vLJLCfhOA+hTblq5YlhO+IvKyV9/buuKDSj5Xzgy/GtgR
kCKcPNjTLmGFKc5zS51ujyQCbztwCZqTHQezUBD6+vsl9zeBDjKSXj432rVi9FBD
0dVMOUmltYETVmcVrxGbFnFQMBIKpDFpYJmojKNGO0sG2mlF+blddxAop/++siru
ycWqt8XhM5WbO6AGjxN1XwOAgP5ieX52lY0FZ1hUpuvHt82ngom8gw==
-----END RSA PRIVATE KEY-----
- 从文件rsaprivatekey.pem读取私匙,用口令1234解密,生成的公钥匙输出到文件rsapublickey.pem
[root@localhost ~]# openssl rsa -in rsaprivatekey.pem -passin pass:trousers -pubout -out rsapubckey.pem
writing RSA key
[root@localhost ~]# cat rsapubckey.pem
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD6wAaCknpNy7ak9ppttplvdf4K
KYHpUCEmFRH79jXAK/xaa6uS0aOJ1TPVOpwW6QFXvgBzDr8E58fhOsVjP0FhTVWm
Foe8svi9Rd6+Fhz/3Qpg4C1/drD6axRZ+7YxLxVTFBoKnhdUILuAXJp3U7KgNoV5
51LR3ku6/SXJ7OPngQIDAQAB
-----END PUBLIC KEY-----
- 用公钥匙rsapublickey.pem加密文件plain.txt, 输出到文件cipher.txt
[root@localhost ~]# vi plain.txt
admin
[root@localhost ~]# openssl rsautl -encrypt -pubin -inkey rsapublickey.pem -in plain.txt -out cipher.txt
- 使用私钥匙rsaprivatekey.pem解密密文cipher.txt,输出到文件plain.txt
[root@localhost ~]# openssl rsautl -decrypt -inkey rsaprivatekey.pem -in cipher.txt -out plain.txt
Enter pass phrase for rsaprivatekey.pem:
# 输入密码 rousers
[root@node1 ~]# cat plain.txt
admin
- 用私钥匙rsaprivatekey.pem给文件plain.txt签名,输出到文件signature.bin
[root@localhost ~]# openssl rsautl -sign -inkey rsaprivatekey.pem -in plain.txt -out signature.bin
Enter pass phrase for rsaprivatekey.pem:
- 用公钥匙rsapublickey.pem验证签名signature.bin,输出到文件plain.txt
[root@localhost ~]# openssl rsautl -verify -pubin -inkey rsapublickey.pem -in signature.bin -out plain
- 从X.509证书文件cert.pem中获取公钥匙,用3DES加密mail.txt,输出到文件mail.enc
[root@localhost ~]# openssl smime -encrypt -in mail.txt -des3 -out mail.enc cert.pem
- 从X.509证书文件cert.pem中获取接收人的公钥匙,用私钥匙key.pem解密S/MIME消息mail.enc,结果输出到文件mail.txt
[root@localhost ~]# openssl smime -decrypt -in mail.enc -recip cert.pem -inkey key.pem -out mail.txt
- cert.pem为X.509证书文件,用私匙key,pem为mail.txt签名,证书被包含在S/MIME消息中,输出到文件mail.sgn
[root@localhost ~]# openssl smime -sign -in mail.txt -signer cert.pem -inkey key.pem -out mail.sgn
- 验证S/MIME消息mail.sgn,输出到文件mail.txt 签名者的证书应该作为S/MIME消息的一部分包含在mail.sgn中
[root@localhost ~]# openssl smime -verify -in mail.sgn -out mail.txt
DSA:DSA只是一种算法,和RSA不同之处在于它不能用作加密和解密,也不能进行密钥交换,只用于签名,比RSA要快很多,和RSA加密解密过程相反,在DSA数字签名和认证中,发送者使用自己的私钥对文件或消息进行签名,接受者收到消息后使用发送者的公钥来验证签名的真实性。
# 生成1024位DSA参数集,并输出到文件dsaparam.pem
[root@localhost ~]# openssl dsaparam -out dsaparam.pem 1024
# 使用参数文件dsaparam.pem生成DSA私钥匙,
# 采用3DES加密后输出到文件dsaprivatekey.pem
[root@localhost ~]# openssl gendsa -out dsaprivatekey.pem -des3 dsaparam.pem
# 使用私钥匙dsaprivatekey.pem生成公钥匙,
# 输出到dsapublickey.pem
[root@localhost ~]# openssl dsa -in dsaprivatekey.pem -pubout -out dsapublickey.pem
# 从dsaprivatekey.pem中读取私钥匙,解密并输入新口令进行加密,
# 然后写回文件dsaprivatekey.pem
[root@localhost ~]# openssl dsa -in dsaprivatekey.pem -out dsaprivatekey.pem -des3 -passin
七、创建CA和申请证书
使用openssl工具创建CA证书和申请证书时,需要先查看配置文件,因为配置文件中对证书的名称和存放位置等相关信息都做了定义。
- 生成自签名证书
生成 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"
使用 已有RSA 私钥生成自签名证书
openssl req -new -x509 -days 365 -key rsa_private.key -out cert.crt
-new 指生成证书请求,加上-x509 表示直接输出证书,-key 指定私钥文件,其余选项与上述命令相同。
- 生成签名请求及CA 签名
使用 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进行签发。
使用 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)。
仅提取私钥:
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