2017-07-14 167 views
1

我一直试图解密服务器发送给我的应用的一些AES加密数据。无法使用使用Java加密的Obj-C对AES数据进行解密

为了提炼出问题,我写了一个模拟服务器在做什么的小型java程序。它使用AES加密一些测试数据然后将它编码为Base64:

AesCipherService cipherService = new AesCipherService(); 
cipherService.setKeySize(128); 

String stringKey = "2EE1F10212ADD4BE"; 
byte[] keyAsBytes = stringKey.getBytes(); 

String text = "text to encrypt"; 
byte[] encryptedBytes = cipherService.encrypt(text.getBytes(), keyAsBytes).getBytes(); 
String base64String  = Base64.encodeToString(encryptedBytes); 
System.out.println(base64String); 

// Reverse the process to check can retrieve "text to encrypt": 
byte[] bytesToDecode = Base64.decode(base64String); 
byte[] decryptedBytes = cipherService.decrypt(bytesToDecode, keyAsBytes).getBytes();   
String decryptedString = new String(decryptedBytes); 
System.out.println(decryptedString); 

当运行此是输出:

R5UBpP30YjX9Ae2HoPb2Rrfi5rQJY2d0ac1 + zaIX5A4 =

文本加密

所以我可以成功地加密数据,打印出来。然后,如果我解密它显示原始文本,所以这里的一切工作正常。

现在这里是我的Obj-C代码,我试图解密从Java代码加密的数据。我已经复制/从NetBeans IDE输出窗口粘贴的加密数据作为OBJ-C内容的源数据进行解密:

- (void) decryptData 
{ 
    NSData* dataToDecrypt  = [[NSData alloc] initWithBase64EncodedString: @"R5UBpP30YjX9Ae2HoPb2Rrfi5rQJY2d0ac1+zaIX5A4=" options: 0]; 
    NSString* key    = @"2EE1F10212ADD4BE"; 

    char keyPtr[kCCKeySizeAES128]; 
    bzero(keyPtr, sizeof(keyPtr)); 
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; 

    NSUInteger dataLength = [dataToDecrypt length]; 
    size_t bufferSize = dataLength + kCCBlockSizeAES128; 
    void *buffer = malloc(bufferSize); 

    size_t numBytesDecrypted = 0; 
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, 
              kCCAlgorithmAES, 
              kCCOptionPKCS7Padding, 
              keyPtr, 
              kCCBlockSizeAES128, 
              keyPtr, 
              [dataToDecrypt bytes], 
              dataLength, 
              buffer, 
              bufferSize, 
              &numBytesDecrypted); 
    if (cryptStatus == kCCSuccess) { 
     NSLog(@"Success"); 
     NSData* unencryptedData = [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted]; 
     Byte *unencryptedAsBytes = (Byte*)malloc(unencryptedData.length); 
     memcpy(unencryptedAsBytes, [unencryptedData bytes], unencryptedData.length); 
     NSString *decryptedString = [NSString stringWithUTF8String:[unencryptedData bytes]]; 
     NSLog(@"%@", decryptedString); 
    } 
} 

当该运行状态是kCCSuccess和numBytesDecrypted是32(同由于数据长度),但解密的字符串不是 “文本加密”,decryptedString是零,如果在Xcode的控制台I PO unencryptedAsBytes它会显示这样的:

“\一条Y | \ 376 \ 347cD * \ 320NC \ X14 \ x91C \ x88 \ 301 \ 341z \ xaca \ x11 \ 371

任何想法这里有什么问题?

+0

4.W¯¯这里是'AesCipherService'记录?你是否将密钥用作IV,这是不安全的。 5.也许IV是加密数据中的第一个16字节,这并不罕见。 – zaph

+0

@zaph AesCipherService是Apache加密库https://shiro.apache.org/static/1.2.3/apidocs/org/apache/shiro/crypto/AesCipherService.html的一部分。代码的Java部分不是由我编写的,而是由服务器开发人员编写的,我试图编写Objective-C部分来解密他们已加密的部分。我上面发布的代码是我重新创建他们以精简格式完成的任务,尝试以更易于管理的方式重新创建问题。他们正在使用上面的AesCipherService,即他们没有明确地设置IV等,因此AesCipherService默认值正在被使用。 – Gruntcakes

回答

2

Java加密代码生成一个随机IV,并以它为前缀加密。为了将解密的IV从加密中分离出来。

在十六进制:

key:  32454531463130323132414444344245 
iv:  479501A4FDF46235FD01ED87A0F6F646 (first 16 binary bytes of the full encryption) 
encrypted: B7E2E6B40963677469CD7ECDA217E40E (rest of binary bytes of the full encryption) 
decrypted: 7465787420746F20656E6372797074 

代码:

NSData* fullEncrypted  = [[NSData alloc] initWithBase64EncodedString: @"R5UBpP30YjX9Ae2HoPb2Rrfi5rQJY2d0ac1+zaIX5A4=" options: 0]; 
NSData *ivData = [fullEncrypted subdataWithRange:NSMakeRange(0, kCCBlockSizeAES128)]; 
NSData *encryptedData = [fullEncrypted subdataWithRange:NSMakeRange(kCCBlockSizeAES128, fullEncrypted.length-kCCBlockSizeAES128)]; 
NSLog(@"ivData:   %@", ivData); 
NSLog(@"encryptedData: %@", encryptedData); 

NSData *keyData = [@"2EE1F10212ADD4BE" dataUsingEncoding:NSUTF8StringEncoding]; 
NSLog(@"keyData:   %@", keyData); 

NSMutableData *unencryptedData = [NSMutableData dataWithLength:encryptedData.length]; 
size_t numBytesDecrypted = 0; 
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, 
             kCCAlgorithmAES, 
             kCCOptionPKCS7Padding, 
             keyData.bytes, keyData.length, 
             ivData.bytes, 
             encryptedData.bytes, encryptedData.length, 
             unencryptedData.mutableBytes, unencryptedData.length, 
             &numBytesDecrypted); 
if (cryptStatus == kCCSuccess) { 
    NSLog(@"Success"); 

    unencryptedData.length = numBytesDecrypted; 
    NSLog(@"unencryptedData: %@", unencryptedData); 

    NSString *decryptedString = [[NSString alloc] initWithData:unencryptedData encoding:NSUTF8StringEncoding]; 
    NSLog(@"decryptedString: %@", decryptedString); 
} 

输出:

ivData:   479501a4 fdf46235 fd01ed87 a0f6f646 
encryptedData: b7e2e6b4 09636774 69cd7ecd a217e40e 
keyData:   32454531 46313032 31324144 44344245 
Success 
unencryptedData: 74657874 20746f20 656e6372 79707400 
decryptedString: text to encrypt 
+0

完全真棒!不能够感谢你,我一直坚持这几天。你是如何确定随机四被预先加密的数据? – Gruntcakes

+0

因为这是常见的,并且加密的数据比它应该长一个块。此外,ObjC代码默认为CBC模式,需要IV。当然,我首先猜测编码是错误的。 zaph

+0

顺便说一句,这里是一个整洁[AES转换器(http://extranet.cryptomathic.com/aescalc?key=32454531463130323132414444344245&iv=479501A4FDF46235FD01ED87A0F6F646&input=B7E2E6B40963677469CD7ECDA217E40E&mode=cbc&action=Decrypt&output=B47CF26CD2992D0A765D1731AB4B2904),请注意在输出数据后01,即是填充。 – zaph

相关问题