Since we have this security section now, I figured I'd make a post illustrating just how much of a joke the light encryption is.
The fun stuff first: Run something like this on your lightly encrypted save file:
Code: Select all
hexdump -C pup_save_cryptx.2fs | head
Code: Select all
# hexdump -C pup_save_cryptx.2fs | head
00000000 65 61 74 61 70 6f 6e 79 74 61 00 00 00 00 00 00 |eataponyta......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 65 61 74 61 70 6f 6e 79 74 61 00 00 00 00 00 00 |eataponyta......|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000040 65 61 74 61 70 6f 6e 79 74 61 00 00 00 00 00 00 |eataponyta......|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000060 65 61 74 61 70 6f 6e 79 74 61 00 00 00 00 00 00 |eataponyta......|
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000080 65 61 74 61 70 6f 6e 79 74 61 00 00 00 00 00 00 |eataponyta......|
00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
Yes, it's really that simple to crack.
You may wonder, "Why is it so easy? How does it work?" That's what I'm going to explain for the rest of this post.
The basic concept of cryptography is pretty simple: You take the data you want to hide and merge it with other data (or perform a transform) so that it looks like noise. To read it, you remove the second set of data (or undo the transform) to get the original data. The second set of data is typically either a key, or data that is generated based on the key. For the encryption used in Puppy's light encryption mode, it is the key itself.
Puppy's light encryption uses XOR encryption. XOR is a boolean algebra operator, and means "exclusive or". You use it to compare two numbers. For example, if you are comparing a 1 and a 0, it gives you a 1. But if you compare two 0s or two 1s, you get a 0. In other words, it will return true if either input A or input B is true, but not if both are true.
When you are dealing with numbers bigger than 1, you just represent them in binary and take them one digit at a time:
Code: Select all
1010 XOR 0011 = 1001
Code: Select all
1001 XOR 0011 = 1010
That is the way XOR encryption works. Your data is A and your key is K. Except it's a little more complicated than that. Your data is typically very long, while the key is relatively short (hopefully not too short though). So what it does is break up the data into blocks of 64 bytes, and applies K to each of those separately.
As for K, it is whatever you typed in as your key, padded with 0s to make it 64 bytes. In other words, if you type in an 8 character key, that defines the first 8 bytes of K. The rest is just 0s. This has distressing consequences.
The problem with XOR encryption is that if you XOR something with 0, it doesn't do anything. A XOR 0 = A, and also: 0 XOR K = K. So unless you use a 64 character long password, very significant chunks of your data will not be encrypted at all! Furthermore, anywhere there is a sizeable amount of 0s in your data (real 0s, not the ASCII code for the number 0), your key will be visible in the encrypted data.
Also, if the person trying to break in knows what some of the data is at a given location, he can just XOR the known data with the encrypted data to determine that portion of K.
This makes a sad situation even more pitiful: The pup_save file is a filesystem image. Filesystems typically have good amounts of known data in their headers. For example, all the pup_save.2fs files on my harddrive have 0s for the first 1024 bytes. I don't know if that particular block of zeros is standard for ext2 filesystems, but if it isn't, you could just look up the specs for ext2 and locate data that is constant.
Here is some more output from the same file I used above, but from deeper where there is actual data.
Code: Select all
00080460 0b 06 54 05 1f 18 00 59 1b 0f 20 6d 65 0d 0a 50 |..T....Y.. me..P|
00080470 72 65 73 73 69 6e 67 20 64 6f 77 6e 20 6f 6e 20 |ressing down on |
00080480 1c 0e 01 41 1e 00 4e 14 15 0f 20 61 73 6b 20 66 |...A..N... ask f|
00080490 6f 72 0d 0a 55 6e 64 65 72 20 70 72 65 73 73 75 |or..Under pressu|
000804a0 17 04 79 6b 24 07 0f 0d 54 03 75 72 6e 73 20 61 |..yk$...T.urns a|
000804b0 20 62 75 69 6c 64 69 6e 67 20 64 6f 77 6e 0d 0a | building down..|
http://www.ascii.cl/conversion.htm
http://ascii.cl/
Code: Select all
enc: 0b 06 54 05 1f 18 00 59 1b 0f 20 6d 65 0d 0a 50 72 65 73 73 69 6e 67 20 64 6f 77 6e 20 6f 6e 20
key: 65 61 74 61 70 6f 6e 79 74 61 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
XORed: 6e 67 20 64 6f 77 6e 20 6f 6e 20 6d 65 0d 0a 50 72 65 73 73 69 6e 67 20 64 6f 77 6e 20 6f 6e 20
ascii: n g d o w n o n m e P r e s s i n g d o w n o n
Also, in case you wonder how to create an XOR encrypted file to play with (as opposed to rebooting a couple times to make a new pup_save_cryptx.2fs file):
Code: Select all
modprobe cryptoloop
dd if=/dev/zero of=pup_save_cryptx.2fs count=1k bs=1k
losetup-FULL -E 1 /dev/loop2 pup_save_cryptx.2fs
mke2fs -q -m 0 /dev/loop2
mkdir mount_point
mount /dev/loop2 mount_point
Code: Select all
umount mount_point
Code: Select all
losetup-FULL -E 1 /dev/loop2 pup_save_cryptx.2fs
mount /dev/loop2 mount_point
Code: Select all
losetup -f