OpenSSl是一个开源项目,包括密码库和SSL/TLS工具集。它已是在安全领域的事实标准,并且拥有比较长的历史,现在几乎所有的服务器软件和很多客户端都在使用openssl,其中基于命令行的工具是进行加密、证书管理以及测试最常用到的软件。功能主要包括:

  • 创建RSA,DSA,DH密钥对
  • 公共密钥的加密操作
  • 创建X509证书,CSR和CRLs
  • 生成消息摘要
  • 使用加密算法加密解密
  • SSL/TLS服务器客户端测试
  • 处理S/MIME签名或者加密邮件
  • 时间戳记的请求,生成和验证

由于美国加密算法的限制,CENTOS的OpenSSL不支持IDEA,RC5和MDC2。以下为其配置文件openssl.cnf的位置以及默认的主要目录

网络安全-openssl工具_字段

基础

linux上基本已经安装了OpenSSL,无需再安装,而windows上OpenSSL则需要另外单独配置。本次是基于centos8的上的OpenSSL进行测试。

确定OpenSSL版本和配置

openssl version

网络安全-openssl工具_主机名_02

不同的操作系统会经常修改OpenSSL的代码,主要是修复一些已知的漏洞,然而项目的名称和版本号经常保持原样。

可以使用-a参数获取完整的版本信息。

openssl version -a

输出如下:

OpenSSL 1.1.1k  FIPS 25 Mar 2021
built on: Wed Aug 31 14:57:14 2022 UTC
platform: linux-x86_64
options: bn(64,64) md2(char) rc4(16x,int) des(int) idea(int) blowfish(ptr)
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -O3 -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -Wa,--noexecstack -Wa,--generate-missing-build-notes=yes -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DZLIB -DNDEBUG -DPURIFY -DDEVRANDOM="\"/dev/urandom\"" -DSYSTEM_CIPHERS_FILE="/etc/crypto-policies/back-ends/openssl.config"
OPENSSLDIR: "/etc/pki/tls"
ENGINESDIR: "/usr/lib64/engines-1.1"
Seeding source: os-specific
engines: rdrand dynamic

上面OPENSSLDIR:"/etc/pki/tls"是默认情况下查找配置和证书的目录。在centos8中,该位置是/etc/ssl的别名,系统会在其中保存TLS相关的文件。

网络安全-openssl工具_字段_03

misc目录包含一些补充脚本,其中最为有用的的脚本允许你实现一个私有证书的颁发机构。


查看可用命令

OpenSSL包含了很多密码相关的工具,通过以下命令显示可用命令。

openssl help

网络安全-openssl工具_字段_04

列出了所有可以使用的工具,如果对于某个命令,想获取更加详细的信息,可以使用man加上工具的名称。

  • Standard commands 标准命令
  • Message Digest commands 消息摘要命令
  • Cipher commands 加密命令

命令

说明

openssl enc <算法名称> -k <加密口令> -e in <明文文件名> -out <加密文件名> 

对文件进行对称加密

openssl enc <算法名称> -k <加密口令> -d in <明文文件名> -out <加密文件名>

对文件进行对称解密

openssl dgst <算法名称> <文件名>

对文件信息生成摘要

密钥和证书管理

OpenSSL能够运行并支持SSL的web服务器,整个过程包含以下三个步骤:

  1. 生成强加密的私钥
  2. 创建证书签名申请(certificate signing request,CSR),并且发送给CA
  3. 在web服务器上安装CA提供的证书

PKI,CA与证书管理

PKI (Public Key Infrastructure,公共密钥设施),是一个基于非对称加密技术实现并提供安全服务的具有通用行的安全设施,它通过一系列组件和规程,支持利用数字证书管理密钥并建立新人关系。PKI同时融合了Hash算法以及对称加密技术。

PKI由多个组件构成,其中最基本的组件是数字证书,它就是PKI管理的对象。证书是将所有者的身份信息和其所拥有的公钥进行绑定的文件。证书文件还包括颁发证书的权威机构(CA)对该证书的签名。通过签名保证了证书的合法性和有效性,当前,通常使用x.509 V3标准的证书,内容如下所示:

字段

说明

版本

证书格式版本号,例如V1

序列号

证书的序列号,是证书的唯一标识

签名算法

CA用于颁发证书所使用的签名和Hash算法,如RSA,SHA-1

