Objective-C的AES加密与Java的AES加密看起来不太一样。

3

Well im trying to encrypt an string in objective c extending NSData with this method:


 @implementation NSData (AES128)

  • (NSData *)AES128Encrypt { //定义加密密钥 char keyPtr[kCCKeySizeAES128] = {'\xe1','\xaa','\x9c','\x61','\x46','\x74','\x44','\x56','\xf0','\xe5','\x47','\x46','\x86','\xdc','\x95','\x77'}; //获取待加密数据长度 NSUInteger dataLength = [self length]; //计算加密后数据的缓存区大小 size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); //加密操作 size_t numBytesEncrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, keyPtr, kCCKeySizeAES128, NULL /* initialization vector (optional) */, [self bytes], dataLength, buffer, bufferSize, &numBytesEncrypted); if (cryptStatus == kCCSuccess) { //将加密后的数据转化为NSData类型并返回,同时释放缓存区 return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; } free(buffer); //释放缓存区 return nil; }

  • (NSData *)AES128Decrypt { //定义解密密钥 char keyPtr[kCCKeySizeAES128] = {'\xe1','\xaa','\x9c','\x61','\x46','\x74','\x44','\x56','\xf0','\xe5','\x47','\x46','\x86','\xdc','\x95','\x77'}; //获取待解密数据长度 NSUInteger dataLength = [self length]; //计算解密后数据的缓存区大小 size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); //解密操作 size_t numBytesDecrypted = 0; CCCryptorStatus cryptStatus=CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, keyPtr, kCCKeySizeAES128, NULL /* initialization vector (optional) */, [self bytes], dataLength, buffer, bufferSize, &numBytesDecrypted); if (cryptStatus == kCCSuccess) { //将解密后的数据转化为NSData类型并返回,同时释放缓存区 return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted]; } free(buffer); //释放缓存区 return nil; }

@end

then i call it here:


NSString *strData = @"My string";

NSData *objNSData = [NSData dataWithData:[strData dataUsingEncoding:NSUTF8StringEncoding]];

NSLog(@"加密后的数据: %@",[objNSData description]);

如果我只是在Objective-C中使用它,那么它可以正常工作。但是当我尝试将其发送到Java服务器时,它就无法工作了。

我的加密数据看起来像这样:

86fcf0fa9e3dff93dc8918ffd02ee203 12de0bf8c8ba300456293c4240296c0d

如果我尝试使用相同的密钥在Java中进行AES加密,我会得到这个结果:

86fcf0fa9e3dff93dc8918ffd02ee203 8388f173da143c6aeeb90e554259c83c

很奇怪,因为前半部分是一样的。

有人知道为什么会发生这种情况吗?谢谢。

1个回答

9
我从未进行过Objective-C编程,但我几乎可以确定你的代码中使用了不同模式的AES。您需要确保这些模式是一致的。默认情况下可能是Cipher Block Chaining(CBC)模式。请确保在Java代码中设置此选项。
顺便说一句,CBC模式应具有随机初始化向量(IV),而不是NULL(我假设使用全零)。这也需要在两者之间保持一致。
我必须声明加密标准通常更安全地使用高级协议,例如SSL/TLS用于传输数据和像Keyczar这样的东西用于静止数据。正确使用密码学非常困难,一个微小的错误(例如选择错误的模式)可能会完全破坏系统的安全性。

2
哥们,我爱你 :) 其实问题出在我只传递了 kCCOptionPKCS7Padding 选项给 CCCrypt 函数,而我应该传递 kCCOptionPKCS7Padding | kCCOptionECBMode 选项。不管怎样,谢谢你,你的答案救了我的一天 :) - JonLOo
不用谢。请记住,正如我之前提到的那样,您真的不应该使用ECB模式。如果可能的话,请使用类似CBC的东西。请参阅http://www.moserware.com/2009/09/stick-figure-guide-to-advanced.html的第3幕,第21场戏剧(直接链接:http://4.bp.blogspot.com/_Zfbv3mHcYrc/SrfI0ckVcMI/AAAAAAAABss/wUh6hWmtNaU/s1600-h/aes_act_3_scene_21_modes_1100.png) - Jeff Moser
问题在于ECB模式似乎是obj-c中唯一支持的方式。 - JonLOo
根据http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-36064/CommonCrypto/CommonCryptor.h,如果您没有指定模式,则默认为CBC。我会使用它。 "kCCOptionPKCS7Padding" 也可以使用。只需确保在Java端执行相同操作即可。此外,您应该使用随机初始化向量(Java端也需要知道此内容)。 - Jeff Moser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接