# 前言

一篇简单的 OpenSSL 对称加密使用经验,偶尔更新。


# 获取帮助

openssl enc -h

输入如下:

Usage: enc [options]
General options:
 -help               Display this summary
 -list               List ciphers
 -ciphers            Alias for -list
 -e                  Encrypt
 -d                  Decrypt
 -p                  Print the iv/key
 -P                  Print the iv/key and exit
 -engine val         Use engine, possibly a hardware device
Input options:
 -in infile          Input file
 -k val              Passphrase
 -kfile infile       Read passphrase from file
Output options:
 -out outfile        Output file
 -pass val           Passphrase source
 -v                  Verbose output
 -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
Encryption options:
 -nopad              Disable standard block padding
 -salt               Use salt in the KDF (default)
 -nosalt             Do not use salt in the KDF
 -debug              Print debug info
 -bufsize val        Buffer size
 -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 the use of PBKDF2
                     Default: 10000
 -pbkdf2             Use password-based key derivation function 2 (PBKDF2)
                     Use -iter to change the iteration count from 10000
 -none               Don't encrypt
 -*                  Any supported cipher
Random state options:
 -rand val           Load the given file(s) into the random number generator
 -writerand outfile  Write random data to the specified file
Provider options:
 -provider-path val  Provider load path (must be before 'provider' argument if required)
 -provider val       Provider to load (can be specified multiple times)
 -propquery val      Property query used when fetching algorithms

# 列出支持的加密算法

可以通过 -list-ciphers 参数来列出当前版本 OpenSSL 支持的对称加密算法:

openssl enc -list

或:

openssl enc -ciphers

个人使用的 OpenSSL 版本是 3.1.2,它的输出如下:

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

# 对称加密算法命名规则的简单介绍


# 可变密钥长度 分组加密算法

一个可变密钥长度的分组加密算法参数通常由三部分组成,对称加密算法 - 密钥长度 - 分组密码工作模式

举个例子: AES-128-CTR

AES对称加密算法高级加密标准(Advanced Encryption Standard,AES),它支持 128 位、192 位和 256 位的密钥长度

128密钥长度 指定为 128 位

CTR分组密码工作模式计数器模式(Counter Mode, CTR)


# 固定密钥长度 分组加密算法

一个固定密钥长度的分组加密算法参数通常由两部分组成,对称加密算法 - 分组密码工作模式

举个例子: SM4-CFB

SM4对称加密算法商密 - 4,它的 密钥长度默认固定为 128 位

CFB分组密码工作模式密文反馈模式(Cipher FeedBack,CFB)


# 流密码

一个流密码的参数通常就是对称加密算法本身:对称加密算法

举个例子: Chacha20

Chacha20:对称加密算法Chacha20


# 默认 ECB 模式

当使用分组密码对称加密算法时不指定分组密码工作模式,OpenSSL 将会默认使用 ECB 模式 对文件进行加密。

举个例子: BF

BF对称加密算法Blowfish,默认分组密码工作模式是 电子密码本模式(Electronic CodeBlock),注意,这一模式是不安全的


# 对称加密算法 简单介绍


# AES

高级加密标准(Advanced Encryption Standard,AES),NIST 标准,原型是 Rjindael,属于 SPN 密码。

目前世界上最流行的加密算法,具有高度的安全性、高度的兼容性、强大的性能和广泛的硬件加速支持,是绝大多数情况下对称加密算法的首选。密文分组 128 位,密钥长度可选 128 位,192 位或 256 位,对应的 SPN 迭代轮次分别为 10 轮、12 轮与 14 轮。


# ARIA

ARIA 是韩国密码学研究者基于 AES 修改而来的一种 SPN 密码,原型是 AES。

韩国用于取代 AES 而设计的加密算法,具有高度安全性和较好的性能,密文分组 128 位,密钥长度可选 128 位,192 位或 256 位,对应的 SPN 迭代轮次分别是 12 轮、14 轮和 16 轮。


# BF(Blowfish)

Blowfish 是 Bruce Schneier 设计的一种 Feistel 密码。

一个相对较老的对称加密算法,密文分组 64 位,密钥长度可选 32-448 位,迭代固定 16 轮。目前仍然具有能够接受的安全性,最优的密文分析只能破解 4 轮 BF,或将 14 轮 BF 与伪随机序列区分开来。但由于密文分组仅有 64 位,研究表明可能存在生日攻击问题。作者 Bruce Schneier 本人建议使用 TwoFish 进行替代。