颁发者

CA的唯一标识名

有效期

证书的有效时间段,包括证书的生效和过期时间

使用者

证书申请者的唯一标识信息

也称为DN,包含必须的CN和一些其他的可选属性

公钥

证书申请者的公钥信息和加密属性

颁发者唯一的标识符

CA的唯一标识符(可选)

使用者位置的标识符

证书申请者的唯一标识符(可选)

扩展部分

可选的扩展的属性

CA签名

CA对颁发证书的数字签名

按照证书签名者的身份不同,证书可以分为3类

  1. 自签名证书,通常在实验环境使用
  2. 由本地CA签署的证书,
  3. 由可信的CA签署的证书

CA,证书权威机构,是PKI中受信任的第三方实体,它是信任起点,各个实体必须对CA高度信任,因为要通过CA的担保来认证其他实体。

CA是PKI的核心,主要任务包括:

  • 证书的颁发,吊销,更新和续订等
  • CRL,证书吊销列表的管理和发布
  • OSCP,在线证书状态协议,的管理和发布
  • 证书的存储以及事件日志记录等。



生成密钥

在使用公钥之前第一步是先生成一个私钥,在生成私钥的时候,必须有以下几项:

  • 密钥算法

支持RSA,DSA和ECDSA密钥,但是在实际使用场景中不是所有的密钥类型都适用的。对于web服务器的密钥,一般都选RSA,因为DSA一般因为效率问题会限制在1024位,而且IE浏览器不支持更长的DSA密钥。ECDSA还没有被大部分的CA支持,对于SSH来说,一般都是使用DSA和RSA

  • 密钥长度

默认的密钥长度一般都不够安全,所以需要手动指定要配置的密钥长度。例如RSA密钥的默认长度是512位,不够安全。一般认为2048位的RSA密钥是安全的,DSA密钥也应该不少于2048位,ECDSA密钥则应该在256位以上。

  • 密码

应该使用密码去保存密钥,虽然这个只是一个可选项,受密码保护的密钥可以安全的存储传输以及备份,但是密钥的密码也经常带来不便。例如每次需要重启web服务器的时候就会要求输入密码,因此在现时中无法使用。

使用genrsa命令来生成RSA密钥

openssl genrsa -aes128 -out fd.key 2048

网络安全-openssl工具_标识符_05

这里指定私钥使用AES-128算法来加密保存,也可以使用AES-192或者AES-256,建议不要使用其他算法,如DES,3DES,SEED。

这里会提示需要创建密钥的密码,并重复确认。

以上的输出结果e值代表公用指数,默认情况下会设为64537,它会显著的提供高RSA的验证功能。

私钥以所谓的PEM格式存储,该格式仅包含文本。

cat fd.key

网络安全-openssl工具_标识符_06

初略看私钥是一堆随机数,其实并不是,可以使用rsa命令解析出私钥的结构

openssl rsa -text -in fd.key  #提示需要输入密钥密码

网络安全-openssl工具_标识符_07

网络安全-openssl工具_标识符_08

网络安全-openssl工具_标识符_09

网络安全-openssl工具_主机名_10

如果需要单独查看密钥的公开部分,可以使用如下命令

openssl rsa -in fd.key -pubout -out fd-public.key

 查看生成的文件,会发现有明显的标识,表示这部分确实是公开的信息。

网络安全-openssl工具_字段_11

DSA的密钥生成分成两个部分,先生成DSA的参数,然后再生成密钥,如下所示:

openssl dsaparam -genkey 2048 | openssl dsa -out dsa.key -aes128

网络安全-openssl工具_主机名_12

这种方式可以生成一个受密码保护的密钥,而不会在磁盘上留下临时文件DSA参数,或者临时的密钥。

创建ECDSA密钥的过程是类似的,但是不能创建任意长度的密钥。对于每个密钥,需要选择一个命名曲线(named curve),它可以控制密钥的长度,同时也限定了椭圆曲线的参数。

openssl ecparam -genkey -name secp256r1 | openssl ec -out ec.key -ase128

网络安全-openssl工具_标识符_13

OpenSSL支持非常多的命名曲线,但是对于WEB服务器使用的密钥来说,只能使用两种,secp256r1和secp384r1。

创建证书签名申请

