解密使用Objective-C与Java进行AES加密的数据
我尝试解密最初使用Java中的Objective-C加密的数据。解密使用Objective-C与Java进行AES加密的数据
还有其他问题提到这一点,但他们真的很混乱,他们中的许多都还没有解决,因此我会张贴自己的。
这是对数据加密的代码:
- (int) encryptWithKey: (NSString *) key
{
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char * keyPtr[kCCKeySizeAES128+1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
// fetch key data
[key getCString: keyPtr maxLength: sizeof(keyPtr) encoding: NSUTF8StringEncoding];
// encrypts in-place, since this is a mutable data object
size_t numBytesEncrypted = 0;
CCCryptorStatus result = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES128,
NULL /* initialization vector (optional) */,
[self mutableBytes], [self length], /* input */
[self mutableBytes], [self length]+32, /* output */
&numBytesEncrypted);
return numBytesEncrypted;
}
我执行此功能,并将所得数据刻录到光盘,此代码写:
NSString* strTest = @"Hallo Welt!";
NSLog(@"strTest = %@", strTest);
NSMutableData *protectedData = [NSMutableData dataWithData:[strTest dataUsingEncoding:NSUTF8StringEncoding]];
int laenge = [protectedData encryptWithKey:@"keykeykeykeykeykeykeykey"];
NSData* dataOutput = [[NSData alloc] initWithBytes:[protectedData bytes] length:laenge];
[dataOutput writeToFile:@"/encryptedFileObjC" atomically:YES];
在Java中我使用此代码试图达到相同的行为:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
String keyString = "keykeykeykeykeykeykeykey";
byte[] keyBytes = keyString.getBytes("UTF-8");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, "AES"),
new IvParameterSpec(new byte[16]));
byte[] resultBytes = cipher.doFinal("Hallo Welt!".getBytes("UTF8"));
FileOutputStream out =
new FileOutputStream(new File("encryptedFileJava"));
out.write(resultBytes);
out.close();
如果我现在尝试解密文件是e通过Objective-C加密我得到了一个不好的填充异常。如果我用加密的内容打开这两个文件,它们是不同的:
Hallo Welt!用Java加密:96 C5 CB 51 39 B5 27 FB B3 93 BF 92 18 BB 16 9B
Hallo Welt!使用ObjC加密:A3 61 32 8E A5 E6 66 E0 41 64 89 25 62 D3 21 16
文件内容不应该相同吗?我想我没有在两种语言中得到相同算法的所有参数。
我需要修改Java代码以获得与Objective-C代码相同的结果,以便能够解密用Objective-C加密的一些数据。
- 我不会假设CCCrypt支持使用相同的数组输入和输出。尝试使用两个不同的数组。
- 你必须自己调整输出数组的大小(在调用之后numBytesEncrypted应该等于16)。
- 据我所见,一个空IV信号使用ECB加密而不是CBC。只要你的输入小于15字节,它应该没有什么区别,但它仍然是你应该修复的东西。
编辑:另一个问题:
- 您正在使用24字节密钥。AES-128需要128位= 16字节密钥,AES-192需要192位= 24字节密钥,AES-256需要256位= 32字节密钥。您明确地将AES-128指示为CCCrypt,这意味着它将忽略密钥的最后8个字节。您只是将AES指示为Java,这意味着它会根据密钥大小来决定使用哪种AES变体。由于您提供的是24字节密钥,因此它使用AES-192。修复它,使两端使用相同的算法,你应该是好的。
您可能有一堆问题。
在做任何加密/解密,你需要确保:
- 字符串编码是相同的(你使用两个UTF8,这就是好)
- 填补方案是相同的(你PKCS5上一个和PKCS7另一方面)
- 初始化向量是相同的(你对其他的一个空和空字节)
当然..和所述加密方案是相同的。混淆你的加密似乎使用AES128,虽然评论讨论使用AES256。不知道什么Java版本正在使用
我的填充问题是它似乎在java中没有可用的pkcs5padding。其他一些网页建议使用pkcs5,因为它几乎相同。 – Janusz 2010-06-22 10:57:29
“PKCS#5填充”和“PKCS#7填充”是同义词。 – 2010-06-22 12:51:53
这可能无助于你的问题,但它是错的呢:
char * keyPtr[kCCKeySizeAES128+1]; // room for terminator (unused)
定义kCCKeySizeAES128 + 1个指针,不kCCKeySizeAES128 + 1个的字节数组。碰巧,因为你得到的缓冲区比你需要的大四倍或八倍,这取决于你是在编译32位还是64位。
我不能做任何与objc代码的数据已被加密 – Janusz 2010-06-22 12:56:28
我很惊讶Java代码可以运行,因为keyBytes数组只有长度15,而不是有效的AES密钥长度。 – 2010-06-22 11:07:35
密钥长度为什么是15?我假设长度是24字节,我对加密非常陌生,所以如果我有一个基本的误解,请纠正我。 – Janusz 2010-06-22 12:10:23
@Janusz你可以帮我拿这个加密/解密的示例代码,我的电子邮件ID是 - [email protected]。我面临同样的问题。谢谢。 – 2013-06-28 08:15:08