2010-07-05 233 views
3

更新:找到解決方案。我將很快用實際的工作代碼和命令更新這個問題。用AES 128加密openssl和解密,ecb模式


客戶端正在用C++加密文件服務器端,我需要在iPhone應用程序中解密它。

我的客戶可以在他身上進行加密和解密,我也可以在iPhone上進行解密,但是我們無法解密彼此加密的文件。 我看到很多關於SO的相關問題,但沒有人能幫助我找到一個在兩邊都以相同方式工作的實現。

我想輸出一些我們將接受的樣本值作爲通用實現。

我試圖用openssl加密文件並用可可解密,但是不能。

以下是我使用的加密:

echo "123456789ABCDEFG" | openssl enc -aes-128-ecb -nosalt -K "41414141414141414141414141414141" -iv 0 > hello.txt.bin

添加選項-p OpenSSL的來電顯示和IV使用的關鍵預期:

key=41414141414141414141414141414141 
iv =00000000000000000000000000000000 

而對於可可解密(在NSData類別中):

- (NSData *)AESDecryptWithKey:(NSString *)key { 

    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]; 

    NSUInteger dataLength = [self length]; 

    //See the doc: For block ciphers, the output size will always be less than or 
    //equal to the input size plus the size of one block. 
    //That's why we need to add the size of one block here 
    size_t bufferSize = dataLength + kCCBlockSizeAES128; 
    void *buffer = malloc(bufferSize); 

    size_t numBytesEncrypted = 0; 

    char iv[32]; 
    for (int i = 0; i < 32; i++) { 
     iv[i] = 0; 
    } 

    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionECBMode + kCCOptionPKCS7Padding, 
              keyPtr, kCCKeySizeAES128, 
              iv, //"00000000000000000000000000000000" /* initialization vector (optional) */, 
              [self bytes], dataLength, /* input */ 
              buffer, bufferSize, /* output */ 
              &numBytesEncrypted); 

    if (cryptStatus == kCCSuccess) { 
     //the returned NSData takes ownership of the buffer and will free it on deallocation 
     return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; 
    } 

    free(buffer); //free the buffer; 
    return nil; 
} 

called th是這樣:

- (void)testBinaryFileDecryption { 
    NSString *databasePath = [[NSBundle mainBundle] pathForResource:@"hello" ofType:@"txt.bin"]; 

    NSData *data = [NSData dataWithContentsOfFile:databasePath]; 
    NSAssert(nil != data, @"Encrypted data, freshly loaded from file should not be nil"); 

    NSData *plain = [data AESDecryptWithKey:@"AAAAAAAAAAAAAAAA"]; 
    NSAssert(nil != plain, @"Decrypted plain data should not be nil"); 

    NSLog(@"Result: '%@'", [[NSString alloc] initWithData:plain encoding:NSASCIIStringEncoding]); 
}

結果日誌: Result: '4¨µ¢Ä½Pk£N

我忘記了什麼選擇嗎? NSData的編碼是否返回了NSASCIIStringEncoding以外的內容?

+2

您發現的解決方案發生了什麼?有沒有可能發佈它? – OlivaresF 2011-03-14 01:54:22

回答

2

我對iPhone開發一無所知,但看着這段代碼,看起來你正在嘗試使用實際密鑰的十六進制編碼來解密數據包。 OpenSSL的enc需要十六進制編碼,因爲它將十六進制轉換爲字節。您的實際鍵看起來更像這樣,直接轉換爲ascii時。

["\037", " ", "!", "\"", "#", "$", "%", "&", "'", "\036", "\037", " ", "!", "\"", "#", "$"] 

(所有如果要你用解密成OpenSSL的ENC接受相同的格式字符串編碼,可能是鈍,關鍵是3331333233333334333533363337333833393330333133323333333433353336。)

嘗試在您的iPhone代碼中使用41414141414141414141414141414141的關鍵規範來使用OpenSSL並使用AAAAAAAAAAAAAAAA

此外,我強烈建議您使用長度恰好爲N * 16個字節的數據進行初始測試。 OpenSSL enc使用PKCS#5填充(除非使用-nopad),並且您的iPhone代碼使用PKCS#7填充。粗略看一下RFC,它們似乎是相同的填充機制,但我可能是錯的。

我知道你只是在這裏嘗試一些東西,但在實際的生產代碼中,請不要使用ECB mode

+0

感謝您的快速回復。 用'echo「123456789ABCDEFG」| openssl enc -aes-128-ecb -nosalt -K「41414141414141414141414141414141」-iv 0> hello.txt.bin'和'\t NSData * plain = [data AESDecryptWithKey:@「AAAAAAAAAAAAAAAAA」];',我沒有得到有用的結果(結果:'ĐÊÐÅp:wíö¹X+ 3u |Ýç; Q') – Guillaume 2010-07-05 12:09:14

+0

@Guillaume,昨天晚上寫我的答案時我恐怕太累了 - 看起來IV也出現了同樣的情況:OpenSSL enc正在使用全零的IV,而您的iPhone正在使用全部爲零的IV。 (看起來像0x303030303030的字節。)您可以將一個零數組傳遞給CCCrypt例程,也可以將匹配的IV傳遞給OpenSSL enc。 – sarnold 2010-07-05 21:58:05

+0

我更新了代碼,並在問題中使用了openssl命令。 也不行:( 感謝您的堅韌。任何其他想法? – Guillaume 2010-07-06 07:37:06

2

我使用Crypt :: OpenSSL :: AES來加密在我的iOS應用程序中解密的文件,該應用程序使用CommonCryptor進行解密。

cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, 0, 
          keyPtr, kCCKeySizeAES256, 
          IVECTOR /* initialization vector (optional) -- was NULL*/, 
          [self bytes], dataLength, /* input */ 
          buffer, bufferSize, /* output */ 
          &numBytesDecrypted); 

要初始化該IVECTOR我正在使用bzero。

bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) 

OpenSSL的作用下加密在Perl我這樣做:

my $cipher = Crypt::CBC->new(-key => $key, 
           -literal_key => 1, 
           -header => 'none', 
           -iv =>  '0000000000000000', 
           -cipher => 'Crypt::OpenSSL::AES'); 

的OpenSSL似乎接受 '0000000000000000' IV爲同樣的事情,ASCII 0(零)字符。似乎回想起來似乎合理,但它需要大量的頭髮拉,因爲每個加密失敗看起來像其他加密失敗:垃圾出。