连接 aespipe 文件:第一个文件后每 512 个字节出现错误字节

连接 aespipe 文件:第一个文件后每 512 个字节出现错误字节

我正在努力加密流埃斯佩普到日志文件,每次运行它时附加到同一个文件是有意义的,所以我想做类似的事情

my_stream | aespipe -K my_key >> aes_logfile

我已经考虑到aespipe写出 512 字节的块,并且我确保填充我的流,以便它始终以这些大小的增量输出数据。我几乎让我的计划得以实施除了 aespipe 会破坏第一个文件之后每 512 字节增量的第一个字节。例如,以下文件that_file(以 结尾的行~)为 512 字节。

Hey StackOverflow, here is a  ~
small example. The lines are  ~
32 characters long (including ~
the trailing \n) and with     ~
aespipe you can encrypt this  ~
file with                     ~
                              ~
cat this_file | aespipe -K \  ~
 your_key_with_one_line.gpg \ ~
 > enc_file                   ~
                              ~
then you can concatenate onto ~
the encrypted file again with ~
 >> and get a new file.       ~
Note that this file is 512 B. ~
So it is the right block size ~

这是以下内容的输出:

# First go
cat that_file | aespipe -K my_key.gpg >  aes_logfile
# Second go
cat that_file | aespipe -K my_key.gpg >> aes_logfile

# Try decrypting
cat aes_logfile | aespipe -d -K my_key.gpg

带注释的输出:

Hey StackOverflow, here is a  ~
small example. The lines are  ~
32 characters long (including ~
the trailing \n) and with     ~
aespipe you can encrypt this  ~
file with                     ~
                              ~
cat this_file | aespipe -K \  ~
 your_key_with_one_line \     ~
 > enc_file                   ~
                              ~
then you can concatenate onto ~
the encrypted file again with ~
 >> and get a new file.       ~
Note that this file is 512 B. ~
So it is the right block size ~
Iey StackOverflow, here is a  ~    # <-- H became I!
small example. The lines are  ~
32 characters long (including ~
the trailing \n) and with     ~
aespipe you can encrypt this  ~
file with                     ~
                              ~
cat this_file | aespipe -K \  ~
 your_key_with_one_line \     ~
 > enc_file                   ~
                              ~
then you can concatenate onto ~
the encrypted file again with ~
 >> and get a new file.       ~
Note that this file is 512 B. ~
So it is the right block size ~

每 512 字节就会发生一次,我不知道为什么。有什么办法可以解决这个问题吗? ( aespipe version 2.4d)

答案1

嗯,我可以重现它。

# dd count=1 if=/dev/zero | aespipe > aes_zero
Password: Error: Password must be at least 20 characters.
# dd count=1 if=/dev/zero | aespipe >> aes_zero
Password: Error: Password must be at least 20 characters.
# cat aes_zero | aespipe -d | hexdump -C
Password: Error: Password must be at least 20 characters.
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000200  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
          ^^
00000210  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400

密文:

