本文主要介绍如何使用 OpenSSL 来进行对称加解密,文中所使用到的软件版本:OpenSSL 1.1.1s、CentOS 7.9.2009。

1、对称加密算法

对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。有时又叫传统密码算法,就是加密密钥能够从解密密钥中推算出来,同时解密密钥也可以从加密密钥中推算出来。而在大多数的对称算法中,加密密钥和解密密钥是相同的,所以也称这种加密算法为秘密密钥算法或单密钥算法。它要求发送方和接收方在安全通信之前,商定一个密钥。对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人都可以对他们发送或接收的消息解密,所以密钥的保密性对通信的安全性至关重要。

 对称加密算法主要有四种加密模式:

1)电子密码本模式 Electronic Code Book(ECB):最基本的加密模式,也就是通常理解的加密,相同的明文将永远加密成相同的密文,无初始向量,容易受到密码本重放攻击,一般情况下很少用。

2)密码分组链接模式 Cipher Block Chaining(CBC):明文被加密前要与前面的密文进行异或运算后再加密,因此只要选择不同的初始向量,相同的密文加密后会形成不同的密文,这是目前应用最广泛的模式。CBC加密后的密文是上下文相关的,但明文的错误不会传递到后续分组,但如果一个分组丢失,后面的分组将全部作废(同步错误)。

3)加密反馈模式 Cipher Feedback Mode(CFB):类似于自同步序列密码,分组加密后,按 8 位分组将密文和明文进行移位异或后得到输出同时反馈回移位寄存器,优点最小可以按字节进行加解密,也可以是 n 位的,CFB 也是上下文相关的,CFB 模式下,明文的一个错误会影响后面的密文(错误扩散)。

4)输出反馈模式 Output Feedback Mode(OFB):将分组密码作为同步序列密码运行,和 CFB 相似,不过 OFB 用的是前一个 n 位密文输出分组反馈回移位寄存器,OFB 没有错误扩散问题。

2、用法

可以使用 OpenSSL 来进行对称加解密,通过 openssl enc -help 命令查看用法:

shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl enc -help
Usage: enc [options]
Valid options are:
-help Display this summary
-list List ciphers
-ciphers Alias for -list
-in infile Input file
-out outfile Output file
-pass val Passphrase source
-e Encrypt
-d Decrypt
-p Print the iv/key
-P Print the iv/key and exit
-v Verbose output
-nopad Disable standard block padding
-salt Use salt in the KDF (default)
-nosalt Do not use salt in the KDF
-debug Print debug info
-a Base64 encode/decode, depending on encryption flag
-base64 Same as option -a
-A Used with -[base64|a] to specify base64 buffer as a single line
-bufsize val Buffer size
-k val Passphrase
-kfile infile Read passphrase from file
-K val Raw key, in hex
-S val Salt, in hex
-iv val IV in hex
-md val Use specified digest to create a key from the passphrase
-iter +int Specify the iteration count and force use of PBKDF2
-pbkdf2 Use password-based key derivation function 2
-none Don't encrypt
-* Any supported cipher
-rand val Load the file(s) into the random number generator
-writerand outfile Write random data to the specified file
-engine val Use engine, possibly a hardware device

参数说明:

参数

说明

-in infile

指定输入文件

-out outfile

指定输出文件

-pass val

指定密码的输入方式:命令行输入(pass)、文件输入(file)、环境变量输入(var)、文件描述符输入(fd)、标准输入(stdin)。默认是标准输入。

-e

加密

-d

解密

-P

打印偏移量iv和密钥key,不进行加解密操作

-p

打印偏移量iv和密钥key

-a,-base64

加密时结束用base64编码,解密时输入先用base64解密

-S

指定 salt 值,而不是随机生成;hex 格式

-pbkdf2

使用第二版本的基于密码生成密钥的函数

-*

指定算法,可以使用 openssl enc -list 查看支持的算法

3、查看支持的算法

可以使用 openssl enc -list 查看当前版本 OpenSSL 支持的对称加密算法:

shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl enc -list
Supported ciphers:
-aes-128-cbc -aes-128-cfb -aes-128-cfb1
-aes-128-cfb8 -aes-128-ctr -aes-128-ecb
-aes-128-ofb -aes-192-cbc -aes-192-cfb
-aes-192-cfb1 -aes-192-cfb8 -aes-192-ctr
-aes-192-ecb -aes-192-ofb -aes-256-cbc
-aes-256-cfb -aes-256-cfb1 -aes-256-cfb8
-aes-256-ctr -aes-256-ecb -aes-256-ofb
-aes128 -aes128-wrap -aes192
-aes192-wrap -aes256 -aes256-wrap
-aria-128-cbc -aria-128-cfb -aria-128-cfb1
-aria-128-cfb8 -aria-128-ctr -aria-128-ecb
-aria-128-ofb -aria-192-cbc -aria-192-cfb
-aria-192-cfb1 -aria-192-cfb8 -aria-192-ctr
-aria-192-ecb -aria-192-ofb -aria-256-cbc
-aria-256-cfb -aria-256-cfb1 -aria-256-cfb8
-aria-256-ctr -aria-256-ecb -aria-256-ofb
-aria128 -aria192 -aria256
-bf -bf-cbc -bf-cfb
-bf-ecb -bf-ofb -blowfish
-camellia-128-cbc -camellia-128-cfb -camellia-128-cfb1
-camellia-128-cfb8 -camellia-128-ctr -camellia-128-ecb
-camellia-128-ofb -camellia-192-cbc -camellia-192-cfb
-camellia-192-cfb1 -camellia-192-cfb8 -camellia-192-ctr
-camellia-192-ecb -camellia-192-ofb -camellia-256-cbc
-camellia-256-cfb -camellia-256-cfb1 -camellia-256-cfb8
-camellia-256-ctr -camellia-256-ecb -camellia-256-ofb
-camellia128 -camellia192 -camellia256
-cast -cast-cbc -cast5-cbc
-cast5-cfb -cast5-ecb -cast5-ofb
-chacha20 -des -des-cbc
-des-cfb -des-cfb1 -des-cfb8
-des-ecb -des-ede -des-ede-cbc
-des-ede-cfb -des-ede-ecb -des-ede-ofb
-des-ede3 -des-ede3-cbc -des-ede3-cfb
-des-ede3-cfb1 -des-ede3-cfb8 -des-ede3-ecb
-des-ede3-ofb -des-ofb -des3
-des3-wrap -desx -desx-cbc
-id-aes128-wrap -id-aes128-wrap-pad -id-aes192-wrap
-id-aes192-wrap-pad -id-aes256-wrap -id-aes256-wrap-pad
-id-smime-alg-CMS3DESwrap -idea -idea-cbc
-idea-cfb -idea-ecb -idea-ofb
-rc2 -rc2-128 -rc2-40
-rc2-40-cbc -rc2-64 -rc2-64-cbc
-rc2-cbc -rc2-cfb -rc2-ecb
-rc2-ofb -rc4 -rc4-40
-seed -seed-cbc -seed-cfb
-seed-ecb -seed-ofb -sm4
-sm4-cbc -sm4-cfb -sm4-ctr
-sm4-ecb -sm4-ofb

算法名称中包含了密钥位数及模式,OpenSSL 默认使用 PKCS7Padding 的填充方式。

4、具体使用

4.1、使用 aes-128-cbc 算法加密

shell> echo -n 123456|/home/mongo/soft/openssl-1.1.1s/bin/openssl enc -e -aes-128-cbc -a -p -pbkdf2 -pass pass:abc
salt=5BD68E48B20CADF8
key=D66105C0AE7324FF0D3F9424AC222120
iv =0A03ECE1334289FBB5DBBBC556AA6CD9
U2FsdGVkX19b1o5Isgyt+AtQPniEdSStNGYJJQqPWQY=

OpenSSL 通过用户输入的密码及一个随机的 salt 来生成 key 和 iv,命令执行的生成的结果会包含 salt 值,所以会跟其他加密工具得到的结果不一致;把结果 "U2FsdGVkX19b1o5Isgyt+AtQPniEdSStNGYJJQqPWQY=" 转换为 hex 格式值为:"53616C7465645F5F5BD68E48B20CADF80B503E78847524AD346609250A8F5906",紫色部分是固定的字符串 ”Salted__“,中间红色的部分为 salt 值,最后蓝色的部分是真正的加密结果。

可以通过 -S 来指定 salt 值,这样每次输出的 slat、key、iv 值都是一样的。

该标准命令等效于如下的加解密命令:

echo -n 123456|/home/mongo/soft/openssl-1.1.1s/bin/openssl aes-128-cbc -e -a -p -pbkdf2 -pass pass:abc

4.2、使用 aes-128-cbc 算法解密

echo U2FsdGVkX19b1o5Isgyt+AtQPniEdSStNGYJJQqPWQY= | /home/mongo/soft/openssl-1.1.1s/bin/openssl enc -d -aes-128-cbc -a -p -pbkdf2 -pass pass:abc

4.3、使用文件作为输入

新建文件 a.txt,在文件中输入内容:

123456

使用 a.txt 作为输入:

shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl enc -e -aes-128-cbc -a -p -pbkdf2 -pass pass:abc -S 5BD68E48B20CADF8 -in a.txt
salt=5BD68E48B20CADF8
key=D66105C0AE7324FF0D3F9424AC222120
iv =0A03ECE1334289FBB5DBBBC556AA6CD9
U2FsdGVkX19b1o5Isgyt+PY1unvJCsuD7lZxfV9YQxk=

 

注:标准输入(结束方法:先输入回车,然后输入 ctrl+D)会把换行符也带入计算;使用文件输入时,也会在文件内容最后增加换行作为 OpenSSL 的计算输入;这会导致计算结果(去除结果中 salt 部分)与其他加密工具(如:Java)的计算结果不一致,所以使用 echo -n 来去除换行。