# Camellia

卡梅利亚(Camellia)是日本 NTT 和 MEC 设计的一款 Feistel 加密算法,其计算量和安全性基本与 AES 相当,名称意为 “山茶”。

一个常见的加密算法,具有高度的安全性、较为广泛的支持、强大的性能,是 AES 的一种替代算法。密文分组 128 位,密钥长度可选 128 位、192 位或 256 位,对应 Feistel 迭代轮次分别为 18 轮,24 轮与 24 轮。


# CAST / CAST5 / CAST-128

CAST 是 Carlisle AdamsStafford Tavares 设计的一款 Feistel 密码,在加拿大常用。

CAST5 的密文分组为 64 位,密钥长度 40-128 位,步长 8 位。80 位以下采用 12 轮迭代,80 位及以上采用 16 轮迭代。被 GPG,PGP 和 OpenSSL 等支持。


# Chacha20

Chacha20 是 Daniel Julius Bernstein 设计的一种流密码算法,是 Salsa20 的改进版本。

Chacha20 采用 128 位或 256 位密钥,ARX 结构,512 位状态位和 20 轮重复,具有高度的安全性。由于 Chacha20 是流密码算法,因此具有低延迟、高性能、算力需求低的优点,适合在移动设备上、ARM 架构处理器与嵌入式设备上使用。常常与 Poly1305 校验码一同使用。


# DES

数据加密标准(Data Encryption Standard, DES),上古加密算法,上世纪 70 年代由 DES 开发,已经过时。

DES 采用 56 位密钥和 64 位密文分组,Feistel 结构 16 轮迭代。在目前的算力下,蛮力攻击(穷举法)攻破 DES 已经成为可能。线性分析和选择明文攻击均能有效削弱 DES 的安全性。


# DES-EDE / DES3 (3DES)

三重数据加密标准(Triple Data Encryption Standard, 3DES)或 DES-EDE(Data Encryption Standard - Encryption Decryption Encryption)是对 DES 的加强,通过三个使用不同密钥的 DES 分别对原始数据进行加密、解密、加密得到密文(密钥选项 1),将密钥空间扩展到 2168,但由于中途相遇攻击,其安全性实际为 2112

当然,也存在 K2 = K1(密钥选项 2)和 K3 = K2 = K1(密钥选项 3)的 3DES 版本。其中,根据 NIST 的评估,密钥选项 2 的有效安全性仅有约 280,而密钥选项 3 明显不合理,第二轮解密和第一轮加密直接抵消,因此相当于 DES。密钥选项 2 与密钥选项 3 均已经弃用。目前的 3DES 或 DES-EDE 默认使用密钥选项 1。

3DES 对于目前的算力和密码分析手段仍然属于安全的,但是其性能和理论安全性仍然弱于 AES。其主要优势在于能与支持 DES 的老式通信系统兼容。如有可能,应尽量升级到 AES。


# DESX

使用 64 位密钥的 DES,其中仍然是 56 位用于加密,8 位用于校验。不推荐。


# IDEA

国际数据加密算法(International Data Encryption Algorithm,IDEA),最早称为改良建议加密标准(Improved Proposed Encryption Standard,IPES),是 1991 年提出的一种 Feistel 密码。

IDEA 的密文分组长度为 64 位,密钥长度为 128 位,迭代轮次为 8.5。目前 IDEA 被认为是一种不再安全的加密算法,尽管目前最优的攻击方式复杂度仍然来到 2126.1,超过了目前的常规算力破解能力。(资料来源:维基百科)


# RC2 / ARC2

RC2(Rivest Cipher 2)是 Ron Rivest 设计的基于不平衡 Feistel 结构的分组加密算法,目前已经过时,面对相关密钥攻击脆弱。

RC2 的分组长度为 64 位,密钥长度 1-128 位。它采用 16 轮不平衡 Feistel 结构的混淆操作和 2 轮扰乱操作。


# RC4 / ARC4 / ARCFOUR

RC4(Rivest Cipher 4)是 Ron Rivest 设计的一种流密码,曾经非常流行,被广泛用于 SSL 和 WPA 等协议,但目前已经过时。

