OpenSSL Command-Line HOWTO

https://www.madboa.com/geek/openssl/#introduction

内容

介绍

OpenSSLopenssl附带的命令行二进制文件 可以执行各种加密操作。它可以在脚本中派上用场,也可以用于完成一次性命令行任务。

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”将无法正常工作。您应该会看到一个页面,列出了可用的各种密码以及有关您的连接的一些统计信息。大多数现代浏览器也允许您检查证书。

如何检索远程证书?

如果合并opensslsed,您可以通过一个壳状的衬垫或一个简单的脚本获取远程证书。

#!/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,您可能会找到三种不同类型的文件中的一种或多种。

  1. 一个名为的大型文件cert.pem,来自VeriSign和Thawte等公认证书颁发机构的许多证书的综合集合。

  2. certs子目录中的一些小文件以.pem 文件扩展名命名,每个文件都包含来自单个CA的证书。

  3. 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_clients_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选项启用S​​NI 。

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

如何从密钥中删除密码?

也许你已经厌倦了每次安全守护进程启动时输入你的密码。您可以使用rsadsa选项解密密钥,删除密码短语要求,具体取决于您在创建私钥时选择的签名算法。

如果您创建了一个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 <[email protected]>' \
  -to 'Her Fullname <[email protected]>' \
  -subject 'My encrypted reply' |\
sendmail [email protected]

如何签署S / MIME邮件?

如果您不需要对整个邮件进行加密,但您确实需要对其进行签名,以确保收件人可以确保邮件的完整性,则该配方与加密类似。主要区别在于您需要拥有自己的密钥和证书,因为您无法使用收件人的证书进行任何签名。

openssl smime \
  -sign \
  -signer /path/to/your-cert.pem \
  -in my-message.txt \
  -from 'Your Fullname <[email protected]>' \
  -to 'Her Fullname <[email protected]>' \
  -subject 'My signed reply' |\
sendmail [email protected]

进一步阅读

虽然需要时间来阅读它们并弄清楚它们之间的关系,但是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).

欢迎评论

这份文件已在网上发表了十多年。它的大部分发展都归功于我自己的好奇心,但是通过读者提出的主动建议,已经取得了一些重要的改进。因此,请允许我明确表示对本文档的意见和建议表示赞赏,可以通过[email protected]与作者联系

猜你喜欢

转载自blog.csdn.net/wxh0000mm/article/details/88949269