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

标签 python objective-c encryption aes

我遇到了与 this question 相同的问题但不幸的是没有答案。

我有以下要使用 CCCrypt 加密的 Objective-C 代码:

(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() 函数时,它都会返回垃圾。我是不是遗漏了什么或在某处启用了错误的选项?


示例输入和输出:

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 打印的是乱码...所以我假设这是一个填充错误或类似的错误

IV 在 iOs 端为零,在 Python 端为 16x 0(见代码)

最佳答案

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

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


请记住 a - (b % a) a 的任何(正)值都不能为 0或 b .这意味着

if amount_to_pad == 0:
    amount_to_pad = self.block_size

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

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

关于python - 使用 Objective-C 加密数据并在 Python 中解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32460076/

相关文章:

encryption - 哪种是最好的加密方法 base 64 或 MD5?

python - 在使用 python、django 或基于 shell 的工具进行重定向后,如何捕获最终 url?

python - 在Python中查看图幂律分布图

python - 重新排列 numpy 数组

ios - 如何动态更改 UIStoryboard 中使用的颜色

java - Android - 实现加密 IM 的最佳方式

c# - 将 C# .Net 加密/解密算法迁移到 Ruby

当在进程内创建父对象时,Python 多线程不使用公共(public)内存

ios - 如何在iOS中绘制梯形?

ios - UIWebView 泄漏、JS 垃圾收集器和 WebCore 虚拟机