使用 Objective-C 加密数据并在 Python 中解密

Encrypt data using Objective-C and Decrypt in Python

我和this question有同样的问题,但不幸的是没有答案。

我有以下 objective-c 代码可以使用 CCCrypt 进行加密:

(NSData *)doCrypt:(NSData *)data usingKey:(NSData *)key withInitialVector:(NSData *)iv mode:(int)mode error: (NSError *)error
{
    int buffersize = 0;
    if(data.length % 16 == 0) { buffersize = data.length + 16; }
    else { buffersize = (data.length / 16 + 1) * 16 + 16; }

    // int buffersize = (data.length <= 16) ? 16 : data.length;
    size_t numBytesEncrypted = 0;
    void *buffer = malloc(buffersize * sizeof(uint8_t));
    CCCryptorStatus result = CCCrypt(mode, 0x0, 0x1, [key bytes], [key length], [iv bytes], [data bytes], [data length], buffer, buffersize, &numBytesEncrypted);

    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted freeWhenDone:YES];
}

我使用 kCCAlgorithmAES128kCCOptionPKCS7Padding 作为选项,并使用 [Cryptor doCrypt:data usingKey:key withInitialVector:nil mode:0x0 error:nil];

调用函数

现在我想使用 python 解密它,为此我有以下代码:

def decrypt(self, data, key):
        iv = '\x00' * 16

        encoder = PKCS7Encoder()
        padded_text = encoder.encode(data)

        mode = AES.MODE_CBC
        cipher = AES.new(key, mode, iv)
        decoded = cipher.decrypt(padded_text)
        return decoded

PKCS7Encoder 看起来像这样:

class PKCS7Encoder():
    """
    Technique for padding a string as defined in RFC 2315, section 10.3,
    note #2
    """
    class InvalidBlockSizeError(Exception):
        """Raised for invalid block sizes"""
        pass

    def __init__(self, block_size=16):
        if block_size < 2 or block_size > 255:
            raise PKCS7Encoder.InvalidBlockSizeError('The block size must be ' \
                    'between 2 and 255, inclusive')
        self.block_size = block_size

    def encode(self, text):
        text_length = len(text)
        amount_to_pad = self.block_size - (text_length % self.block_size)
        if amount_to_pad == 0:
            amount_to_pad = self.block_size
        pad = chr(amount_to_pad)
        return text + pad * amount_to_pad

    def decode(self, text):
        pad = ord(text[-1])
        return text[:-pad]

然而,每当我调用 decrypt() 函数时,它 returns 都是垃圾。我是不是遗漏了什么或者在某处启用了错误的选项?


输入和输出示例:

NSData *keyData = [[NSData alloc] initWithRandomData:16];
    NSLog(@"key: %@", [keyData hex]);
    NSString *str = @"abcdefghijklmno";
    NSLog(@"str: %@", str);
    NSData *encrypted = [Cryptor encrypt:[str dataUsingEncoding:NSUTF8StringEncoding] usingKey:keyData];
    NSLog(@"encrypted str: %@", [encrypted hex]);

给出:

key: 08b6cb24aaec7d0229312195e43ed829
str: a
encrypted str: 52d61265d22a05efee2c8c0c6cd49e9a

和python:

cryptor = Cryptor()
encrypted_hex_string = "52d61265d22a05efee2c8c0c6cd49e9a"
hex_key = "08b6cb24aaec7d0229312195e43ed829"
print cryptor.decrypt(encrypted_hex_string.decode("hex"), hex_key.decode("hex"))

结果:

láz

这很奇怪,但是如果转储十六进制我得到 610f0f0f0f0f0f0f0f0f0f0f0f0f0f0fb02b09fd58cccf04f042e2c90d6ce17a61 = a 所以我认为它只是显示错误。

更大的输入:

key: 08b6cb24aaec7d0229312195e43ed829
str: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
encrypted str: 783fce3eca7ebe60d58b01da3d90105a93bf2d659cfcffc1c2b7f7be7cc0af4016b310551965526ac211f4d6168e3cc5

结果:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaôNÍ“ƒ˜�Üšw6C%

这里你看到 a 打印的是乱码...所以我认为这是一个填充错误或类似的错误

iOs 侧的 IV 为零,Python 侧为 16x 0(参见代码)

你的解密:aes_decrypt(pkcs7_<strong>pad</strong>(密文))
正确解密: pkcs7_<strong>unpad</strong>(aes_decrypt(密文))

必须这样做,因为 CBC 模式下的 AES 需要块大小的倍数的明文,但您通常希望加密任意明文。所以需要加密前加padding,解密后去掉padding。


请记住,对于 ab 的任何(正)值,a - (b % a) 不能为 0。这意味着

if amount_to_pad == 0:
    amount_to_pad = self.block_size

是无法访问的代码,可以删除。好消息是 a - (b % a) 已经做了你想用 if 块做的事情。

您还应该扩展 unpad (decode) 函数以实际检查每个填充字节是否为相同字节。您还应该检查每个填充字节是否不为零或大于块大小。