RC4 采用 40-2048 位的密钥,以及 2064 位的状态位(1684 个有效状态位)对数据进行加密,拥有很快的加密速度。但是它的密钥流能够被与伪随机序列区分开来。在 2015 年,比利时的密码研究员宣布了 RC4 的破解,能够在 75 小时内取得 Cookie 的内容。目前现代的密码学协议通常已经弃用 RC4。


# SEED

SEED 是韩国 KISA 研发的一种 Feistel 密码。

SEED 的密文分组为 128 位,密钥长度固定为 128 位,迭代轮数 16 轮,目前仍然具有较高的安全性。


# SM4 / SMS4

SM4(商密 - 4)是中国国密算法系列中的对称加密算法,属于 Feistel 密码。

SM4 的分组长度为 128 位,密钥长度固定为 128 位,采用非对称 Feistel 结构 32 轮迭代,具有很强的安全性和较高的性能,广泛用于中国标准 WLAN WAPI 和 TLS。


# 基本加解密指令


# 简单的加密指令

一个最简单的加密文件的示例如下,该指令通过 AES-128-CTR 加密算法对 plaintext.txt 文件进行加密:

openssl enc -e -AES-128-CTR -in plaintext.txt -out ciphertext.txt

OpenSSL 此时会提醒你输入密码:

enter AES-128-CTR encryption password:

输入密钥后,OpenSSL 会提醒你输入确认密码:

Verifying - enter AES-128-CTR encryption password:

如果确认密码与密码一致,那么文件将开始加密。但是,这种加密方式已经过时,OpenSSL 此时会弹出提示:

*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.

# 简单的解密指令

一个最简单的解密文件的示例如下,该指令尝试通过 AES-128-CTR 加密算法对 ciphertext.txt 文件进行解密:

openssl enc -d -AES-128-CTR -in ciphertext.txt -out decryptedtext.txt

OpenSSL 此时会提醒你输入密码:

enter AES-128-CTR decryption password:

密码如果正确,OpenSSL 将会解密文件。但它仍然会提醒你这种加密方式已经过时,会弹出提示:

*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.

# PBKDF2、迭代次数与盐

OpenSSL 目前并不鼓励直接使用字符串作为密钥,而是推荐使用 PBKDF2 生成加密密钥。

openssl enc 有这两个 KDF 参数:

-PBKDF2 :PBKDF2(Password-Based Key Derivation Function 2)是一种密钥推到函数,它能够从用户提供的密码中推导出实际的加密密钥,能够有效增强密码安全性,避免爆破原始密码。

-iter :迭代次数(Iterations)指定了 PBKDF2 的迭代轮数,迭代轮数越高,密码的安全性相对就越高,但也会消耗更多的计算资源。一般建议设置在 80000 以上。(建议来源:Bitwarden)

-salt :盐(Salt)是一个随机生成的唯一值,它在每一轮迭代中与输入值连接在一起参加 KDF 迭代,进一步增加了彩虹表攻击和爆破的难度。这个选项是默认开启的。

# 示例:使用 PBKDF2 与盐进行加解密

以下这条指令通过 AES-128-CTR 加密算法对 plaintext.txt 文件进行加密,使用加盐 PBKDF2,迭代次数 80000,输出文件为 ciphertext.txt。

openssl enc -e -AES-128-CTR -pbkdf2 -iter 80000 -salt -in plaintext.txt -out ciphertext.txt

以下这条指令通过 AES-128-CTR 加密算法对 ciphert.txt 文件进行解密,使用加盐 PBKDF2,迭代次数 80000,输出文件为 decryptedtext.txt。

openssl enc -d -AES-128-CTR -pbkdf2 -iter 80000 -salt -in ciphertext.txt -out decryptedrtext.txt

# 总体选择参数


# -help

陈列 OpenSSL enc 指令的帮助:

openssl enc -h

或:

openssl enc -help

它的输出如下:

Usage: enc [options]
General options:
 -help               Display this summary
 -list               List ciphers
 -ciphers            Alias for -list
 -e                  Encrypt
 -d                  Decrypt
 -p                  Print the iv/key
 -P                  Print the iv/key and exit
 -engine val         Use engine, possibly a hardware device
Input options:
 -in infile          Input file
 -k val              Passphrase
 -kfile infile       Read passphrase from file
