2012-06-05 18 views
5

Tôi có một ứng dụng cần mã hóa một số dữ liệu bằng AES/CBC/không có đệm. Ứng dụng này cũng được chuyển trên Android. Có mã hóa được thực hiện như thế này:Mã hóa iOS AES128/CBC/nopadding tại sao không hoạt động?

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

các initializationVector trông như thế này:

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

trên iOS tôi có một cái gì đó như thế này để mã hóa:

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

phương pháp mô tả ở trên là một phần của danh mục trên NSData. phương pháp được gọi là như thế này:

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

vấn đề mà tôi có là tôi không nhận được cùng một dữ liệu được mã hóa trên iOS và Android. Trên iOS, dữ liệu được mã hóa có độ dài 0 byte.

Bạn có thể đưa ra bất kỳ gợi ý nào về cách mã hóa chuỗi bằng AES128 với CBC và không có lớp đệm và có lẽ là ví dụ không?

Cảm ơn bạn

Trả lời

7

Tôi đã tìm ra giải pháp cho vấn đề của mình. Để làm cho công việc mã hóa mà không cần đệm tôi phải thêm 0x0000 thay vì kCCOptionPKCS7Padding hoặc kCCOptionECBMode được xử lý.

Ngoài ra nếu dữ liệu cần được mã hóa không có độ dài nhiều kCCKeySizeAES128 (16) thì vectơ giữ dữ liệu phải được thay đổi kích thước để có độ dài nhiều với kCCKeySizeAES128 và các giá trị trống được điền bằng thứ gì đó. Tôi đã thêm dấu cách.

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

Đề án đệm không tồn tại không có gì. Nếu dữ liệu đơn giản của bạn kết thúc bằng cùng một giá trị như byte đệm, lược đồ của riêng bạn sẽ không thành công. Thay vào đó, bạn nên sử dụng vùng đệm PKCS # 5/PKCS # 7. Tùy thuộc vào nhu cầu của bạn, bạn cũng nên có thêm tính năng bảo vệ tính toàn vẹn (mã hóa chế độ AESCMAC, HMAC hoặc GCM). –

+0

vấn đề là phía máy chủ đã được thực hiện bằng cách sử dụng AES128/CBC/không đệm và sẽ không được sửa đổi để chấp nhận đệm. Tôi biết rằng padding không tồn tại cho không có gì nhưng trong trường hợp này cơ hội dữ liệu cần được mã hóa sẽ kết thúc với byte đệm thực sự nhỏ đến 0. –

+2

OK, vậy thì tốt, nhưng hãy nhớ: một triệu cơ hội một thành công chín lần trong số mười lần (Terry Pratchett). Đảm bảo ghi lại "tính năng" này. –

Các vấn đề liên quan