我遇到与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];
}
我使用kCCAlgorithmAES128
和kCCOptionPKCS7Padding
作为选项,并使用[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
这很奇怪,但是如果转储十六进制我得到610f0f0f0f0f0f0f0f0f0f0f0f0f0f0fb02b09fd58cccf04f042e2c90d6ce17a
和61 = a
所以我认为它只是显示错误。
更大的投入:
key: 08b6cb24aaec7d0229312195e43ed829
str: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
encrypted str: 783fce3eca7ebe60d58b01da3d90105a93bf2d659cfcffc1c2b7f7be7cc0af4016b310551965526ac211f4d6168e3cc5
结果:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaôNÍ“ƒ˜�Üšw6C%
在这里你看到a'被打印出垃圾...所以我认为这是一个填充错误或类似的东西
IV在iOs方面是nill,在Python方面是16x 0(参见代码)
答案 0 :(得分:2)
您的解密: aes_decrypt(pkcs7_pad(ciphertext))
正确解密: pkcs7_unpad(aes_decrypt(ciphertext))
必须以这种方式完成,因为CBC模式下的AES需要块大小的倍数的明文,但是您通常希望加密任意明文。因此,您需要在加密前应用填充并在解密后删除填充。
请注意,对于a - (b % a)
或a
的任何(正)值,b
不能为0。这意味着
if amount_to_pad == 0:
amount_to_pad = self.block_size
是无法访问的代码,可以删除。好的是,a - (b % a)
已经完成了你想对if
块做的事情。
您还应该扩展unpad(decode
)函数以实际检查每个填充字节是否是相同的字节。您还应该检查每个填充字节是不是零还是大于块大小。