2

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

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

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

2)如何在python中获取密码以匹配C代码。

3)我是否缺少任何核心转换步骤?

C中的rijndael.h:

#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

谢谢!

4

1 回答 1

0

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

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

这实际上产生了相同的结果

password.ljust(32, '\0')

但是您应该注意,这种生成密钥的方法被认为是极其不安全的。如果攻击者怀疑密钥由用 0 字节填充的 ASCII 字符组成,则密钥空间(可能的密钥数量)会大大减少。如果密钥由随机字节组成,则有 256^32 = 1.15e77 个密钥。例如,如果密钥以 8 个 ASCII 字符后跟零开头,则只有 (127-32)^8 = 6.63e15 个可能的密钥。而且由于那里有带有常用密码的字典,攻击者可能不必用尽这个减少的密钥空间。他会先尝试相对较小的字典。

考虑使用加密散列函数或其他适当的密钥派生函数将密码短语转换为密钥。

尝试使用pycrypto工具包。它实现了 Rijndael/AES 和其他密码

于 2012-09-30T14:46:04.413 回答