Output options:
 -out outfile        Output file
 -pass val           Passphrase source
 -v                  Verbose output
 -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
Encryption options:
 -nopad              Disable standard block padding
 -salt               Use salt in the KDF (default)
 -nosalt             Do not use salt in the KDF
 -debug              Print debug info
 -bufsize val        Buffer size
 -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 the use of PBKDF2
                     Default: 10000
 -pbkdf2             Use password-based key derivation function 2 (PBKDF2)
                     Use -iter to change the iteration count from 10000
 -none               Don't encrypt
 -*                  Any supported cipher
Random state options:
 -rand val           Load the given file(s) into the random number generator
 -writerand outfile  Write random data to the specified file
Provider options:
 -provider-path val  Provider load path (must be before 'provider' argument if required)
 -provider val       Provider to load (can be specified multiple times)
 -propquery val      Property query used when fetching algorithms

# -list 或 -ciphers

列出 OpenSSL 支持的对称加密算法:

openssl enc -list

或:

openssl enc -ciphers

以 OpenSSL 3.1.2 版本为例,它的输出如下:

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

# -e

加密指令,例如:

openssl enc -AES-128-CTR -e -pbkdf2 -iter 80000 -salt -in plaintext.txt -out ciphertext.txt

这条指令通过 AES-128-CTR 加密算法对 plaintext.txt 进行加密,输出到 ciphertext.txt 当中,密钥派生函数采用 PBKDF2 ,迭代次数 80000 ,加盐。

# -d

解密指令,例如:

openssl enc -AES-128-CTR -d -pbkdf2 -iter 80000 -salt ciphertext.txt -out decrypted.txt

这条指令通过 AES-128-CTR 加密算法对 ciphertext.txt 进行解密,输出到 decrypted.txt 当中,密钥派生函数采用 PBKDF2 ,迭代次数 80000 ,加盐。

# -p 或 -P

输出 IV(Initialization Vector,初始化向量)和密钥,加盐也会输出盐值。

openssl enc -p -AES-128-CTR -e -pbkdf2 -iter 80000 -salt -in plaintext.txt -out ciphertext.txt

它的输出为:

salt=EEADC4C2FABA433D
key=BD956B91B899D59A02DA992B65908A6F
iv =6AC35A79C1EE8C7192680E294696D279

# -engine

指定加密引擎,一般来说并不需要这么做,除非你有特殊需求。


# 输入参数


# -in

指定输入文档,例如 -in plaintext.txt 就是指以 plaintext.txt 文件作为输入。


# -k

指定加密密钥,例如:

openssl enc -e -AES-128-CTR -pbkdf2 -iter 80000 -salt -k your_awesome_password -in plaintext.txt -out ciphertext.txt

其中 -k your_awesome_password 就指定了初始密钥为 "your_awesome_password"


# -kfile

从指定文件的第一行中导入密钥,例如:

openssl enc -e -AES-128-CTR -pbkdf2 -iter 80000 -salt -kfile your_awesome_password.bin -in plaintext.txt -out ciphertext.txt

其中 -kfile your_awesome_password.bin 就指定了初始密钥从 your_awesome_password.bin 这个文件的第一行中导入。


# 输出参数


# -out

指定输出文档,例如 -out ciphertext.txt 就是指输出到 ciphertext.txt 这个文件中。如果没有这个文件,那么就新建。


# pass

指定密码的来源。

# 直接在命令行中提供密码

例如这条命令,直接指定密码为 your_awesome_password

openssl enc -AES-128-CTR -e -pass pass:your_awesome_password -in plaintext.txt -out ciphertext.txt

# 从文件中读取密码

例如这条命令,从 password.txt 中的第一行读取密码:

openssl enc -AES-128-CTR -e -pass file:password.txt -in plaintext.txxt -out ciphertext.txt

# 使用环境变量提供密码

例如这条命令,将尝试从系统的 OPENSSL_PASSWORD 环境变量读取密码:

openssl enc -AES-128-CTR -e -pass env:OPENSSL_PASSWORD -in plaintext.txt -out ciphertext.txt

# -v

输出详细信息,例如:

openssl enc -v -e -AES-128-CTR -pbkdf2 -iter 80000 -salt -k your_awesome_password -in plaintext.txt -out ciphertext.txt

这是它的输出:

