2012-06-05 38 views
5

我有一個應用程序需要使用AES/CBC /無填充編碼一些數據。該應用程序也在Android上移植。有編碼是這樣完成的:iOS加密AES128/CBC/nopadding爲什麼不能正常工作?

byte[] encodedKey = getKey(); 
    SecretKeySpec skeySpec = new SecretKeySpec(encodedKey, "AES"); 
    AlgorithmParameterSpec paramSpec = new IvParameterSpec(initializationVector); 

    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); 
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec, paramSpec); 

    int blockSize = cipher.getBlockSize(); 
    int diffSize = decrypted.length % blockSize; 
    System.out.println("Cipher size: " + blockSize); 
    System.out.println("Current size: " + decrypted.length); 
    if (diffSize != 0) { 
     diffSize = blockSize - diffSize; 
     byte[] oldDecrypted = decrypted; 
     decrypted = new byte[decrypted.length + diffSize]; 
     System.arraycopy(oldDecrypted, 0, decrypted, 0, oldDecrypted.length); 
     for (int i = 0; i < diffSize; i++) { 
     decrypted[i + oldDecrypted.length] = " ".getBytes()[0]; 
     } 
     System.out.println("New size: " + decrypted.length); 

    } 
    return cipher.doFinal(decrypted); 

的initializationVector看起來是這樣的:

private byte[] initializationVector = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 

iOS上我有這樣的事情加密:

- (NSData *)AES128EncryptWithKey:(NSString *)key 
{ 
    // 'key' should be 16 bytes for AES128, 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]; 

    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; 
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, 
              kCCAlgorithmAES128, 
              0x0000, 
              keyPtr, 
              kCCKeySizeAES128, 
              NULL /* 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; 
} 

上述方法是屬於NSData類別的一部分。 調用該方法是這樣的:

NSData *data = [@"4915200456727" dataUsingEncoding:NSUTF8StringEncoding]; 
    NSData *cipher = [data AES128EncryptWithKey:@"@x#zddXekZerBBw6"]; 
    NSString *ecriptedString = [NSString stringWithFormat:@"%.*s", [cipher length], [cipher bytes]]; 

,我有是,我沒有收到關於iOS和Android相同的加密數據的問題。在iOS上,加密數據的長度爲0字節。

你可以給任何關於如何加密字符串使用AES128與CBC和沒有填充和可能的例子?

謝謝

回答

7

我找到了我的問題的解決方案。爲了使加密工作沒有填充我不得不添加0x0000而不是kCCOptionPKCS7Padding或kCCOptionECBMode哪些被處理。

此外,如果需要編碼的數據不具有kCCKeySizeAES128(16)的長度倍數,則必須調整包含數據的向量的大小,使其具有kCCKeySizeAES128的長度倍數和空值填充某些值。我添加了空格。

- (NSData *)AES128EncryptWithKey:(NSString *)key 
{ 
    char keyPtr[kCCKeySizeAES128+1]; 
    bzero(keyPtr, sizeof(keyPtr)); 

    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; 

    int dataLength = [self length]; 
    int diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128); 
    int newSize = 0; 

    if(diff > 0) 
    { 
     newSize = dataLength + diff; 
    } 

    char dataPtr[newSize]; 
    memcpy(dataPtr, [self bytes], [self length]); 
    for(int i = 0; i < diff; i++) 
    { 
     dataPtr[i + dataLength] = 0x20; 
    } 

    size_t bufferSize = newSize + kCCBlockSizeAES128; 
    void *buffer = malloc(bufferSize); 

    size_t numBytesEncrypted = 0; 
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, 
              kCCAlgorithmAES128, 
              0x0000, //No padding 
              keyPtr, 
              kCCKeySizeAES128, 
              NULL, 
              dataPtr, 
              sizeof(dataPtr), 
              buffer, 
              bufferSize, 
              &numBytesEncrypted); 

    if(cryptStatus == kCCSuccess) 
    { 
     return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; 
    } 

    return nil; 
} 
+0

填充方案並不存在。如果您的普通數據與填充字節的值相同,則您自己的方案將失敗。您應該使用PKCS#5/PKCS#7填充。根據您的需要,您還應該添加完整性保護(AESCMAC,HMAC或GCM模式加密)。 –

+0

問題是服務器端已經使用AES128/CBC/no padding實現,並且不會被修改爲接受填充。我知道填充並不存在,但在這種情況下,數據需要加密的機會將以填充字節結束,真的很小到0. –

+2

好吧,那很好,但請記住:一對一的機會在十分之九的成功(特里Pratchett)。一定要記錄這個「功能」。 –