https://www.madboa.com/geek/openssl/#introduction
内容
介绍
OpenSSL库openssl
附带的命令行二进制文件 可以执行各种加密操作。它可以在脚本中派上用场,也可以用于完成一次性命令行任务。
openssl
但是,使用该应用程序的文档有点分散,因此本文旨在提供一些使用它的实际示例。我假设您已经安装了OpenSSL,并且openssl
二进制文件位于shell的PATH中。
为了清楚起见,这篇文章是严格实用的; 它不涉及加密理论和概念。如果您不知道MD5的总和是多少,本文将不会启发您一点 - 但如果您需要知道的是如何使用openssl
生成文件总和,那么您很幸运。
这篇文章的本质是我将逐步添加新的例子。如果我没有得到您需要的信息,请稍后再回来查看。
如何找到我正在运行的OpenSSL版本?
使用该version
选项。
$ openssl version
OpenSSL 1.0.1e-fips 11 Feb 2013
您可以通过该version -a
选项获得更多信息。
$ openssl version -a
OpenSSL 1.0.1e-fips 11 Feb 2013
built on: Thu Jul 23 19:06:35 UTC 2015
platform: linux-x86_64
options: bn(64,64) md2(int) rc4(16x,int) des(idx,cisc,16,int)
idea(int) blowfish(idx)
compiler: gcc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT
-DDSO_DLFCN -DHAVE_DLFCN_H -DKRB5_MIT -m64 -DL_ENDIAN -DTERMIO
-Wall -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions
-fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic
-Wa,--noexecstack -DPURIFY -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT
-DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM
-DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM
-DWHIRLPOOL_ASM -DGHASH_ASM
OPENSSLDIR: "/etc/pki/tls"
engines: rdrand dynamic
如何获取可用命令的列表?
获取可用命令列表有三个内置选项,但没有一个提供我认为有用的输出。最好的办法是提供一个无效的命令(help
或者-h
会做得很好)以获得可读的答案。
$ openssl help
openssl:Error: 'help' is an invalid command.
Standard commands
asn1parse ca ciphers cms
crl crl2pkcs7 dgst dh
dhparam dsa dsaparam ec
ecparam enc engine errstr
gendh gendsa genpkey genrsa
nseq ocsp passwd pkcs12
pkcs7 pkcs8 pkey pkeyparam
pkeyutl prime rand req
rsa rsautl s_client s_server
s_time sess_id smime speed
spkac ts verify version
x509
Message Digest commands (see the `dgst' command for more details)
md2 md4 md5 rmd160
sha sha1
Cipher commands (see the `enc' command for more details)
aes-128-cbc aes-128-ecb aes-192-cbc aes-192-ecb
aes-256-cbc aes-256-ecb base64 bf
bf-cbc bf-cfb bf-ecb bf-ofb
camellia-128-cbc camellia-128-ecb camellia-192-cbc camellia-192-ecb
camellia-256-cbc camellia-256-ecb cast cast-cbc
cast5-cbc cast5-cfb cast5-ecb cast5-ofb
des des-cbc des-cfb des-ecb
des-ede des-ede-cbc des-ede-cfb des-ede-ofb
des-ede3 des-ede3-cbc des-ede3-cfb des-ede3-ofb
des-ofb des3 desx idea
idea-cbc idea-cfb idea-ecb idea-ofb
rc2 rc2-40-cbc rc2-64-cbc rc2-cbc
rc2-cfb rc2-ecb rc2-ofb rc4
rc4-40 seed seed-cbc seed-cfb
seed-ecb seed-ofb zlib
shell称之为“标准命令”是主要的顶级选项。
您可以对任何子命令使用相同的技巧。
$ openssl dgst -h
unknown option '-h'
options are
-c to output the digest with separating colons
-r to output the digest in coreutils format
-d to output debug info
-hex output as hex dump
-binary output in binary form
-sign file sign digest using private key in file
-verify file verify a signature using public key in file
-prverify file verify a signature using private key in file
-keyform arg key file format (PEM or ENGINE)
-out filename output to filename rather than stdout
-signature file signature to verify
-sigopt nm:v signature parameter
-hmac key create hashed MAC with key
-mac algorithm create MAC (not neccessarily HMAC)
-macopt nm:v MAC algorithm parameters or key
-engine e use engine e, possibly a hardware device.
-md4 to use the md4 message digest algorithm
-md5 to use the md5 message digest algorithm
-ripemd160 to use the ripemd160 message digest algorithm
-sha to use the sha message digest algorithm
-sha1 to use the sha1 message digest algorithm
-sha224 to use the sha224 message digest algorithm
-sha256 to use the sha256 message digest algorithm
-sha384 to use the sha384 message digest algorithm
-sha512 to use the sha512 message digest algorithm
-whirlpool to use the whirlpool message digest algorithm
更无聊的方式,您可以参考OpenSSL手册页。
如何获取可用密码列表?
使用该ciphers
选项。该 密码(1)手册页是非常有帮助的。
# list all available ciphers
openssl ciphers -v
# list only TLSv1 ciphers
openssl ciphers -v -tls1
# list only high encryption ciphers (keys larger than 128 bits)
openssl ciphers -v 'HIGH'
# list only high encryption ciphers using the AES algorithm
openssl ciphers -v 'AES+HIGH'
基准
如何对系统的性能进行基准测试?
OpenSSL开发人员直接在openssl
二进制文件中构建了一个基准测试套件 。它可以通过speed
选项访问。它测试它在给定时间内可以执行的操作数,而不是执行给定数量的操作所需的时间。这让我感到非常理智,因为基准测试在慢速系统上运行的时间并不比在快速系统上运行时长得多。
要运行catchall基准测试,请运行它而不需要任何其他选项。
openssl speed
有两组结果。第一个报告每个算法每秒可以处理多少字节,第二个报告/验证周期所需的时间。以下是2.70GHz Intel Xeon E5的结果。
The 'numbers' are in 1000s of bytes per second processed.
type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes
md2 2540.48k 5184.66k 6989.57k 7651.67k 7872.51k
mdc2 0.00 0.00 0.00 0.00 0.00
md4 83248.41k 261068.18k 624212.82k 940529.32k 1128846.68k
md5 62411.57k 184768.36k 408835.75k 586930.52k 678061.98k
hmac(md5) 48713.62k 148265.56k 359626.67k 563050.68k 670255.79k
sha1 68829.72k 195087.40k 431001.51k 623344.42k 729505.79k
rmd160 38598.59k 96226.86k 183336.45k 235962.71k 257526.44k
rc4 480093.57k 678565.35k 783765.42k 818297.51k 838205.99k
des cbc 69500.17k 71184.75k 71491.50k 71641.77k 72010.15k
des ede3 26433.63k 26717.01k 26772.99k 26788.18k 26907.57k
idea cbc 95690.28k 99334.17k 100835.40k 100787.54k 100900.86k
seed cbc 76871.40k 77238.46k 77736.50k 77452.97k 77545.47k
rc2 cbc 48984.63k 49589.03k 50188.07k 50103.98k 50066.77k
rc5-32/12 cbc 0.00 0.00 0.00 0.00 0.00
blowfish cbc 122583.30k 129550.92k 130876.67k 131111.94k 131394.22k
cast cbc 109471.38k 114523.31k 115934.46k 116200.45k 116331.86k
aes-128 cbc 128352.23k 138604.76k 141173.42k 142832.25k 142682.79k
aes-192 cbc 107703.93k 114456.79k 117716.65k 118847.36k 118784.00k
aes-256 cbc 93374.87k 99521.51k 101198.51k 101382.49k 101635.41k
camellia-128 cbc 99270.57k 150412.42k 170346.33k 176311.91k 177913.86k
camellia-192 cbc 85896.60k 117356.52k 128556.97k 132759.72k 133425.83k
camellia-256 cbc 87351.27k 117695.15k 128972.03k 132130.47k 133455.87k
sha256 52372.61k 117766.12k 204825.69k 249974.10k 270914.90k
sha512 41278.19k 165820.37k 258298.69k 365981.70k 419864.58k
whirlpool 24803.02k 53047.07k 87593.90k 104570.54k 111159.98k
aes-128 ige 128441.31k 132981.88k 133269.08k 133738.15k 133966.51k
aes-192 ige 107831.37k 111507.07k 111800.66k 112156.67k 112219.48k
aes-256 ige 94382.07k 96351.17k 96750.68k 96958.46k 97446.44k
ghash 888644.92k 1452788.80k 1696788.74k 1763055.96k 1799086.49k
sign verify sign/s verify/s
rsa 512 bits 0.000049s 0.000004s 20547.1 248266.2
rsa 1024 bits 0.000194s 0.000011s 5146.0 90735.4
rsa 2048 bits 0.001194s 0.000037s 837.3 27277.1
rsa 4096 bits 0.008560s 0.000137s 116.8 7324.5
sign verify sign/s verify/s
dsa 512 bits 0.000048s 0.000046s 20667.7 21701.8
dsa 1024 bits 0.000113s 0.000126s 8831.9 7951.8
dsa 2048 bits 0.000362s 0.000430s 2762.0 2322.9
sign verify sign/s verify/s
256 bit ecdsa (nistp256) 0.0001s 0.0004s 9856.1 2524.4
384 bit ecdsa (nistp384) 0.0002s 0.0008s 5103.6 1191.7
521 bit ecdsa (nistp521) 0.0004s 0.0018s 2679.0 550.3
op op/s
256 bit ecdh (nistp256) 0.0003s 3063.8
384 bit ecdh (nistp384) 0.0007s 1447.3
521 bit ecdh (nistp521) 0.0015s 666.2
您可以直接运行任何特定于算法的子测试。
# test rsa speeds
openssl speed rsa
# do the same test on a two-way SMP system
openssl speed rsa -multi 2
如何对远程连接进行基准测试?
该s_time
选项允许您测试连接性能。最简单的调用将运行30秒,使用任何密码,并使用SSL握手来确定每秒的连接数,使用新的和重用的会话:
openssl s_time -connect remote.host:443
除了最简单的调用之外,还s_time
提供了各种各样的测试选项。
# retrieve remote test.html page using only new sessions
openssl s_time -connect remote.host:443 -www /test.html -new
# similar, using only SSL v3 and high encryption (see
# ciphers(1) man page for cipher strings)
openssl s_time \
-connect remote.host:443 -www /test.html -new \
-ssl3 -cipher HIGH
# compare relative performance of various ciphers in
# 10-second tests
IFS=":"
for c in $(openssl ciphers -ssl3 RSA); do
echo $c
openssl s_time -connect remote.host:443 \
-www / -new -time 10 -cipher $c 2>&1 | \
grep bytes
echo
done
如果您没有可供您使用的启用SSL的Web服务器,则可以使用该s_server
选项模拟一个。
# on one host, set up the server (using default port 4433)
openssl s_server -cert mycert.pem -www
# on second host (or even the same one), run s_time
openssl s_time -connect myhost:4433 -www / -new -ssl3
证书
如何生成自签名证书?
您首先需要决定是否要加密密钥。这样做意味着密钥受密码保护。
从好的方面来说,在密钥中添加密码使其更加安全,因此密钥对窃取密钥的人来说不太可能有用。然而,缺点是您必须将密码存储在文件中,或者每次要启动Web或ldap服务器时手动键入密码。
它说它违反了我通常的偏执性质,但我更喜欢未加密的密钥,因此每次启动安全守护程序时我都不必手动输入密码。(如果你后来厌倦了键入密码短语,解密你的密钥并不是非常困难。)
此示例将生成一个名为的文件mycert.pem
,该文件将包含私钥和基于它的公共证书。证书有效期为365天,密钥(由于 -nodes
选项)未加密。
openssl req \
-x509 -nodes -days 365 -sha256 \
-newkey rsa:2048 -keyout mycert.pem -out mycert.pem
使用此命令行调用,您将必须回答许多问题:国家/地区名称,州,城市等。棘手的问题是“公共名称”。您需要回答人们将通过哪个主机名或CNAME来解决服务器问题。这是非常重要的。如果您的Web服务器的真实主机名是mybox.mydomain.com但是人们将使用www.mydomain.com来解决该框,那么使用后一个名称来回答“公共名称”问题。
一旦您对提供给这些问题的答案感到满意,您就可以通过添加-subj
选项来编写整个脚本。我已经在下面的示例中包含了一些有关位置的信息,但是您真正需要包含的证书才是有用的主机名(CN)。
openssl req \
-x509 -nodes -days 365 -sha256 \
-subj '/C=US/ST=Oregon/L=Portland/CN=www.madboa.com' \
-newkey rsa:2048 -keyout mycert.pem -out mycert.pem
如何为VeriSign生成证书申请?
申请由VeriSign等认可的证书颁发机构签署的证书是一个复杂的官僚程序。在创建证书请求之前,您必须执行所有必需的文书工作。
与创建自签名证书的方法一样,您必须决定是否要在私钥上使用密码。下面的食谱假设你没有。您最终会得到两个文件:一个名为的新私钥mykey.pem
和一个名为的证书请求myreq.pem
。
openssl req \
-new -sha256 -newkey rsa:2048 -nodes \
-keyout mykey.pem -out myreq.pem
如果您已经获得了密钥并希望将其用于生成请求,则语法会更简单一些。
openssl req -new -key mykey.pem -out myreq.pem
同样,您也可以在命令行上提供主题信息。
openssl req \
-new -sha256 -newkey rsa:2048 -nodes \
-subj '/CN=www.mydom.com/O=My Dom, Inc./C=US/ST=Oregon/L=Portland' \
-keyout mykey.pem -out myreq.pem
在与VeriSign等机构打交道时,您需要特别注意确保在创建证书申请期间提供的信息完全正确。我从个人经验中知道,即使是在组织名称中用“和”代替“和”这一微不足道的差异也会拖延这个过程。
如果您愿意,可以仔细检查证书申请中提供的签名和信息。
# verify signature
openssl req -in myreq.pem -noout -verify -key mykey.pem
# check info
openssl req -in myreq.pem -noout -text
将密钥文件保存在安全的位置。您需要它才能使用VeriSign发送给您的证书。证书申请通常会粘贴到VeriSign的在线申请表中。
如何测试新证书?
该s_server
选项提供了一种简单但有效的测试方法。下面的示例假设您已将密钥和证书合并到一个名为的文件中mycert.pem
。
首先,在将使用证书的计算机上启动测试服务器。默认情况下,服务器将侦听端口4433; 你可以使用-accept
选项改变它。
openssl s_server -cert mycert.pem -www
如果服务器在没有投诉的情况下启动,那么证书可以用于生产用途的可能性很大。
您还可以点在测试服务器,Web浏览器如, https://yourserver:4433/
。不要忘记指定“https”协议; 普通的“http”将无法正常工作。您应该会看到一个页面,列出了可用的各种密码以及有关您的连接的一些统计信息。大多数现代浏览器也允许您检查证书。
如何检索远程证书?
如果合并openssl
及sed
,您可以通过一个壳状的衬垫或一个简单的脚本获取远程证书。
#!/bin/sh
#
# usage: retrieve-cert.sh remote.host.name [port]
#
REMHOST=$1
REMPORT=${2:-443}
echo |\
openssl s_client -connect ${REMHOST}:${REMPORT} 2>&1 |\
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'
反过来,您可以将这些信息传回管理,openssl
例如检查所有活动证书上的日期。
#!/bin/sh
#
for CERT in \
www.yourdomain.com:443 \
ldap.yourdomain.com:636 \
imap.yourdomain.com:993
do
echo |\
openssl s_client -connect ${CERT} 2>/dev/null |\
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' |\
openssl x509 -noout -subject -dates
done
如何从证书中提取信息?
SSL证书包含大量信息:发行者,有效日期,主题和一些核心加密内容。该x509
子命令是获取这些信息的入口点。以下示例均假定您要检查的证书存储在名为的文件中cert.pem
。
使用该-text
选项将为您提供全面的信息。
openssl x509 -text -in cert.pem
其他选项将提供更有针对性的数据集。
# who issued the cert?
openssl x509 -noout -in cert.pem -issuer
# to whom was it issued?
openssl x509 -noout -in cert.pem -subject
# for what dates is it valid?
openssl x509 -noout -in cert.pem -dates
# the above, all at once
openssl x509 -noout -in cert.pem -issuer -subject -dates
# what is its hash value?
openssl x509 -noout -in cert.pem -hash
# what is its MD5 fingerprint?
openssl x509 -noout -in cert.pem -fingerprint
如何导出或导入PKCS#12证书?
PKCS#12文件可以由许多应用程序导入和导出,包括Microsoft IIS。它们通常与文件扩展名相关联.pfx
。
要创建PKCS#12证书,您需要私钥和证书。在转换过程中,您将有机会在证书上放置“导出密码”(如果您选择,可以为空)。
# create a file containing key and self-signed certificate
openssl req \
-x509 -sha256 -nodes -days 365 \
-newkey rsa:2048 -keyout mycert.pem -out mycert.pem
# export mycert.pem as PKCS#12 file, mycert.pfx
openssl pkcs12 -export \
-out mycert.pfx -in mycert.pem \
-name "My Certificate"
如果有人向您发送PKCS#12以及使用它所需的任何密码,您可以将其导出为标准PEM格式。
# export certificate and passphrase-less key
openssl pkcs12 -in mycert.pfx -out mycert.pem -nodes
# same as above, but you’ll be prompted for a passphrase for
# the private key
openssl pkcs12 -in mycert.pfx -out mycert.pem
证书验证
与OpenSSL库链接的应用程序可以验证由公认的证书颁发机构(CA)签名的证书。
我如何验证证书?
使用该verify
选项验证证书。
openssl verify cert.pem
如果您的本地OpenSSL安装识别证书或其签名权限以及其他所有内容(日期,签名链等)签出,您将收到一条简单的OK消息。
$ openssl验证remote.site.pem
remote.site.pem:好的
如果有任何不妥之处,您会看到一些错误消息,其中包含对问题的简短描述,例如,
-
error 10 at 0 depth lookup:certificate has expired
。证书通常在有限的时间内发出 - 通常只有一年 - 并且openssl
如果证书已过期则会投诉。 -
error 18 at 0 depth lookup:self signed certificate
。除非您例外,否则 OpenSSL不会验证自签名证书。
OpenSSL识别哪些证书颁发机构?
当为您的系统构建OpenSSL时,它配置了“OpenSSL文件的目录。”(这是--openssldir
传递给配置脚本的选项,适用于您的实际操作类型。)这是通常包含有关证书颁发机构信息的目录。系统信任。
此目录的默认位置是/usr/local/ssl
的,但大多数厂商把它放在其他地方,例如,/usr/share/ssl
(红帽/ Fedora的), /etc/ssl
(Gentoo的),/usr/lib/ssl
(Debian的),或 /System/Library/OpenSSL
(在Macintosh OS X)。
使用该version
选项可标识安装使用的目录(标记为OPENSSLDIR)。
openssl version -d
在该目录和一个名为的子目录中certs
,您可能会找到三种不同类型的文件中的一种或多种。
-
一个名为的大型文件
cert.pem
,来自VeriSign和Thawte等公认证书颁发机构的许多证书的综合集合。 -
certs
子目录中的一些小文件以.pem
文件扩展名命名,每个文件都包含来自单个CA的证书。 -
certs
子目录中的一些符号链接,文件名如晦涩052eae11.0
。每个.pem
文件通常都有一个这样的链接 。隐藏文件名的第一部分实际上是基于
.pem
其指向的文件中的证书的哈希值。文件扩展名只是一个迭代器,因为从理论上讲,多个证书可以生成相同的哈希值。例如,在我的Gentoo系统上,有一个名为的符号链接
f73e89fd.0
指向一个名为的文件vsignss.pem
。果然,该文件中的证书生成的哈希等同于符号链接的名称:
$ openssl x509 -noout -hash -in vsignss.pem
f73e89fd
当应用程序遇到远程证书时,它通常会检查是否可以cert.pem
在证书的哈希值后面的文件中找到证书,如果没有,则查看是否可以找到证书。如果找到,则认为证书已经过验证。
有趣的是,有些应用程序(如Sendmail)允许您在运行时指定您信任的证书的位置,而其他应用程序(如Pine)则不允许。
如何让OpenSSL识别/验证证书?
将包含您要信任的证书的文件放入上面certs
讨论的 目录中。然后创建基于哈希的符号链接。这是一个可以做到这一点的小脚本。
#!/bin/sh
#
# usage: certlink.sh filename [filename ...]
for CERTFILE in $*; do
# make sure file exists and is a valid cert
test -f "$CERTFILE" || continue
HASH=$(openssl x509 -noout -hash -in "$CERTFILE")
test -n "$HASH" || continue
# use lowest available iterator for symlink
for ITER in 0 1 2 3 4 5 6 7 8 9; do
test -f "${HASH}.${ITER}" && continue
ln -s "$CERTFILE" "${HASH}.${ITER}"
test -L "${HASH}.${ITER}" && break
done
done
命令行客户端和服务器
在s_client
和s_server
选项提供了一个方法来启动启用了SSL的命令行客户端和服务器。本文档中还有其他使用示例,但本节仅专用于它们。
在本节中,我假设您熟悉有争议的特定协议:SMTP,HTTP等。解释它们超出了本文的范围。
如何连接到安全的SMTP服务器?
您可以使用命令行从命令行测试甚至使用启用SSL的SMTP服务器s_client option
。
安全SMTP服务器在最多三个端口上提供安全连接:25(TLS),465(SSL)和587(TLS)。在0.9.7版本的某个时候, openssl
二进制文件在与SMTP服务器通信时可以使用STARTTLS。
# port 25/TLS; use same syntax for port 587
openssl s_client -connect remote.host:25 -starttls smtp
# port 465/SSL
openssl s_client -connect remote.host:465
RFC821建议(虽然它没有明确指定)两个字符“<CRLF>”作为行终止符。大多数邮件代理不关心这一点,并接受“<LF>”或“<CRLF>”作为行终止符,但Qmail没有。如果您想遵守RFC821的信函和/或与Qmail通信,请使用以下-crlf
选项:
openssl s_client -connect remote.host:25 -crlf -starttls smtp
如何使用SNI连接到Web服务器?
IPv4地址的短缺促使开发了HTTP 1.1标准,因此单个IP地址可以托管多个基于名称的虚拟服务器。
后来,同样的地址短缺导致 了TLS协议的服务器名称指示(SNI)扩展的发展。使用SNI时,客户端在TLS协商期间发送它想要联系的主机名。然后,启用SNI的服务器能够提供具有匹配主机名的证书,以供客户端验证。
openssl
通过指定-servername
选项启用SNI 。
openssl s_client -connect www.massivehost.com:443 -servername www.myhost.com
如何连接到安全[无论]服务器?
连接到不同类型的启用SSL的服务器与上面概述的操作基本相同。截至本文撰写之日, openssl
仅支持带有SMTP服务器的命令行TLS,因此您必须使用与任何其他协议的简单SSL连接。
# https: HTTP over SSL
openssl s_client -connect remote.host:443
# ldaps: LDAP over SSL
openssl s_client -connect remote.host:636
# imaps: IMAP over SSL
openssl s_client -connect remote.host:993
# pop3s: POP-3 over SSL
openssl s_client -connect remote.host:995
如何从命令行设置SSL服务器?
该s_server
选项允许您从命令行设置启用SSL的服务器,但我不建议将其用于除测试或调试之外的任何其他内容。如果您需要围绕其他不安全服务器的生产质量包装器,请查看 Stunnel。
s_server
当您拥有证书时,该选项最有效; 没有一个它是相当有限的。
# the -www option will sent back an HTML-formatted status page
# to any HTTP clients that request a page
openssl s_server -cert mycert.pem -www
# the -WWW option "emulates a simple web server. Pages will be
# resolved relative to the current directory." This example
# is listening on the https port, rather than the default
# port 4433
openssl s_server -accept 443 -cert mycert.pem -WWW
摘要
使用该dgst
选项生成摘要是您可以使用openssl
二进制文件完成的更直接的任务之一。事实上,生成摘要通常是为了做同样的事情,你可以找到特殊用途的二进制文件。
如何创建文件的MD5或SHA1摘要?
使用该dgst
选项创建摘要。我见过几个系统,其中OpenSSL dgst(1)手册页没有准确报告通过本地openssl
二进制文件提供的摘要功能。我建议运行openssl dgst -h
以查看实际可用的摘要。
# MD5 digest
openssl dgst -md5 filename
# SHA1 digest
openssl dgst -sha1 filename
# SHA256 digest
openssl dgst -sha256 filename
md5sum
虽然输出格式不同,但MD5摘要与使用广泛使用的命令创建的摘要相同 。
$ openssl dgst -md5 foo-2.23.tar.gz
MD5(foo-2.23.tar.gz)= 81eda7985e99d28acd6d286aa0e13e07
$ md5sum foo-2.23.tar.gz
81eda7985e99d28acd6d286aa0e13e07 foo-2.23.tar.gz
SHA1摘要和sha1sum
应用程序的输出也是如此。
$ openssl dgst -sha1 foo-2.23.tar.gz
SHA1(foo-2.23.tar.gz)= e4eabc78894e2c204d788521812497e021f45c08
$ sha1sum foo-2.23.tar.gz
e4eabc78894e2c204d788521812497e021f45c08 foo-2.23.tar.gz
如何签署摘要?
如果您希望确保未经您的许可不会修改您创建的摘要,则可以使用您的私钥对其进行签名。以下示例假定您要对所调用文件的SHA256总和进行签名foo-1.23.tar.gz
。
# signed digest will be foo-1.23.tar.gz.sha1
openssl dgst -sha256 \
-sign mykey.pem
-out foo-1.23.tar.gz.sha1 \
foo-1.23.tar.gz
如何验证签名摘要?
要验证签名摘要,您需要从中获取摘要的文件,签名摘要和签名者的公钥。
# to verify foo-1.23.tar.gz using foo-1.23.tar.gz.sha1
# and pubkey.pem
openssl dgst -sha256 \
-verify pubkey.pem \
-signature foo-1.23.tar.gz.sha1 \
foo-1.23.tar.gz
如何创建Apache摘要密码条目?
Apache的HTTP摘要认证功能需要特殊的密码格式。Apache附带了该htdigest
实用程序,但它只会写入文件,而不是标准输出。在与远程用户合作时,他们有时可以在他们信任的计算机上生成密码哈希,然后将其邮寄以包含在本地密码数据库中。
密码数据库的格式相对简单:以冒号分隔的用户名列表,授权域(由Apache AuthName指令指定),以及这两个项的MD5摘要和密码。下面是一个复制输出的脚本 htdigest
,除了输出写入标准输出。它利用了该dgst
选项从标准输入读取的能力。
#!/bin/bash
echo "Create an Apache-friendly Digest Password Entry"
echo "-----------------------------------------------"
# get user input, disabling tty echoing for password
read -p "Enter username: " UNAME
read -p "Enter Apache AuthName: " AUTHNAME
read -s -p "Enter password: " PWORD; echo
printf "\n%s:%s:%s\n" \
"$UNAME" \
"$AUTHNAME" \
$(printf "${UNAME}:${AUTHNAME}:${PWORD}" | openssl dgst -md5)
还有哪些其他类型的摘要?
使用内置list-message-digest-commands
选项获取本地OpenSSL安装可用的摘要类型列表。
openssl list-message-digest-commands
与dgst(1)手册页中的列表一样,此列表可能已过时。请小心!
加密/解密
我如何base64编码的东西?
使用该enc -base64
选项。
# send encoded contents of file.txt to stdout
openssl enc -base64 -in file.txt
# same, but write contents to file.txt.enc
openssl enc -base64 -in file.txt -out file.txt.enc
也可以对字符串值进行快速命令行编码:
$ echo“编码我”| openssl enc -base64
ZW5jb2RlIG1lCg ==
请注意,它echo
会以静默方式将换行符附加到字符串中。-n
如果要避免这种情况,请考虑使用其选项,如果您尝试对密码或身份验证字符串进行编码,这可能很重要。
$ echo -n“编码我”| openssl enc -base64
ZW5jb2RlIG1l
使用-d
(解码)选项来反转该过程。
$ echo“ZW5jb2RlIG1lCg ==”| openssl enc -base64 -d
encode me
我如何简单地加密文件?
使用像GPG这样的工具可能更好地完成简单的文件加密。但是,您可能有机会加密文件而无需构建或使用密钥/证书结构。你想要记住的只是一个密码。它几乎可以这么简单 - 如果你还记得你用于加密的密码。
要选择密码,请参阅enc(1)手册页。更简单(也许更准确),您可以openssl
通过两种方式之一索取列表。
# see the list under the 'Cipher commands' heading
openssl -h
# or get a long list, one cipher per line
openssl list-cipher-commands
选择密码后,您还必须决定是否要对数据进行base64编码。这样做意味着加密数据可以粘贴到电子邮件中。否则,输出将是二进制文件。
# encrypt file.txt to file.enc using 256-bit AES in CBC mode
openssl enc -aes-256-cbc -salt -in file.txt -out file.enc
# the same, only the output is base64 encoded for, e.g., e-mail
openssl enc -aes-256-cbc -a -salt -in file.txt -out file.enc
要解密file.enc
您或文件的收件人,需要记住密码和密码。
# decrypt binary file.enc
openssl enc -d -aes-256-cbc -in file.enc
# decrypt base64-encoded version
openssl enc -d -aes-256-cbc -a -in file.enc
如果您希望每次加密或解密文件时都避免键入密码,openssl(1)手册页将在“PASS PHRASE ARGUMENTS”标题下提供详细信息。密码参数的格式非常简单。
# provide password on command line
openssl enc -aes-256-cbc -salt -in file.txt \
-out file.enc -pass pass:mySillyPassword
# provide password in a file
openssl enc -aes-256-cbc -salt -in file.txt \
-out file.enc -pass file:/path/to/secret/password.txt
错误
如何解释SSL错误消息?
浏览系统日志,您会看到一些明显与OpenSSL或加密相关的错误消息:
sshd[31784]: error: RSA_public_decrypt failed: error:0407006A:lib(4):func(112):reason(106)
sshd[770]: error: RSA_public_decrypt failed: error:0407006A:lib(4):func(112):reason(106)
找出问题的第一步是使用errstr
选项来表示错误代码。代码编号位于“error:”和“:lib”之间。在这种情况下,它是0407006A。
$ openssl errstr 0407006A
error:0407006A:rsa routines:RSA_padding_check_PKCS1_type_1:block type is not 01
如果您有完整的OpenSSL安装,包括所有开发文档,您可以在那里开始调查。在此示例中,RSA_padding_add_PKCS1_type_1(3)手册页将通知您PKCS#1涉及签名的块方法。在那之后,当然,您需要了解应用程序的源代码,以确定何时会收到这些类型的数据包。
按键
如何生成RSA密钥?
使用该genrsa
选项。
# default 1024-bit key, sent to standard output
openssl genrsa
# 2048-bit key, saved to file named mykey.pem
openssl genrsa -out mykey.pem 2048
# same as above, but encrypted with a passphrase
openssl genrsa -des3 -out mykey.pem 2048
如何生成公共RSA密钥?
使用该rsa
选项可生成私有RSA密钥的公共版本。
openssl rsa -in mykey.pem -pubout
如何生成DSA密钥?
构建DSA密钥需要参数文件,并且DSA验证操作比其RSA对应文件慢,因此它们不像RSA密钥那样广泛使用。
如果您只打算构建单个DSA密钥,则只需使用dsaparam
子命令一步即可完成。
# key will be called dsakey.pem
openssl dsaparam -noout -out dsakey.pem -genkey 1024
另一方面,如果您要创建多个DSA密钥,则可能需要在生成密钥之前构建共享参数文件。构建参数可能需要一段时间,但一旦构建,密钥生成就会很快完成。
# create parameters in dsaparam.pem
openssl dsaparam -out dsaparam.pem 1024
# create first key
openssl gendsa -out key1.pem dsaparam.pem
# and second ...
openssl gendsa -out key2.pem dsaparam.pem
如何创建椭圆曲线键?
在0.9.8版本的OpenSSL中添加了使用椭圆曲线加密的例程。生成EC密钥涉及该ecparam
选项。
openssl ecparam -out key.pem -name prime256v1 -genkey
# openssl can provide full list of EC parameter names suitable for
# passing to the -name option above:
openssl ecparam -list_curves
如何从密钥中删除密码?
也许你已经厌倦了每次安全守护进程启动时输入你的密码。您可以使用rsa
或dsa
选项解密密钥,删除密码短语要求,具体取决于您在创建私钥时选择的签名算法。
如果您创建了一个RSA密钥并将其存储在一个名为的独立文件中 key.pem
,那么这里是如何将相同密钥的解密版本输出到一个名为的文件newkey.pem
。
# you'll be prompted for your passphrase one last time
openssl rsa -in key.pem -out newkey.pem
通常,您将私钥和公共证书存储在同一文件中。如果它们存储在一个名为的文件中mycert.pem
,您可以构建一个newcert.pem
分两步调用的解密版本。
# you'll need to type your passphrase once more
openssl rsa -in mycert.pem -out newcert.pem
openssl x509 -in mycert.pem >>newcert.pem
密码哈希
使用该passwd
选项,您可以生成与传统/etc/passwd
文件,较新式 /etc/shadow
文件和Apache密码文件互操作的密码哈希。
如何生成加密样式的密码哈希?
您可以非常简单地生成新哈希:
$ openssl passwd MySecret
8E4vqBR4UOYF。
如果您知道现有密码的“salt”,则可以复制哈希。
$ openssl passwd
-salt 8E MySecret 8E4vqBR4UOYF。
如何生成阴影式密码哈希?
较新的Unix系统使用更安全的基于MD5的散列机制,该机制使用八个字符的盐(与传统的crypt()中的两个字符的盐相比 - 样式哈希)。使用-1
选项生成它们仍然很简单:
$ openssl passwd -1 MySecret
$ 1 $ sXiKzkus $ haDZ9JpVrRHBznY5OxB82。
在这种情况下,这种格式的盐由第二和第三美元符号之间的八个字符组成sXiKzkus
。因此,您还可以使用已知的salt和密码复制哈希。
$ openssl passwd -1 -salt sXiKzkus MySecret
$ 1 $ sXiKzkus $ haDZ9JpVrRHBznY5OxB82。
质数
当前的加密技术在很大程度上依赖于素数的生成和测试,因此OpenSSL库包含几个处理素数的例程就不足为奇了。从版本0.9.7e(左右)开始,该prime
选项已添加到openssl二进制文件中。
如何测试数字是否为素数?
将号码传递给prime
选项。请注意,openssl返回的数字将是十六进制格式,而不是十进制格式。
$ openssl prime 119054759245460753
1A6F7AC39A53511 is not prime
您也可以直接传递十六进制数字。
$ openssl prime -hex 2f
2F is prime
如何生成一组素数?
从OpenSSL版本1.0.0开始,openssl二进制文件可以生成指定长度的素数:
$ openssl prime -generate -bits 64
16148891040401035823
$ openssl prime -generate -bits 64 -hex
E207F23B9AE52181
如果您使用的是早于1.0.0的OpenSSL版本,则必须将一堆数字传递给openssl并查看其中的内容。该seq
实用程序在此功能中很有用。
# define start and ending points
AQUO=10000
ADQUEM=10100
for N in $(seq $AQUO $ADQUEM); do
# use bc to convert hex to decimal
openssl prime $N | awk '/is prime/ {print "ibase=16;"$1}' | bc
done
随机数据
如何生成随机数据?
使用该rand
选项可生成二进制或base64编码的数据。
# write 128 random bytes of base64-encoded data to stdout
openssl rand -base64 128
# write 1024 bytes of binary random data to a file
openssl rand -out random-data.bin 1024
# seed openssl with semi-random bytes from browser cache
cd $(find ~/.mozilla/firefox -type d -name Cache)
openssl rand -rand $(find . -type f -printf '%f:') -base64 1024
在带有/dev/urandom
设备和GNU副本的Unix 机器head
或最新版本的BSD上head
,您可以获得类似的效果,通常具有更好的熵:
# get 32 bytes from /dev/urandom and base64 encode them
head -c 32 /dev/urandom | openssl enc -base64
通过使用strings
以下方法,您可以获得比使用Base64编码提供的更多种类的字符:
# get 32 bytes from /dev/random, grab printable characters, and
# strip whitespace. using echo and the shell's command substitution
# will nicely strip out newlines.
echo $(head -c 32 /dev/random | strings -1) | sed 's/[[:space:]]//g'
确保你知道之间的权衡random
,并urandom
依靠他们真正关键的熵之前的设备。有关详细信息,请参阅Linux和BSD系统上的随机(4)手册页,或Solaris上的随机(7D)。
S / MIME
S / MIME是发送和接收安全MIME数据的标准,尤其是在电子邮件中。自动S / MIME功能已添加到相当多的电子邮件客户端,但openssl
可以使用该smime
选项提供命令行S / MIME服务。
请注意,smime(1)手册页中的文档 包含许多好的示例。
如何验证签名的S / MIME邮件?
验证签名邮件非常简单。使用邮件客户端将签名的邮件保存到文件中。在此示例中,我假设该文件已命名msg.txt
。
openssl smime -verify -in msg.txt
如果发件人的证书由您的OpenSSL基础结构信任的证书颁发机构签名,您将看到一些邮件头,邮件的副本以及说明的结束行Verification successful
。
如果未经授权方修改了消息,则输出将以失败消息结束,表明摘要和/或签名与您收到的内容不匹配:
Verification failure
23016:error:21071065:PKCS7 routines:PKCS7_signatureVerify:digest
failure:pk7_doit.c:804:
23016:error:21075069:PKCS7 routines:PKCS7_verify:signature
failure:pk7_smime.c:265:
同样,如果您的OpenSSL基础架构无法识别发件人的证书,您将收到类似的错误:
Verification failure
9544:error:21075075:PKCS7 routines:PKCS7_verify:certificate verify
error:pk7_smime.c:222:Verify error:self signed certificate
大多数电子邮件客户端在附加到邮件的签名中发送公共证书的副本。从命令行,您可以自己查看证书数据。您将使用该smime -pk7out
选项将PKCS#7证书的副本传送回pkcs7
选项。这很奇怪,但它很有效。
openssl smime -pk7out -in msg.txt | \
openssl pkcs7 -text -noout -print_certs
如果您想提取通讯员证书的副本以供长期使用,请仅使用该管道的第一部分。
openssl smime -pk7out -in msg.txt -out her-cert.pem
此时,您可以将其集成到OpenSSL基础架构中,也可以将其保存在特定用途的某个地方。
openssl smime -verify -in msg.txt -CAfile /path/to/her-cert.pem
如何加密S / MIME邮件?
假设某人向您发送了她的公共证书,并要求您加密一些消息给她。你已将她的证书保存为 her-cert.pem
。您已将回复保存为my-message.txt
。
要获得默认 - 虽然相当弱的RC2-40加密,您只需告诉 openssl
消息和证书的位置。
openssl smime her-cert.pem -encrypt -in my-message.txt
如果您非常确定您的远程通讯员具有强大的SSL工具包,您可以指定更强大的加密算法,如三重DES:
openssl smime her-cert.pem -encrypt -des3 -in my-message.txt
默认情况下,加密邮件(包括邮件头)将发送到标准输出。使用-out
选项或shell将其重定向到文件。或者,更加棘手,直接输出到输出sendmail
。
openssl smime her-cert.pem \
-encrypt \
-des3 \
-in my-message.txt \
-from 'Your Fullname <you@youraddress.com>' \
-to 'Her Fullname <her@heraddress.com>' \
-subject 'My encrypted reply' |\
sendmail her@heraddress.com
如何签署S / MIME邮件?
如果您不需要对整个邮件进行加密,但您确实需要对其进行签名,以确保收件人可以确保邮件的完整性,则该配方与加密类似。主要区别在于您需要拥有自己的密钥和证书,因为您无法使用收件人的证书进行任何签名。
openssl smime \
-sign \
-signer /path/to/your-cert.pem \
-in my-message.txt \
-from 'Your Fullname <you@youraddress.com>' \
-to 'Her Fullname <her@heraddress.com>' \
-subject 'My signed reply' |\
sendmail her@heraddress.com
进一步阅读
虽然需要时间来阅读它们并弄清楚它们之间的关系,但是OpenSSL手册页是最好的起点:asn1parse(1), ca(1), ciphers(1), config(5), crl(1), crl2pkcs7(1), dgst(1), dhparam(1), dsa(1), dsaparam(1), ec(1), ecparam(1), enc(1), errstr(1), gendsa(1),genpkey(1), genrsa(1), nseq(1), ocsp(1), openssl(1), passwd(1), pkcs12(1), pkcs7(1), pkcs8(1), pkey(1), pkeyparam(1), pkeyutl(1), rand(1), req(1), rsa(1),rsautl(1), s_client(1), s_server(1), s_time(1), sess_id(1), smime(1), speed(1), spkac(1), ts(1), tsget(1), verify(1), version(1), x509(1), x509v3_config(5).
欢迎评论
这份文件已在网上发表了十多年。它的大部分发展都归功于我自己的好奇心,但是通过读者提出的主动建议,已经取得了一些重要的改进。因此,请允许我明确表示对本文档的意见和建议表示赞赏,可以通过heinlein@madboa.com与作者联系。