bufsize=8192
bytes read   :       64
bytes written:       80

# -a 或 -base64

Base64 编解码选项,如果是加密则将输出进行 Base64 编码,如果是解密则对输入先进行 Base64 解码。

例如:

openssl enc -base64 -e -AES-128-CTR -pbkdf2 -iter 80000 -salt -k your_awesome_password -in plaintext.txt -out ciphertext.txt

这样你就会得到 Base64 编码的输出,而不是一堆乱码了:

U2FsdGVkX18mc9HLpslcxebFcULw/x3pPduiYwtum8dFM0AFH0h0o3Wri6K4LXVF
HFj/F0SeXy4Ma3odakvf2oRuM8C4CGPHICzSq2/X830=

# -A

-a-base64 一同使用,将 Base64 编码的缓冲区输出为单行文本。对于需要嵌入单行数据或者脚本的场景或许很有用。

例如:

openssl enc -A -base64 -e -AES-128-CTR -pbkdf2 -iter 80000 -salt -k your_awesome_password -in plaintext.txt -out ciphertext.txt

得到的输出:

U2FsdGVkX19CVxeyE43LfGZf9QR73J7HXEYgc2PmfcElfbIwwvrUS1VRrCfKUqjkL9k2ldAVxTXdmf0c41rluoMKY+On4rKwzRpZlY2Vv84=

# 加密选项


# -nopad

禁用分组加密算法的块填充。此时如果数据长度不是分组大小的整数倍,可能会出错。


# -salt

为 KDF 加盐,默认就是开启的。

例如:

openssl enc -e -AES-128-CTR -pbkdf2 -iter 80000 -salt -in plaintext.txt -out ciphertext.txt

# -nosalt

手动指定 KDF 不使用盐,不推荐不安全,这会削弱加密面对彩虹表攻击和爆破攻击的强度。

openssl enc -e -AES-128-CTR -pbkdf2 -iter 80000 -nosalt -in plaintext.txt -out ciphertext.txt

# -debug

输出调试信息,例如:

openssl enc -e -debug -AES-128-CTR -pass pass:your_awesome_password -pbkdf2 -iter 80000 -salt -in plaintext.txt -out ciphertext.txt

一个示例输出是:

in plaintext.txt -out ciphertext.txt
BIO[0x1e9bc5cf7f0]: write(0,8) - FILE pointer
BIO[0x1e9bc5cf7f0]: write return 1 processed: 8
BIO[0x1e9bc5cf7f0]: write(0,8) - FILE pointer
BIO[0x1e9bc5cf7f0]: write return 1 processed: 8
BIO[0x1e9bc5e02a0]: ctrl(6) - cipher
BIO[0x1e9bc5cf7f0]: ctrl(6) - FILE pointer
BIO[0x1e9bc5cf7f0]: ctrl return 0
BIO[0x1e9bc5e02a0]: ctrl return 0
BIO[0x1e9bc5d0600]: ctrl(10) - FILE pointer
BIO[0x1e9bc5d0600]: ctrl return 0
BIO[0x1e9bc5d0600]: ctrl(2) - FILE pointer
BIO[0x1e9bc5d0600]: ctrl return 0
BIO[0x1e9bc5d0600]: read(0,8192) - FILE pointer
BIO[0x1e9bc5d0600]: read return 1 processed: 64
BIO[0x1e9bc5e02a0]: write(0,64) - cipher
BIO[0x1e9bc5cf7f0]: write(0,64) - FILE pointer
BIO[0x1e9bc5cf7f0]: write return 1 processed: 64
BIO[0x1e9bc5e02a0]: write return 1 processed: 64
BIO[0x1e9bc5d0600]: ctrl(10) - FILE pointer
BIO[0x1e9bc5d0600]: ctrl return 0
BIO[0x1e9bc5d0600]: ctrl(2) - FILE pointer
BIO[0x1e9bc5d0600]: ctrl return 1
BIO[0x1e9bc5e02a0]: ctrl(11) - cipher
BIO[0x1e9bc5cf7f0]: ctrl(11) - FILE pointer
BIO[0x1e9bc5cf7f0]: ctrl return 1
BIO[0x1e9bc5e02a0]: ctrl return 1
BIO[0x1e9bc5d0600]: Free - FILE pointer
BIO[0x1e9bc5cf7f0]: Free - FILE pointer
BIO[0x1e9bc5e02a0]: Free - cipher

