2017-03-20 38 views
5

Triển khai AES256 trên iOS bằng chức năng CCCrypt. Nhưng đầu ra và chiều dài bộ đệm đầu ra khác với Android.Mã hóa AES trên iOS và android, đầu ra và kích thước bộ đệm khác nhau

Lớp mật mã trong Android tạo dữ liệu 48 byte trong đó trong iOS, chúng tôi nhận được dữ liệu 80 byte.

Trong IOS sử dụng kCCAlgorithmAES, kCCOptionPKCS7Padding và trong android bằng AES/CBC/PKCS5Padding.

trong IOS IV là NULL và tạo android iv làm mảng 16 byte mới.

Vui lòng trợ giúp.

vui lòng tìm đầu vào và mã để tham khảo.

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    NSString *message = [NSString stringWithFormat:@"com.myapp.com|355004059196637|911111111111|11341e5e-9643-4559-bbb7-34d40555e96c"]; 
    NSString *key = [NSString stringWithFormat:@"4f28d5901b4b7b80d33fda76ca372c2a20bd1a6c2aad7fa215dc79d507330678"]; 
    NSString *shaEncryptMessage = [self sha256:message length:0]; 
    NSData *aesEncryptData = [self aesEncrypt:[shaEncryptMessage dataUsingEncoding:NSUTF8StringEncoding] key:key iv:nil]; 
    NSString *hMac = [aesEncryptData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; 
    NSLog(@"hMac = %@",hMac); 

    // IOS output : Can+oQR79D3/lsQGctzY/d2VBNZbWWtJxGI8iRIu80R2yTskn9gf2oKHaRESX73u 
    //     LpJHLx1Xr6iH11jFPlmqwW7mQz0xAW4uACNAMEoZ0kY= 
    // Android output : MiMDkdo5cGsPMj2qCnNobgp7dr5KMvBhGuKTonrqr1lCYte/kKegGMtI/4TPhUNI 
} 


- (NSString*) sha256:(NSString *)key length:(NSInteger) length{ 
    const char *s=[key cStringUsingEncoding:NSASCIIStringEncoding]; 
    NSData *keyData=[NSData dataWithBytes:s length:strlen(s)]; 

    uint8_t digest[CC_SHA256_DIGEST_LENGTH]={0}; 
    CC_SHA256(keyData.bytes, (unsigned int)keyData.length, digest); 
    NSData *out=[NSData dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH]; 
    NSString *hash=[out description]; 
    hash = [hash stringByReplacingOccurrencesOfString:@" " withString:@""]; 
    hash = [hash stringByReplacingOccurrencesOfString:@"<" withString:@""]; 
    hash = [hash stringByReplacingOccurrencesOfString:@">" withString:@""]; 
    return hash; 
} 
- (NSData *)aesEncrypt:(NSData *)plainText key:(NSString *)key iv:(NSString *)iv { 
    char keyPointer[kCCKeySizeAES256+2],// room for terminator (unused) ref: https://devforums.apple.com/message/876053#876053 
    ivPointer[kCCBlockSizeAES128]; 
    BOOL patchNeeded; 
    bzero(keyPointer, sizeof(keyPointer)); // fill with zeroes for padding 
    //key = [[StringEncryption alloc] md5:key]; 
    key = [self stringFromHex:key]; 
    patchNeeded= ([key length] > kCCKeySizeAES256+1); 
    if(patchNeeded) 
    { 
     key = [key substringToIndex:kCCKeySizeAES256]; // Ensure that the key isn't longer than what's needed (kCCKeySizeAES256) 
    } 

    [key getCString:keyPointer maxLength:sizeof(keyPointer) encoding:NSUTF8StringEncoding]; 
    [iv getCString:ivPointer maxLength:sizeof(ivPointer) encoding:NSUTF8StringEncoding]; 

    // if (patchNeeded) { 
    //  keyPointer[0] = '\0'; // Previous iOS version than iOS7 set the first char to '\0' if the key was longer than kCCKeySizeAES256 
    // } 

    NSUInteger dataLength = [plainText length]; 

    // For block ciphers, the output size will always be less than or equal to the input size plus the size of one block. 
    size_t buffSize = dataLength + kCCBlockSizeAES128; 
    void *buff = malloc(buffSize); 

    size_t numBytesEncrypted = 0; 



    CCCryptorStatus status = CCCrypt(kCCEncrypt, /* kCCEncrypt, etc. */ 
            kCCAlgorithmAES128, /* kCCAlgorithmAES128, etc. */ 
            kCCOptionPKCS7Padding, /* kCCOptionPKCS7Padding, etc. */ 
            keyPointer, kCCKeySizeAES256, /* key and its length */ 
            NULL, /* initialization vector - use random IV everytime */ 
            [plainText bytes], [plainText length], /* input */ 
            buff, buffSize,/* data RETURNED here */ 
            &numBytesEncrypted); 


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

    free(buff); 
    return nil; 
} 

