OpenSSL使用S/MIME发送签名和加密邮件#

1. 通信双方的证书生成#

1.1 生成根节点证书#

openssl genrsa -out cakey.pem 2048
openssl req -utf8 -new -key cakey.pem -subj "/CN=abc.com" -out cacsr.pem
openssl x509 -req -in cacsr.pem -days 999 -signkey cakey.pem -out cacert.pem

1.2 生成alice的证书#

openssl genrsa -out alicekey.pem 2048
openssl req -utf8 -new -key cakey.pem -subj "/emailAddress=alice@163.com" -out alicecsr.pem
openssl x509 -req -in alicecsr.pem -days 999 -CA cacert.pem -CAKey cakey.pem -set_serial 01 -name "alice" -out alicecert.pem
openssl pkcs12 -export -in alicecert.pem -inkey alicekey.pem -certfile cacert.pem -out alice.p12

1.3 生成bob的证书#

openssl genrsa -out bobkey.pem 2048
openssl req -new -key bobkey.pem -subj "/emailAddress=bob@126.com" -out bobcsr.pem
openssl x509 -req -in bobcsr.pem -days 999 -CA cacert.pem -CAkey cakey.pem -set_serial 02 -name "bob" -out bobcert.pem
openssl pkcs12 -export -in bobcert.pem -inkey bobkey.pem -certfile cacert.pem -out bob.p12

2. 邮件签名#

openssl smime -sign -in /tmp/msg.txt -signer alicecert.pem -inkey alicekey.pem -nocerts -nodetach -text -out /tmp/alicesigned.eml

提醒: -nodetach 把信息原文也包含到base64块里面,而不是用mime格式的分隔符单独放置,比较容易保证信息不被邮件收发服务器重构,导致验证失败。 -nocerts 是一个可选选项,如果设置的话,alice的证书(公钥等)不会被包含到签名信息里面(base64块) -signer 在签发邮件的时候,指定发送人的证书位置,这里指定alice的证书

3. 签名验证#

openssl smime -verify -in /tmp/alicesigned.eml -certfile alicecert.pem -CAfile cacert.pem

注意: -signer 参数这个时候的意思:导出签发邮件的证书保存。所以要小心覆盖原有证书 -CAfile 设置信任的ca位置,否则验证不通过 -certfile 是一个可选选项,如果签名的时候指定了-nocerts,这里可以指定验证证书(alice),这样网络传输经济。

4. 邮件加密#

smime -encrypt -in /tmp/msg.txt -from alice@163.com -to bob@126.com -des3 -out /tmp/msg.eml bobcert.pem

5. 邮件解密#

openssl smime -decrypt -in /tmp/msg.eml -recip bobcert.pem -inkey bobkey.pem

6. 签名并加密#

openssl smime -sign -in msg.txt -signer alicecert.pem -inkey alicekey.pem -nocerts -nodetach -text | openssl smime -encrypt -des3 -from alice@163.com -to bob@126.com -subject HiBob  bobcert.pem

To: bob@126.com

From: alice@163.com

Subject: HiBob

MIME-Version: 1.0

Content-Disposition: attachment; filename=”smime.p7m”

Content-Type: application/x-pkcs7-mime; smime-type=enveloped-data; name="smime.p7m"

Content-Transfer-Encoding: base64

MIIGKQYJKoZIhvcNAQcDoIIGGjCCBhYCAQAxggFmMIIBYgIBADBKMEUxCzAJBgNV

BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX

aWRnaXRzIFB0eSBMdGQCAQMwDQYJKoZIhvcNAQEBBQAEggEAdmR6L5KWIhmIFBwj

。。。。

7.解密并验证#

openssl smime -decrypt -in enc.eml -recip bobcert.pem -inkey bobkey.pem | openssl smime -verify -certfile alicecert.pem -CAfile cacert.pem

Content-Type: text/plain

 Hello, World !

Verification successful

管道命令

openssl smime -sign -in msg.txt -signer alicecert.pem -inkey alicekey.pem -nocerts -nodetach -text | \
openssl smime -encrypt -des3 -from alice@163.com -to bob@126.com -subject HiBob  bobcert.pem | \
openssl smime -decrypt -recip bobcert.pem -inkey bobkey.pem | \
openssl smime -verify -certfile alicecert.pem -CAfile cacert.pem