这其实是 OpenSSL API 给出的一些日志信息,其中涉及到 C 语言的操作,希望了解底层实现或者需要功能调试的可能会用到这个选项。


# -bufsize

手动调整 OpenSSL 缓冲区的大小,这个值默认情况下是 8192B,个人认为大多数情况下没必要修改。

更大的缓冲区在处理大文件时能减少 IO 次数,提升性能,但会引起更大的内存开销;更小的缓冲区处理小文件时能节省内存,但是处理大文件时 IO 次数会提高,性能会受到影响。

一个示例,把缓冲区修改为 1024B:

openssl enc -e -AES-128-CTR -pass pass:your_awesome_password -pbkdf2 -iter 80000 -salt -bufsize 1024 -in plaintext.txt -out ciphertext.txt

# -K

手动指定初始密钥(Raw Key),绕过 KDF。输入形式为 16 进制。必须与 -iv 一同使用。

(PS:个人观点,除非你十分清楚你在做什么,否则不建议这么做

例如,将 Raw Key 手动覆盖为 dc76d65a6ccf7f33fd8ecb7fe640e272 ,将 IV 手动覆盖为 12caf7e7136907d82c6a01a0e3b7fc16

openssl enc -e -AES-128-CTR -K dc76d65a6ccf7f33fd8ecb7fe640e272 -iv 12caf7e7136907d82c6a01a0e3b7fc16 -in plaintext.txt -out ciphertext.txt

# -iv

手动指定初始化向量(Initialization Vector, IV),绕过自带的 IV 发生器。输入形式为 16 进制。

(PS:个人观点,除非你十分清楚你在做什么,否则不建议这么做

例如,将 Raw Key 手动覆盖为 dc76d65a6ccf7f33fd8ecb7fe640e272 ,将 IV 手动覆盖为 12caf7e7136907d82c6a01a0e3b7fc16

openssl enc -e -AES-128-CTR -K dc76d65a6ccf7f33fd8ecb7fe640e272 -iv 12caf7e7136907d82c6a01a0e3b7fc16 -in plaintext.txt -out ciphertext.txt

# -S

手动指定 KDF 的盐值(Salt),绕过自带的 Salt 发生器。输入形式为 16 进制。

(PS:个人观点,除非你十分清楚你在做什么,否则不建议这么做

例如,将盐值手动覆盖为 4351431709882387

openssl enc -e -AES-128-CTR -pass pass:your_awesome_password -pbkdf2 -iter 80000 -salt -S 4351431709882387 -in plaintext.txt -out ciphertext.txt

# -md

手动指定 KDF 使用的散列算法,绕过默认的散列算法。一般而言,没必要。

(PS:个人观点,除非你十分清楚你在做什么,否则不建议这么做

例如,将散列算法手动修改为 SM3

openssl enc -e -AES-128-CTR -pass pass:your_awesome_password -pbkdf2 -iter 80000 -salt -md SM3 -in plaintext.txt -out ciphertext.txt

# -iter

手动指定 KDF 的迭代次数,覆盖默认的迭代次数(10000)。

例如,将 KDF 的迭代次数手动修改为 80000

openssl enc -e -AES-128-CTR -pass pass:your_awesome_password -pbkdf2 -iter 80000 -salt -in plaintext.txt -out ciphertext.txt

# -pbkdf2

使用 PBKDF2 来生成初始密钥,这是一种良好的安全实践:

openssl enc -e -AES-128-CTR -pass pass:your_awesome_password -pbkdf2 -iter 80000 -salt -in plaintext.txt -out ciphertext.txt

# -none

不进行加密,通常是调试时使用的。


# 随机状态选项


# -rand

将选定的文件加载到随机数生成器当中,提供额外的安全性。最好使用可靠的随机源,例如在 Linux 系统上:

openssl enc -e -AES-128-CTR -pass pass:your_awesome_password -pbkdf2 -iter 80000 -salt -in plaintext.txt -out ciphertext.txt -rand /dev/urandom

# writerand

向选定的文件输出生成的随机数据。

openssl enc -e -AES-128-CTR -pass pass:your_awesome_password -pbkdf2 -iter 80000 -salt -in plaintext.txt -out ciphertext.txt -writerand random.txt