解密用Objective-C和Java加密的AES数据

我尝试解密最初用Java中的Objective-C加密的数据。

还有其他问题提到这一点,但它们真的很混乱,其中很多都没有解决,因此我会发布我自己的。

这是加密数据的代码:

- (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(); 

如果我现在尝试解密通过Objective-C加密的文件,我会得到一个错误的填充exception。 如果我打开带有加密内容的两个文件,它们是不同的:

你好世界! 用Java加密: 96 C5 CB 51 39 B5 27 FB B3 93 BF 92 18 BB 16 9B
你好世界! 用ObjC加密: A3 61 32 8E A5 E6 66 E0 41 64 89 25 62 D3 21 16

文件内容不应该相同吗? 我想我在两种语言中没有得到算法的所有参数相同。

我需要更改Java代码以获得与Objective-C代码相同的结果,以便能够解密使用Objective-C加密的某些数据。

  1. 我不认为CCCrypt支持使用相同的数组进行输入和输出。 尝试使用两个不同的arrays。
  2. 您必须自己调整输出数组的大小(调用后numBytesEncrypted应该等于16)。
  3. 据我所知,使用ECB加密而不是CBC的无效IV信号。 只要您的输入小于15个字节,它就不应该有任何区别,但它仍然是您应该修复的。

编辑:另一个问题:

  1. 您使用的是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版本在使用什么

这可能不会导致您的问题,但无论如何它都是错误的:

  char * keyPtr[kCCKeySizeAES128+1]; // room for terminator (unused) 

它定义了一个kCCKeySizeAES128 + 1 指针数组,而不是kCCKeySizeAES128 + 1个字节。 碰巧,它是正常的,因为你得到的缓冲区比你需要的大四到八倍,这取决于你是编译32位还是64位。