问题是我的分类方法没被执行。
其实标题应该是:由相同的加密算法但使用了不同的填充算法引发的血案
我写的分类里的代码
@implementation NSData (YYYYY)
- (NSData *)YYY_AES128EncryptWithKey:(NSString *)key iv:(NSString *)iv
{
return [self YYY_AES128Operation:kCCEncrypt key:key iv:iv];
}
- (NSData *)YYY_AES128Operation:(CCOperation)operation key:(NSString *)key iv:(NSString *)iv{
char keyPtr[kCCKeySizeAES128 + 1];
memset(keyPtr, 0, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
char ivPtr[kCCBlockSizeAES128 + 1];
memset(ivPtr, 0, sizeof(ivPtr));
[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesCrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(operation,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCOptionECBMode ,
keyPtr,
kCCBlockSizeAES128,
ivPtr,
[self bytes],
dataLength,
buffer,
bufferSize,
&numBytesCrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];
}
free(buffer);
return nil;
}
@end
hopper之后
void * -[NSData YYY_AES128EncryptWithKey:iv:](void * self, void * _cmd, void * arg2, void * arg3) {
var_-24 = 0x0;
objc_storeStrong(&var_-24, arg2);
var_-32 = 0x0;
objc_storeStrong(&var_-32, arg3);
var_-80 = [[self YYY_AES128Operation:0x0 key:var_-24 iv:var_-32] retain];
objc_storeStrong(&var_-32, 0x0);
objc_storeStrong(&var_-24, 0x0);
rax = [var_-80 autorelease];
return rax;
}
void * -[NSData YYY_AES128Operation:key:iv:](void * self, void * _cmd, unsigned int arg2, void * arg3, void * arg4) {
var_-104 = 0x0;
objc_storeStrong(&var_-104, arg3);
var_-112 = 0x0;
objc_storeStrong(&var_-112, arg4);
memset(&var_-32, 0x0, 0x11);
[var_-104 getCString:&var_-32 maxLength:0x11 encoding:0x4];
memset(&var_-64, 0x0, 0x11);
[var_-112 getCString:&var_-64 maxLength:0x11 encoding:0x4];
var_-120 = [self length];
var_-136 = malloc(var_-120 + 0x10);
var_-144 = 0x0;
stack[2048] = [objc_retainAutorelease(self) bytes];
if (CCCrypt(arg2, 0x0, 0x3, &var_-32, 0x10, &var_-64, stack[2048], var_-120, var_-136, var_-120 + 0x10, &var_-144) == 0x0) {
var_-72 = [[NSData dataWithBytesNoCopy:var_-136 length:var_-144] retain];
}
else {
free(var_-136);
var_-72 = 0x0;
}
objc_storeStrong(&var_-112, 0x0);
objc_storeStrong(&var_-104, 0x0);
var_-256 = [var_-72 autorelease];
if (*___stack_chk_guard == *___stack_chk_guard) {
rax = var_-256;
}
else {
rax = __stack_chk_fail();
}
return rax;
}
别人的
void * -[NSData AES128EncryptWithKey:iv:](void * self, void * _cmd, void * arg2, void * arg3) {
rbx = [arg2 retain];
r14 = [[self AES128operation:0x0 key:rbx iv:arg3] retain];
[rbx release];
rax = [r14 autorelease];
return rax;
}
void * -[NSData AES128operation:key:iv:](void * self, void * _cmd, unsigned int arg2, void * arg3, void * arg4) {
r12 = [arg3 retain];
*(int8_t *)(&var_-80 + 0x10) = 0x0;
var_-80 = intrinsic_movaps(var_-80, 0x0);
r15 = [arg4 retain];
[arg3 getCString:&var_-80 maxLength:0x11 encoding:0x4];
[r12 release];
*(int8_t *)(&var_-112 + 0x10) = 0x0;
var_-112 = intrinsic_movaps(var_-112, 0x0);
[arg4 getCString:&var_-112 maxLength:0x11 encoding:0x4];
[r15 release];
r15 = malloc([self length] + 0x10);
var_-128 = 0x0;
rbx = objc_retainAutorelease(self);
[rbx bytes];
[rbx length];
rsp = (rsp - 0x30) + 0x30;
if (CCCrypt(arg2, 0x0, 0x1, &var_-80, 0x10, &var_-112, stack[2048], stack[2049], stack[2050], stack[2051], stack[2052]) != 0x0) {
free(r15);
rdi = 0x0;
}
else {
rdi = [[NSData dataWithBytesNoCopy:r15 length:var_-128] retain];
}
if (*___stack_chk_guard == *___stack_chk_guard) {
rax = [rdi autorelease];
}
else {
rax = __stack_chk_fail();
}
return rax;
}
区别在哪
kCCEncrypt = 0, 第一个参数arg2,传入没问题。
看cccrypt的第三个参数
看到第三个参数不一样
enum {
/* options for block ciphers */
kCCOptionPKCS7Padding = 0x0001,
kCCOptionECBMode = 0x0002
/* stream ciphers currently have no options */
};
验证一下填充算法不同的加密结果
+(void)load{
NSData *oData = [@"123467890" dataUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@",oData);
NSLog(@"%@",[oData YYY_AES128EncryptWithKey:@"20003333" iv:@"AES"]);
NSLog(@"%@",[oData YYY_AES128EncryptWithKey:@"20003333" iv:@"AES"]);
NSData *myData = [oData YYY_AES128EncryptWithKey:@"20003333" iv:@"AES"];
NSLog(@"%@",[oData AES128EncryptWithKey:@"20003333" iv:@"AES"]);
NSLog(@"%@",[oData AES128EncryptWithKey:@"20003333" iv:@"AES"]);
NSData *otherData = [oData AES128EncryptWithKey:@"20003333" iv:@"AES"];
NSLog(@"%@",[myData YYY_AES128DecryptWithKey:@"20003333" iv:@"AES"]);
NSLog(@"%@",[otherData AES128DecryptWithKey:@"20003333" iv:@"AES"]);
NSLog(@"%@",[otherData YYY_AES128DecryptWithKey:@"20003333" iv:@"AES"]);
NSLog(@"%@",[myData AES128DecryptWithKey:@"20003333" iv:@"AES"]);
}
<2020-03-19 05:30:37 +0000NSData+YYYYY.m:(20)>-+[NSData(YYYYY) load]-{length = 9, bytes = 0x313233343637383930}-
<2020-03-19 05:30:39 +0000NSData+YYYYY.m:(22)>-+[NSData(YYYYY) load]-{length = 16, bytes = 0x728adf7a267ddc6916e76f0342fd8e68}-
<2020-03-19 05:30:41 +0000NSData+YYYYY.m:(23)>-+[NSData(YYYYY) load]-{length = 16, bytes = 0x728adf7a267ddc6916e76f0342fd8e68}-
<2020-03-19 05:30:46 +0000NSData+YYYYY.m:(27)>-+[NSData(YYYYY) load]-{length = 16, bytes = 0x13f6bc9b49a4cc3022165ef5dee60f79}-
<2020-03-19 05:30:47 +0000NSData+YYYYY.m:(28)>-+[NSData(YYYYY) load]-{length = 16, bytes = 0x13f6bc9b49a4cc3022165ef5dee60f79}-
<2020-03-19 05:30:53 +0000NSData+YYYYY.m:(32)>-+[NSData(YYYYY) load]-{length = 9, bytes = 0x313233343637383930}-
<2020-03-19 05:30:57 +0000NSData+YYYYY.m:(33)>-+[NSData(YYYYY) load]-{length = 9, bytes = 0x313233343637383930}-
<2020-03-19 05:30:59 +0000NSData+YYYYY.m:(35)>-+[NSData(YYYYY) load]-{length = 9, bytes = 0x707760343637383930}-
<2020-03-19 05:31:02 +0000NSData+YYYYY.m:(36)>-+[NSData(YYYYY) load]-{length = 9, bytes = 0x707760343637383930}-
可以看到原始明文是0x313233343637383930。
使用kCCOptionPKCS7Padding | kCCOptionECBMode(简称03)加密后是0x728adf7a267ddc6916e76f0342fd8e68。
使用kCCOptionPKCS7Padding(简称01)加密后是0x13f6bc9b49a4cc3022165ef5dee60f79。
对03的密文使用03解密0x313233343637383930,
对01的密文使用01解密0x313233343637383930,
但
对01的密文使用03解密0x707760343637383930。
对03的密文使用01解密0x707760343637383930。
会导致前面几位不同。
这么简单的问题,去年的我竟然找不到解决办法。
总结:这是由相同的加密算法但使用了不同的填充算法引发的血案。