- (NSString *) stringFromHex:(NSString *)str 
{ 
    NSMutableData *stringData = [[NSMutableData alloc] init]; 
    unsigned char whole_byte; 
    char byte_chars[3] = {'\0','\0','\0'}; 
    int i; 
    for (i=0; i < [str length]/2; i++) { 
     byte_chars[0] = [str characterAtIndex:i*2]; 
     byte_chars[1] = [str characterAtIndex:i*2+1]; 
     whole_byte = strtol(byte_chars, NULL, 16); 
     [stringData appendBytes:&whole_byte length:1]; 
    } 
    return [[NSString alloc] initWithData:stringData encoding:NSASCIIStringEncoding]; 
} 

Hãy tìm mã android cũng có,

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    generateHMAC(); 
} 

String K0 = "4f28d5901b4b7b80d33fda76ca372c2a20bd1a6c2aad7fa215dc79d507330678"; 
String generatedString = "com.myapp.com|355004059196637|911111111111|11341e5e-9643-4559-bbb7-34d40555e96c"; 

private void generateHMAC() { 
    Log.d("Message of Hash", generatedString); 
    byte[] var14 = new byte[0]; 
    try { 
     var14 = SHA256(generatedString); 
     byte[] var15 = new byte[0]; 
     var15 = encrypt(var14, hexStringToByteArray(K0)); 
     String var4 = Base64.encodeToString(var15, 2); 
     Log.d("Existing K0", K0); 
     Log.d("HMAC", var4); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 


public byte[] SHA256(String paramString) throws Exception { 
    MessageDigest md = MessageDigest.getInstance("SHA-256"); 
    md.update(paramString.getBytes("UTF-8")); 
    byte[] digest = md.digest(); 
    return digest; 
} 

public byte[] encrypt(byte[] var1, byte[] var2) throws Exception { 
    SecretKeySpec var3 = new SecretKeySpec(var2, "AES"); 
    byte[] var4 = new byte[16]; 
    IvParameterSpec var5 = new IvParameterSpec(var4); 
    Cipher var6 = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    var6.init(1, var3, var5); 
    byte[] var7 = var6.doFinal(var1); 
    return var7; 
} 

public byte[] hexStringToByteArray(String var1) { 
    byte[] var2 = new byte[var1.length()/2]; 

    for (int var3 = 0; var3 < var2.length; ++var3) { 
     int var4 = var3 * 2; 
     int var5 = Integer.parseInt(var1.substring(var4, var4 + 2), 16); 
     var2[var3] = (byte) var5; 
    } 

    return var2; 
} 
+0

hãy thử https://github.com/alexeypro/EncryptDecrypt AES256EncryptWithKey – Rivendell

+0

Bạn có thể đăng mã không? – TheGreatContini

+0

Mặc dù điều này không trả lời câu hỏi của bạn, bạn nên biết rằng mặc dù Apple cho bạn biết rằng Vector khởi tạo (IV) là tùy chọn, mã hóa không an toàn nếu bạn không chỉ định và chọn IV theo cách không thể đoán trước. Xấu hổ về Apple cho API mã hóa kém này. – TheGreatContini

Trả lời

3

cập nhật sau khi bạn cung cấp đang iOS:

  • Các aesEncryptData nên đầu ra của bạn. Loại bỏ hmac, điều đó không liên quan gì đến mã hóa AES (thay vào đó là tính toàn vẹn của thông báo).
  • Cách duy nhất bạn sẽ khớp với mã Android của mình là nếu bạn đang sử dụng cùng một mã IV mà mã Android đang sử dụng. trả lời

Đầu:

bao lâu là đầu vào? Cung cấp mã nguồn và dữ liệu mẫu có thể giúp chúng tôi giải quyết vấn đề nhanh hơn.

Nếu không có thông tin yêu cầu, tôi không có câu trả lời của bạn, nhưng tôi có một vài gợi ý có thể giúp bạn có được để dưới cùng của nó:

  • đệm của bạn là được. PKCS5Padding trong Java là wrongly named triển khai PKCS # 7, vì vậy nó phải tương thích với kCCOptionPKCS7Padding của Apple.
  • Apple by default uses CBC mode dưới mui xe nếu không có chế độ nào được chỉ định, để đồng ý với mã Android. Vì vậy, đó không thể là vấn đề hoặc.
  • Khi bạn mã hóa, bản mã sẽ là bội số của 16 byte (vì AES có kích thước khối N = 16 byte và theo defn của PKCS #7). Cụ thể:
    • Nếu đầu vào là bội số của 16 byte, thì đầu ra phải chính xác hơn 16 byte so với đầu vào.
    • Nếu đầu vào không phải là bội số của 16 byte, thì đầu ra phải là 16 * Trần (Độ dài đầu vào/16). Ví dụ: 47 byte đầu vào phải là 16 * Trần (17/16) = 16 * 3 = 48 byte đầu ra.
  • Có thể một trong các triển khai sẽ xuất ra IV như một phần của bản mã. Nếu điều này xảy ra, nó sẽ ở phần đầu của bản mã. Bạn sẽ có thể kiểm tra xem điều này có xảy ra không.(Hãy cho tôi biết nếu điều đó đang xảy ra, vui lòng)

Có điều gì đó kỳ quặc và có khả năng được triển khai sai, và chúng tôi cần mã để đến đáy của nó. Không có nghĩa là mã Android dẫn đến 3 khối 16 trong khi mã Apple dẫn đến 5 khối 16.

Ngoài ra, Apple cho bạn biết rằng IV là tùy chọn, chúng có nghĩa là nó là tùy chọn trong việc nhận mã để hoạt động. Nó là not optional for security. IV là bắt buộc và không thể đoán trước được đối với phương thức hoạt động của CBC, và chúng không bao giờ được lặp lại. Nếu bạn bỏ qua điều đó, bạn sẽ rò rỉ thông tin về dữ liệu của mình và trong một số trường hợp, kẻ tấn công có thể giải mã được dữ liệu (các cuộc tấn công oracle đệm).

+0

Cảm ơn @ TheGreatContini, thêm mã iOS và đầu vào mẫu để bạn tham khảo. Xin hãy giúp giải quyết vấn đề này. – Pradip

+0

@Pradip bạn có HMAC-sha256 sau AES, một thuật toán hoàn toàn khác. Lấy HMAC ra, bạn chỉ muốn mã hóa và không có gì khác. Để khớp với Android, bạn sẽ cần phải sử dụng cùng một IV được sử dụng trong Android. Bạn không thể chỉ cần thay thế nil và mong đợi dữ liệu để phù hợp bởi vì nó sẽ không. – TheGreatContini

+0

Vui lòng tìm mã Android được cập nhật, SHA256 theo sau là AES và ouput theo sau là mã hóa base64 (như logic yêu cầu của chúng tôi). Tôi muốn logic tương tự cho iOS như trong android. – Pradip

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