TripleDES
假设我想用模式中的算法加密文本CBC
,我有两个选择。
1- 在线工具,例如这
2- OpenSSL 工具。
在里面在线工具,我输入文本,,KEY
和IV
。
在里面OpenSSL,我输入以下命令:
OpenSSL> des-ede3-cbc -in MyText.txt -K <KEY> -iv <IV>
但是当我使用以下命令时会发生什么:
OpenSSL> des-ede3-cbc -in Mytext.txt
第一个问题:我想知道,是KEY
由我接下来两行输入的密码组成的吗?它会根据什么算法来创建密钥?
如果有人只有密码,他们能解密我的加密文本吗?
第二个问题:什么是Salt
参数!?使用 -nosalt 的加密命令和不使用 -nosalt 的加密命令有什么区别?
第三个问题:使用 时-base64
,输出是 base64 格式吗? 不使用此参数时,输出的格式是什么?
更新: 第四个问题:解密加密文本需要什么?仅密码?IV 和 KEY?还是全部?
第五个问题:
我在 openssl 命令行中输入“1”作为密码。然后你这在线工具并创建“1”的 MD5 哈希值。如下图所示,3DES KEY 的前两个字节等于我输入的密码的 MD5 哈希值。我想知道密钥中的最后一个字节是什么?它是如何创建的?
如果有人只有密码,他怎样解密我的加密文本?
答案1
- Key 和 IV 是从您指定的密码派生而来的,使用的是 OpenSSL 团队并不引以为豪的 OpenSSL 特定算法。他们保留该算法是为了向后兼容,但他们建议您使用更好的基于密码的密钥派生函数,例如 PKCS 的 PBKDF2。
OpenSSL 的定制密钥派生算法位于函数中EVP_BytesToKey(3)。
钥匙:
-K key 实际使用的密钥:必须表示为仅由十六进制数字组成的字符串。
四:
在密码学中,初始化向量 (IV) 或起始变量 (SV)[1] 是密码原语的固定大小输入,通常要求是随机的或伪随机的。
因此,IV 是用于加密文件的额外输入。它是不是关键(我猜这只是术语)。
2 盐是你指定的密钥的附加部分(前缀)。(见维基百科。这使得无法在密钥上使用彩虹表或预先计算的哈希表。盐通常以未加密的形式存储。
3 输出将是二进制的,并且很可能包含不可打印的字符。您的终端仿真器将尝试将这些字节值呈现为其默认字符编码和字体中的可打印字符,但它们可能看起来像“垃圾文本”,并且不适合复制/粘贴、FTP 或电子邮件。
4 要解密加密文本,您需要密钥和 IV。如果您没有其中一个或两个,而您缺少的密钥和 IV 是从密码中派生出来的,那么如果您有密码,您可以从密码中重新派生出缺少的密钥和/或 IV。您不需要 Salt,因为您已经拥有它;它被添加到加密文本的开头。Salt 并不是真正的秘密,它只是一种挫败预先计算的哈希表和彩虹表的方法。
5 定义EVP_BytesToKey(3),如果您使用密码“1”并且--nosalt
,则密钥的前 16 个字节将是:
md5( D_0 || password || salt)
(请注意,在这种情况下,||
指的是连接,而不是逻辑or
)
相当于
md5 ( `null` || "1" || `null`)
相当于
md5("1")
结果是
0xc4ca4238a0b923820dcc509a6f75849b
这个值就是手册页所称的D_1
。
Key 和 IV 其余所需的字节生成如下:
md5( D_1 || password || salt)
相当于
md5( 0xC4CA4238A0B923820DCC509A6F75849B || "1" || `null` )
相当于
md5( 0xC4CA4238A0B923820DCC509A6F75849B31 )
(请注意,ASCII“1”变为连接在值末尾的 0x31 D_1
)
结果是:
0x7976c7161415c830816dd4068a1d9a52
这就是该手册页所称的 D_2。
密钥只需要比D_1
已经证明的多 8 个字节,因此它取 D_2 的前 8 个字节并变为:
Key: C4CA4238A0B923820DCC509A6F75849B7976c7161415c830
IV 只需要 8 个字节,并且由于 D_2 中有 8 个未使用的字节,因此它们成为 IV:
IV: 816dd4068a1d9a52
下面是生成密钥的前 16 个字节 D_1 的命令行(假设您的示例密码为“1”和--nosalt
):
echo -n "1" | openssl md5
下面是生成 D_2 的命令行,即密钥的剩余 8 个字节以及 IV 的所有 8 个字节(再次给出您的示例输入):
echo -n "$(echo -n "1" | openssl md5 -binary)1" | md5
其工作原理是获取 D_1 的输出(确保将其保存为二进制而不是将其转换为 ASCII 编码的十六进制数字),在其后附加“1”(0x31),然后获取md5
该输出。