一旦有了私钥,就可以创建证书签名CSR。这是要求CA给证书签名的一种正式申请,该申请包含证书的实体公钥以及该实体的某些信息。该数据将成为证书的一部分,CSR始终使用它携带的公钥所对应的的私钥进行签名。

CSR的创建过程一般都是交互式的,需要提供区分证书所需的不同元素。如果想让某一个字段为空,不要直接回车,必须输入一个点(.),如果直接回车,OpenSSL会直接使用这个字段的默认值。

CSR请求配置如下:

openssl req -new -key fd.key -out fd.csr

配置说明

Enter pass phrase for fd.key:                      #输入加密密码
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]: #必填,国家代码
State or Province Name (full name) []:HUBEI #必填,省份
Locality Name (eg, city) [Default City]:WUHAN #必填,城市
Organization Name (eg, company) [Default Company Ltd]:CCB #必填 公司名
Organizational Unit Name (eg, section) []:DEVOPS #必填,组织名
Common Name (eg, your name or your server's hostname) []:www.devops.com #必填,域名
Email Address []:abc@qq.com #必填,管理员邮箱

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: #可选,用于确认身份
An optional company name []: #可选

A challenge password ,质询密码是一个可选字段,用于在证书吊销过程中确认申请过该证书最初的实体的身份。如果输入这个字段,则会将密码包括CSR文件中并发送给CA,但是机会没有CA会依赖这个字段。一般建议将该字段留空,因为设置这个并没有增加CSR的任何安全性,另外它与密钥密码不一样。

CSR生成之后,可以使用它直接去进行证书的签名或者将它发送给公共CA让他们对证书进行签名。

可以用如下命令来检查CSR是否正确。

openssl req -text -in fd.csr -noout

网络安全-openssl工具_标识符_14

使用当前证书生成CSR文件

如果需要更新一张证书,但是不想对里面的证书做任何更改,可以使用如下命令创建一个全新的CSR文件:

openssl x509 -x509toreq -in fd.crt -out fc.csr -singkey fd.key

非交互方式生成CSR

在使用自定义的OpenSSL配置文件,可以实现非交互的自动化生成CSR。例如想生成www.devops.com的csr文件,可以先创建一个fd.cnf文件,内容如下:

#cat fd.cnf
[req]
prompt=no
distinguished_name=dn
input_passwrd=****** #此处写入密码


[dn]
CN=ww.devops.com
emailAddress=abc@qq.com
O=CCB
L=hubei
C=CN
ST=wuhan

然后使用下面的命令直接创建CSR文件

openssl req -new -config fd.cnf -key fd.key -out fd.csr

自签名证书

如果只是实验环境,那么不需要找CA上获取一个公共可信任的证书,则可以生成自签名的证书。使用之前创建的CSR文件,按照如下方法创建证书

openssl x509 -req -days 365 -in fd.csr -signkey fd.key -out fd1.crt

网络安全-openssl工具_字段_15


也可以无需单独创建CSR ,直接使用私钥创建签名证书

#带有交互
openssl req -new -x509 -days 365 -key fd.key out -fd2.crt
#不带交互
openssl req -new -x509 -days 365 -key fd.key out -fd2.crt \
-subj "/C=CN/L=HUBEI/O=CCB/CN=www.devops.com"

创建多个主机名的有效证书

默认情况下,OpenSSL创建的证书只包含一个公用名而且只能设置一个主机名。这个限制下,即便由多个关联的站点,也不得不为每个站点生成一张单独的证书。此时需要使用多域名证书,即使维护一个站点,也得确保用户在访问站点的子域名的时候证书是有效的。在实际中使用至少两个名称,一个为www开头的,一个是没有任何前缀的。如www.devops.com​,和devops.com。

有两种方式在一张证书里里面支持多个主机名。

  1. 在x.509的使用者可选名称,SAN扩展字段里面列出所有需要使用的主机名
  2. 使用泛域名

在实际使用过程中,结合两种方法,可以设置定级域名和一个泛域名来涵括素有的二级域名,如www.devops.com  和 *.devops.com 

当证书包括可选名称的时候,所有的公用名就会被忽略CA所有新创建的证书甚至可能不再包括任何公用名。

首先将扩展信息放在一个单独文本文件中,名为fd.ext.文件中指定扩展的名称subjectAltName,列出所需的主机名

#vim fd.ext
subjectAltName = DNS:*.devops.com,DNS:devops.com

然后在使用x509命令签发证书的时候,使用-extfile参数引用该文件

openssl x509 -req -days 365 \
-in fd.csr -signkey fd.key -out fd3.crt -extfile fd.ext

网络安全-openssl工具_标识符_16


检查证书

x509命令可以对刚生成的自签名的证书进行检查。

openssl x509 -text -in fd.crt -noout # -text打印证书内容,-noout则不打印编码后的证书内容,减少信息干扰

网络安全-openssl工具_主机名_17


自签名证书一般只包括最基本的证书数据,而公共CA签发的证书则含有更多有意义的信息,包括

  • 基本约束basic constraint

该扩展用于标记证书是否是一个CA,这样证书就可以给其他证书进行签名

  • 密钥用法key usage,KU和 扩展密钥用法(extended key usage,EKU)

该扩展限制了证书的使用范围,如果这两个扩展同时存在,只有列表的方法可用。如果该扩展不存在,则没有任何限制。

  • CRL分发点 CRL distribution point

该扩展列出了CA证书吊销列表的地址,当证书需要被吊销的时候这个信息非常重要。CA会对CRL进行签名,并且每隔一段时间发布一次。

  • 证书策略 certificate policy

该扩展用来指出证书使用那种策略签发,例如EV扩展验证。每个标识都拥有一个唯一的对象标识符号。另外这个扩展一般还包括了一个或者多个证书策略申明。

  • 颁发机构信息访问 authority information access,AIA

该扩展包括了两个重要信息,首先它列出了CA的在线证书状态协议OCSP,响应程序的地址,可以用来实时检测证书的吊销情况。该扩展还带上了该证书颁发者的证书地址(也就是证书链的上一层证书)。现在的证书已经很少直接用根证书进行签名了,所以一般用户需要在配置中加上一个或者多个中间证书,这是就容易因为漏导致证书验证失败。有些客户端会使用这个信息来获取中间CA的证书。

  • 使用者密钥标识符subject key identifier 和颁发机构密钥标识符authority key identifier

这两个扩展分别建立了唯一的使用者和颁发机构的标识符。证书的颁发机构密钥标识符的信息必须与颁发者的使用者密钥标识符扩展信息一致。

  • 使用者可选名称 subject alternatice name

该扩展用来列出所有合法的主机名,这个扩展是可选的。如果不存在,客户端就会使用Subject 字段里面的公用名cn提供的信息,如果该扩展存在,那么在验证过程中CN字段的内容会被忽略。


密钥和证书格式转换

私钥和证书可以用各种格式进行存储,所以可能需要进行各种格式之间的转换。常见格式如下:


  • Binary (DER) certificate

原始格式的x.509证书,使用DER ASN.1编码

  • ASCII (PEM) certificate

包含base64编码的DER证书,以---BEGIN CERTIICATE---开头,以---END--CERTIFICATE---结尾,可以将多个证书链放在这同一个文件中。

  • Binary(DER) key

包含DER ANS.1编码后的私钥的原始格式

  • ACSII(PEM) key

包括base64编码后的der密钥和一些元数据信息

  • PCKS#7 certficate(s)

一种比较复杂的格式,设计的目的是用于签名和加密数据的传输,一般常见的是.p7b和.p7c扩展名的文件,并且文件里面可以包括所需的整个证书链。java的进程密钥管理工具支持这种格式

  • PCKS#12(PFX) key and certificate(s)

一种可以保存服务器私钥和整个证书链的复杂格式。一般以.p12 和.pfx扩展名结尾。该证书常见微软的产品,

PEM和 DER转换

#PEM转换到DER
openssl x509 -inform PEM -in fd.pem -outform DER -out fd.der
#DER转换到PEM
openssl x509 -inform DER -in fd.der -outform PEM -out fd.pem


PKCS#12(PFX)转换

openssl pkcs12 -export \
-name "My Certifcate" \
-out fd.p12 \
-inkey fd.key \
-in fd.crt \
-certfile fd-chain.crt



PKCS#7 转换

#PEM转换为PKCS#7
openssl crl2pkcs7 -nocrl -out fc.p7b -certfile fd.crt -certfile fd-chain.crt
#PKCS#7转换为PEM
openssl pkcs7 -in fd.p7b -print_certs -out fd.pem