2017-07-14 76 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

相關問題