# hexdump -C aes_zero
00000000  b3 a3 72 9b 18 5b 6b 73  e5 48 88 d1 8b 66 e3 10  |..r..[ks.H...f..|
00000010  a8 a0 ee d3 7e 08 91 86  6b f7 30 b2 ea 6a 58 0b  |....~...k.0..jX.|
[...]
000001e0  d9 2a 60 22 c9 4a 37 5c  47 21 65 0a bb f3 a8 7d  |.*`".J7\G!e....}|
000001f0  50 9f ef 38 9a c1 95 2b  ff 85 c7 16 cc 90 a7 18  |P..8...+........|
00000200  b3 a3 72 9b 18 5b 6b 73  e5 48 88 d1 8b 66 e3 10  |..r..[ks.H...f..|
00000210  a8 a0 ee d3 7e 08 91 86  6b f7 30 b2 ea 6a 58 0b  |....~...k.0..jX.|
[...]
000003e0  d9 2a 60 22 c9 4a 37 5c  47 21 65 0a bb f3 a8 7d  |.*`".J7\G!e....}|
000003f0  50 9f ef 38 9a c1 95 2b  ff 85 c7 16 cc 90 a7 18  |P..8...+........|
00000400

您已经可以看出这是不好的加密,因为密文重复,而这是根本不应该发生的。

密文本身也没有问题:

# dd count=1 if=aes_zero | md5sum
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.00136312 s, 376 kB/s
f328ce6ff88545bc803b033561cbdffd  -
# dd count=1 skip=1 if=aes_zero | md5sum
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.00148213 s, 345 kB/s
f328ce6ff88545bc803b033561cbdffd  -

所以这是相同的,并且在解密过程中出现了错误的字节。

实际上我天真的期望的不是一个字节的偏差,而是前 512 个字节后面的随机数据。因为对于大多数常用的加密方案,每个扇区的IV应该不同,以避免密文重复,并且结果应该完全不同。

一次性加密 1024 字节:

# dd count=2 if=/dev/zero | aespipe >> aes_zero2
Password: Error: Password must be at least 20 characters.
# hexdump -C aes_zero2
00000000  b3 a3 72 9b 18 5b 6b 73  e5 48 88 d1 8b 66 e3 10  |..r..[ks.H...f..|
00000010  a8 a0 ee d3 7e 08 91 86  6b f7 30 b2 ea 6a 58 0b  |....~...k.0..jX.|
...
000001e0  d9 2a 60 22 c9 4a 37 5c  47 21 65 0a bb f3 a8 7d  |.*`".J7\G!e....}|
000001f0  50 9f ef 38 9a c1 95 2b  ff 85 c7 16 cc 90 a7 18  |P..8...+........|
00000200  60 89 3e 37 87 1c 37 31  1a 11 50 b6 99 50 d3 74  |`.>7..71..P..P.t|
00000210  af a9 a2 30 3d e6 72 5f  f3 96 6d 3b 9e 5b 33 6f  |...0=.r_..m;.[3o|
...
000003e0  3f d3 2e 9a 18 ad 7a c9  5a ee 04 99 28 e6 af 3f  |?.....z.Z...(..?|
000003f0  a3 a9 71 be 1a 56 35 01  06 b9 57 dd fc 42 7c 47  |..q..V5...W..B|G|

正如您所看到的,密文根本不重复。因此,你的连接只会产生错误的密文(IV 设置不正确),并且无论如何都能得到那么多完整的文本是一个很大的惊喜,而且不是好的密码学。您不应该能够将密文移动到不同的偏移量并获得合理的结果(只有前几个字节受到错误 IV 的影响)。


尝试使用 LUKS (aes-xts-plain64) 重现相同的内容:

# truncate -s 1024 luks_zero
# losetup --find --show luks_zero
/dev/loop9
# cryptsetup open --type plain --cipher aes-xts-plain64 /dev/loop9 luks_zero
Enter passphrase for /dev/loop9: Error: Password must be at least 20 characters.
# dd if=/dev/zero of=/dev/mapper/luks_zero
dd: writing to '/dev/mapper/luks_zero': No space left on device
3+0 records in
2+0 records out
1024 bytes (1.0 kB, 1.0 KiB) copied, 0.000719156 s, 1.4 MB/s

这是由 LUKS 加密的零。重复的密文:

# sync
# dd count=1 seek=1 if=/dev/loop9 of=/dev/loop9
# hexdump -C /dev/loop9
00000000  1c 18 b1 e6 57 9c a1 60  8c 98 f0 d3 59 8b 97 0c  |....W..`....Y...|
00000010  bc fc 8a 62 68 52 51 f1  51 49 bf 21 2e f5 bc 84  |...bhRQ.QI.!....|
[...]
000001e0  4a e0 ef eb 8f 09 18 a8  73 95 0b 2c 59 01 69 1b  |J.......s..,Y.i.|
000001f0  92 71 e6 0d dd 3b 71 b5  22 f4 34 1c e1 4a 95 71  |.q...;q.".4..J.q|
00000200  1c 18 b1 e6 57 9c a1 60  8c 98 f0 d3 59 8b 97 0c  |....W..`....Y...|
00000210  bc fc 8a 62 68 52 51 f1  51 49 bf 21 2e f5 bc 84  |...bhRQ.QI.!....|
[...]
000003e0  4a e0 ef eb 8f 09 18 a8  73 95 0b 2c 59 01 69 1b  |J.......s..,Y.i.|
000003f0  92 71 e6 0d dd 3b 71 b5  22 f4 34 1c e1 4a 95 71  |.q...;q.".4..J.q|
00000400

密文被完美复制。解密结果:

# hexdump -C /dev/mapper/luks_zero 
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000200  b7 6c 5c 84 3d 7d dc 58  fc d5 ee 7f 20 c0 d5 09  |.l\.=}.X.... ...|
00000210  a8 78 f8 d8 38 4b 6a 24  bb b1 d2 65 b8 5c 2b ac  |.x..8Kj$...e.\+.|
[...]
000003e0  08 31 74 f4 59 92 3b 7f  0f fa b9 36 2e de 53 e2  |.1t.Y.;....6..S.|
000003f0  24 83 01 53 6e 56 dc a5  3a 3f 1b 4e d5 0a fd a9  |$..SnV..:?.N....|
00000400

512 字节零后跟完全垃圾。这并不能证明加密货币是好的,但它并不像你从 aespipe 获得的那样明显糟糕。


现在,由于这是由于错误的 IV 造成的,因此您只需确保首先使用正确的 IV 进行加密即可。aespipe-O sectornumber这样的标志:

   -O sectornumber
          Set IV offset in 512 byte units. Default is zero. Data is encrypted  in  512  byte  CBC
          chains  and  each  512  byte  chain  starts with IV whose computation depends on offset
          within the data. This option can be used to start encryption or decryption in middle of
          some existing encrypted disk image.

加密和连接事物的新方法:

# dd count=1 if=/dev/zero | aespipe -O 0 > aes_zero
Password: Error: Password must be at least 20 characters.
# dd count=1 if=/dev/zero | aespipe -O 1 >> aes_zero
Password: Error: Password must be at least 20 characters.

看看它是否与我们一次性加密的一致:

# md5sum aes_zero aes_zero2 
3b0479e04a46a3d268dc4252e066d2b5  aes_zero
3b0479e04a46a3d268dc4252e066d2b5  aes_zero2

现在验证解密结果是否正确:

# cat aes_zero | aespipe -d | hexdump -C
Password: Error: Password must be at least 20 characters.
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400

DNA 匹配、时机有效、一切都检查完毕……好吧,它并没有改进加密货币本身,而是解决了眼前的问题,也许它足以达到目的。

从文件大小动态导出正确的-O sectornumber值作为练习留给读者。

相关内容