I’m trying to figure out how to mirror encryption/decryption from an existing C function over to python. However, in my tests of encrypting with C and decrypting with python, I can’t figure out some elements around the key.
These were all code samples online, so I commented things like the base64 call in Python, and at this point I’m unsure on:
1) If I correctly determined the KEYBIT to KEY_SIZE/BLOCK_SIZE settings.
2) How to get from password to key in python to match the C code.
3) Am I missing any core conversion steps?
rijndael.h in C:
#define KEYLENGTH(keybits) ((keybits)/8)
#define RKLENGTH(keybits) ((keybits)/8+28)
#define NROUNDS(keybits) ((keybits)/32+6)
encrypting in C
#define KEYBITS 256
unsigned long rk[RKLENGTH(KEYBITS)];
unsigned char key[KEYLENGTH(KEYBITS)];
char *password = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
for (i = 0; i < sizeof(key); i++)
key[i] = *password != 0 ? *password++ : 0;
nrounds = rijndaelSetupEncrypt(rk, key, 256);
count = 0;
while (count < strlen(input)) {
unsigned char ciphertext[16];
unsigned char plaintext[16];
for (i = 0; i < sizeof(plaintext); i++) {
if (count < strlen(input))
plaintext[i] = input[count++];
else
plaintext[i] = 0;
}
rijndaelEncrypt(rk, nrounds, plaintext, ciphertext);
if (fwrite(ciphertext, sizeof(ciphertext), 1, output) != 1)
fclose(file);
fputs("File write error", stderr);
return 0;
}
}
Decrypt in Python
KEY_SIZE = 32
BLOCK_SIZE = 16
def decrypt(password, filename):
#
# I KNOW THIS IS WRONG, BUT HOW DO I CONVERT THE PASSWD TO KEY?
#
key = password
padded_key = key.ljust(KEY_SIZE, '\0')
#ciphertext = base64.b64decode(encoded)
ciphertext = file_get_contents(filename);
r = rijndael(padded_key, BLOCK_SIZE)
padded_text = ''
for start in range(0, len(ciphertext), BLOCK_SIZE):
padded_text += r.decrypt(ciphertext[start:start+BLOCK_SIZE])
plaintext = padded_text.split('\x00', 1)[0]
return plaintext
Thanks!
The example C code just copies 32 bytes from the
passwordstring into the key. If the key is less than 32 bytes, it padds on the right with zeroes.Translated into python, this would be:
Which actually produces the same result as
You should note however that this method of generating keys is considerd extremely unsafe. If the attacker suspects that the key consists of ASCII characters padded with 0 bytes, the keyspace (amount of possible keys) is reduced considerably. If the key is made out of random bytes, there are 256^32 = 1.15e77 keys. If the key e.g. begins with 8 ASCII characters followed by zeroes, there are only (127-32)^8 = 6.63e15 possible keys. And since there are dictionaries out there with often-used passwords, the attacker probably wouldn’t have to exhaust this reduced keyspace; he would try the relatively small dictionaries first.
Consider using a cryptographic hash function or another proper key derivation function to convert the passphrase into a key.
Try using the pycrypto toolkit. It implements Rijndael/AES and other ciphers.