当使用对称密钥加密文件时,最常见的实用程序(例如 gpg、mcrypt 等)将信息存储在加密消息中,这些信息可用于在解密过程中验证密钥的完整性。例如,如果在解密过程中输入了错误的密钥,gpg 将返回:
gpg:解密失败:密钥错误
假设我正在加密一个包含随机字符串的文件。然后,标准实用程序中使用的密钥完整性检查会增加一个漏洞。
是否有一个通用实用程序不会存储任何信息或冗余来验证密钥/消息完整性(因此将“解密”加密文件以进行验证)任何提供的密钥)?
答案1
作为我的替代品其他答案,我想提供其他东西。一些美丽的东西...... dm-crypt。
普通 dm-crypt(没有 LUKS)不存储有关密钥的任何信息;相反,cryptsetup
他非常乐意使用任何密码打开普通设备并开始使用它。请允许我举例说明:
[root:tmp]# fallocate -l 16M cryptfile
[root:tmp]# cryptsetup --key-file - open --type plain cryptfile cfile-open <<<"pa55w0rd"
注意:您的cryptfile
大小必须大于或等于 512 字节。我认为由于最小扇区大小的cryptsetup
强制执行。
此时,您可能希望将所有随机数据写入到/dev/mapper/cfile-open
.在我看来,明智的做法是提前适当调整原始 cryptfile 的大小,以便使用所有空间;但是,您可以轻松地将其视为另一种通过默默无闻的方式增加的安全性,并准确记录您写入的数据量。 (这只有在底层块已经是半随机的情况下才真正起作用,即,如果您不打算完全填充文件,则应该使用openssl rand
或dd if=/dev/urandom
代替 来创建它fallocate
。)...您甚至可以使用dd
开始写入在设备中间的某个地方。
现在,我会做一些更简单的事情。
[root:tmp]# cryptsetup status cfile-open
/dev/mapper/cfile-open is active.
type: PLAIN
cipher: aes-cbc-essiv:sha256
keysize: 256 bits
device: /dev/loop0
loop: /tmp/cryptfile
offset: 0 sectors
size: 32768 sectors
mode: read/write
[root:tmp]# b $((32768*512))
B KiB MiB GiB TiB PiB EiB
16777216 16384.0 16.00 .01 0 0 0
[root:tmp]# ll cryptfile
-rw-r--r--. 1 root root 16777216 Feb 21 00:28 cryptfile
[root:tmp]# openssl rand -out /dev/mapper/cfile-open $((32768*512))
[root:tmp]# hexdump -n 16 -C /dev/mapper/cfile-open
00000000 00 1d 2d 11 ac 38 c4 d3 cc 81 4f 32 de 64 01 ca |..-..8....O2.d..|
00000010
[root:tmp]# cryptsetup close cfile-open
此时,我已用 16 MiB 的随机数据填充了我的加密文件。看看当我使用错误的密码再次打开它时会发生什么,然后为了清楚起见,我将使用正确的密码再次打开它,您会看到原始数据仍然完好无损。
[root:tmp]# cryptsetup --key-file - open --type plain cryptfile cfile-open <<<"pass"
[root:tmp]# hexdump -n 16 -C /dev/mapper/cfile-open
00000000 89 97 91 26 b5 46 87 0c 67 87 d8 4a cf 78 e6 d8 |...&.F..g..J.x..|
00000010
[root:tmp]# cryptsetup close cfile-open
[root:tmp]# cryptsetup --key-file - open --type plain cryptfile cfile-open <<<"pa55w0rd"
[root:tmp]# hexdump -n 16 -C /dev/mapper/cfile-open
00000000 00 1d 2d 11 ac 38 c4 d3 cc 81 4f 32 de 64 01 ca |..-..8....O2.d..|
00000010
[root:tmp]#
享受。
答案2
GnuPG 无法完成您想要的操作。不过,可以使用 OpenSSL 来完成。您需要在 cfb 或 ofb 等流模式下使用其中一种密码(最好是 AES)。 (看:http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation)
通常,当我使用 openssl 加密数据时,我会按如下方式使用 cbc(带或不带 base64 编码 ( -a
) ...当然还有其他方法来指定密码和输入数据(请参阅man openssl
):
[rsaw:~]$ openssl aes-256-cbc -e -a -pass pass:pa55w0rd <<<inputdata
U2FsdGVkX180a9K5gBgip7/lgdCGCLLlRflAjK8+YwY=
[rsaw:~]$ openssl aes-256-cbc -e -a -pass pass:pa55w0rd <<<inputdata
U2FsdGVkX1+4uSv4uCNj2J4g7441XDioDoAb6JNn2RU=
[rsaw:~]$ openssl aes-256-cbc -e -a -pass pass:pa55w0rd <<<inputdata |
> openssl aes-256-cbc -d -a -pass pass:pa55w0rd
inputdata
事实上,每次都会得到不同的输出,这表明您的密码是加盐的,这通常是好的。现在看看当我使用坏钥匙时会发生什么。
[rsaw:~]$ openssl aes-256-cbc -e -a -pass pass:pa55w0rd <<<inputdata |
> openssl aes-256-cbc -d -a -pass pass:pa55w0r
bad decrypt
139867807664032:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:596:
长话短说,这种模式(cbc)广泛用于加密文件,但它显然不符合您提出的要求。让我们尝试一些不同的东西。
[rsaw:~]$ openssl aes-256-cfb1 -e -a -pass pass:pa55w0rd <<<inputdata
U2FsdGVkX1+p64nx+/K6yCHdHw+Nmn6fSOg=
[rsaw:~]$ openssl aes-256-cfb1 -e -a -pass pass:pa55w0rd <<<inputdata |
> openssl aes-256-cfb1 -d -a -pass pass:pa55w0rd
inputdata
[rsaw:~]$ openssl aes-256-cfb1 -e -a -pass pass:pa55w0rd <<<inputdata |
> openssl aes-256-cfb1 -d -a -pass pass:pa55w0r
'G�疏s�v
虽然上述内容满足您的要求,但我不做任何保证。我不是加密专家。加密是一件大事。情况很复杂。我将要这么说aes*cfb*
并aes*ofb
满足您的要求...并且您应该跳过aes*ecb
.
我将提供 2 个更有趣的花絮:
我通常不会建议使用未加盐的密钥,但在您正在做的事情(加密随机数据)的情况下......您可以跳过盐,因为它在数据的开头添加了更明确定义的结构。例如:
[rsaw:~]$ openssl aes-256-cfb1 -e -a -pass pass:pa55w0rd <<<inputdata U2FsdGVkX18aMT3eK4IH+XWGhp4dOSG9UJQ= [rsaw:~]$ openssl aes-256-cfb1 -e -a -pass pass:pa55w0rd <<<inputdata U2FsdGVkX18uIlFFMbsZib11UgjuITY9rNw= [rsaw:~]$ openssl aes-256-cfb1 -e -a -pass pass:pa55w0rd <<<inputdata U2FsdGVkX1+G9lAIj7RjafT9YNfO9RQXDjU= [rsaw:~]$ openssl aes-256-cfb1 -e -nosalt -a -pass pass:pa55w0rd <<<inputdata X2zi09uo6ale8A==
当我存储数据(包括加密数据)时,完整性始终是我最关心的问题之一。如果有任何数据损坏,我想知道,这样我就可以扔掉整个文件。使用像 openssl 这样的块密码
aes*cbc
(或者 AFAIK 使用 GnuPG 来解决这个问题),任何小的位翻转都会被捕获并导致解密失败。另一方面,如果你做得正确,使用流模式可以让你恢复尽可能多的数据——它可以将损坏保留在流中存在的部分。核实:[rsaw:tmp]$ openssl aes-256-cfb1 -e -a -pass pass:pa55w0rd </etc/services >services.asc [rsaw:tmp]$ wc -l services.asc 13965 services.asc [rsaw:tmp]$ sed '6000q;d' services.asc e6AAnnXAF74c8p52q7+klGC+JHfK91QOx+oFonAzKFoJt0DSNg2WQkdBaxv4YLst [rsaw:tmp]$ sed -i '6000s/^e/f/' services.asc [rsaw:tmp]$ sed '6000q;d' services.asc f6AAnnXAF74c8p52q7+klGC+JHfK91QOx+oFonAzKFoJt0DSNg2WQkdBaxv4YLst [rsaw:tmp]$ openssl aes-256-cfb1 -d -a -pass pass:pa55w0rd <services.asc | diff - /etc/services 5029c5029,5030 < veronica 2770/tcp %���#��*����@jeronica 2770/udp # Veronica --- > veronica 2770/tcp # Veronica > veronica 2770/udp # Veronica
享受。
gpg
PS:除了、openssl
、 或 dm-crypt之外,你不敢使用任何其他东西。坚持3个大的。没有其他的。
答案3
该工具不存储任何内容来验证密钥。
答案4
@udkLpqc:我无法在上面发表评论,是否使用该工具取决于您,但您写的内容在某种程度上不是我所看到的。我在 Ubuntu 上自己编译了它:
$echo -e "uvwxyz\n\n\n\n\n\n\n\n\n\n" | wc -l
11
$echo -e "uvwxyz\n\n\n\n\n\n\n\n\n\n" | ./aes -p "t" | ./aes -d -p "t" | wc -l
11
这对我来说看起来是相同的行数(我使用文件得到了相同的结果)。该工具很旧,消息来源称它支持 PKCS5,而不是 PKCS7。它记录了为什么它回显密码,以及使用 strlen 而不是 strnlen,嗯,这必须在上下文中看到,该工具期望输入直接来自用户,并且它仅对文件名和密码使用 strlen。如果您计划在文件名和密码来自不受信任的来源的某些自动化环境中使用它,我同意,它可能不适合您。