OpenSSL 应用程序需要谨慎使用,它们通常具有旧的且可能不安全的默认值,至少按照现代标准。
在这种情况下openssl enc
,默认使用 MD5 ( apps/enc.c
)的摘要
if (md && (dgst=EVP_get_digestbyname(md)) == NULL)
{
BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
goto end;
}
if (dgst == NULL)
{
dgst = EVP_md5();
}
“-md
消息摘要”选项可用于显式设置,您可以使用任何受支持的摘要,例如 sha256:
openssl enc -md sha256 -e -aes256 -in infile.txt -out outfile.enc -pass pass:foo
您的一些断言是正确的,但它们在这里并不完全适用,特别是由于攻击者不知道摘要输出,因此不适用碰撞攻击。
查找冲突仅在某些时候有用,例如当 MD5 输出用作签名或完整性检查时。碰撞攻击需要您使用哈希输出。
在这种情况下,MD5 被用作密钥派生函数。为此,通常更有趣的是图像前阻力:给定摘要,您可以计算出生成它的输入(例如密码)。MD5 具有良好但不完美的原像电阻,~123 位而不是预期的 128,请参阅RFC6151。
仅给定一个加密文件,如果攻击者的任务是恢复加密数据,那么他必须发现用于加密的对称密钥(key+IV)。该密钥也是他可以从他可以发现的密码短语计算的摘要(盐,如果使用,在文件中可用)。
攻击者不知道密码或密钥(盐/密码的摘要),任何一个都可以:找到哪个更便宜?可能对攻击者有所帮助的是MD5 输出是否有偏差,但据我所知并非如此。
(严格来说可能有两种情况:为了证明某事而恢复密码,不一定要访问加密的数据;或者只是为了访问加密的数据而恢复密钥。)
两个明显的攻击是:
- 暴力破解整个(对称密码)密钥空间,如果 KDF(散列/摘要)输出有偏差,那么这将小于应有的值,这可能有助于攻击者
- 蛮力密码空间,如果输入是由人选择的,那么这将小于密钥空间(盐将消除预先计算的攻击,
enc
默认使用随机盐)
理想情况下,我们想要一个没有偏差的良好 KDF,输出至少与预期输入熵一样大,与对称密码密钥大小匹配,并且成本高昂,因此攻击 #2 不会提供捷径。
使用像 MD5 这样带有短输出(128 位输出)的摘要作为 KDF 意味着用于执行加密的密钥只有 128 位,在这种情况下,只要您需要的密码短语(~160 位, 62^26)。还要考虑将使用的对称密码密钥大小,理想情况下应该匹配这些大小。
这里最大的问题不是使用 MD5 的潜在问题,而是使用的 KDF openssl enc
“便宜”,特别是它只使用一轮,使得对密码的暴力攻击成为最好的攻击(apps/enc.c
第 569 行):
EVP_BytesToKey(cipher,dgst,sptr,
(unsigned char *)str,
strlen(str),1,key,iv);
(硬编码为 1)的第六个参数EVP_BytesToKey
是计数,旨在减慢攻击者的速度(或者在这种情况下不减慢速度)。应该使用一个健壮的、昂贵的密钥拉伸函数,如bcrypt或 scrypt。