rijndael:在C和Python中加密/解密相同的数据

时间:2012-09-30 13:40:20

标签: python c encryption rijndael

我正在试图弄清楚如何将现有C函数的加密/解密镜像到python。但是,在我使用C加密和使用python解密的测试中,我无法弄清楚密钥周围的一些元素。

这些都是在线的代码示例,所以我在Python中评论了类似base64调用的内容,此时我不确定:

1)如果我正确确定KEYBIT到KEY_SIZE / BLOCK_SIZE设置。

2)如何在python中从密码到密钥以匹配C代码。

3)我错过了任何核心转换步骤吗?

rijndael.h in C:

#define KEYLENGTH(keybits) ((keybits)/8)
#define RKLENGTH(keybits)  ((keybits)/8+28)
#define NROUNDS(keybits)   ((keybits)/32+6)

加密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;
    }
}

用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

谢谢!

1 个答案:

答案 0 :(得分:0)

示例C代码只是将password字符串中的32个字节复制到密钥中。如果密钥小于32个字节,则在右侧用零填充。 转换为python,这将是:

key = password[:32]+b'\x00'*(32-len(password))

实际上产生与

相同的结果
password.ljust(32, '\0')

但是请注意,这种生成密钥的方法是extremely unsafe。如果攻击者怀疑该密钥由填充0字节的ASCII字符组成,则密钥空间(可能的密钥数量)会大大减少。如果密钥是由随机字节组成的,则有256 ^ 32 = 1.15e77个密钥。如果密钥,例如以8个ASCII字符开头,后跟零,只有(127-32)^ 8 = 6.63e15个可能的键。而且由于dictionaries有经常使用的密码,攻击者可能不必耗尽这个减少的密钥空间;他会先尝试相对较小的词典。

考虑使用cryptographic hash function或其他适当的key derivation function将密码短语转换为密钥。

尝试使用pycrypto工具包。它实现了Rijndael/AES and other ciphers