Encryption For Ios 3des Not Same As Android And .net
Solution 1:
Have found a solution for the above problem of encryption value generated different on iOS and .NET or Java.
Answer : 1. In Android and .NET you have to use a key of size 16 Bytes (eg: key="1234567890123456")
In iOS you need to use a key size of 24 bytes but the generation of key makes a little difference. Use the same key as used in Android or .NET (16 bytes) and append it with the first 8 Bytes of the same key.
key16Byte = "1234567890123456" //Android and .NET key key24Byte = key16Byte + "12345678" //ios and Java key, Replicated first 8 Bytes of 16Byte key //new24ByteKey = "123456789012345612345678"
- Remove "& kCCModeCBC" from CCypher Mode. 
- Some values require bytes in CCCrypt function which I have changed in the below mentioned code below. like keyData, encryptData. 
Reason for different encryption generated: Android and .NET - It takes 16Byte key and internally replicates, and generates a 24Byte key.
Java - It throws an Exception "Invalid key length", if you provide a 16Byte key value.
iOS - It generates encryption value with 16Byte and 24Byte both values without throwing any exception, so is the reason we get a different encryption generated in case of 16Byte key.
Java Code
publicclassEncryptionHelper {
// Encrypts string and encode in Base64publicstatic String encryptText(String plainText,String key, String IV)throws Exception {
   // ---- Use specified 3DES key and IV from other source --------------byte[] plaintext = plainText.getBytes();//inputbyte[] tdesKeyData = key.getBytes();// your encryption keybyte[] myIV = IV.getBytes();// initialization vectorCipherc3des= Cipher.getInstance("DESede/CBC/PKCS5Padding");
    SecretKeySpecmyKey=newSecretKeySpec(tdesKeyData, "DESede");
    IvParameterSpecivspec=newIvParameterSpec(myIV);
    c3des.init(Cipher.ENCRYPT_MODE, myKey, ivspec);
    byte[] cipherText = c3des.doFinal(plaintext);
    StringencryptedString= Base64.encodeToString(cipherText,
            Base64.DEFAULT);
    // return Base64Coder.encodeString(new String(cipherText));return encryptedString;
}
iOS Code:
- (NSString *)encrypt:(NSString *)encryptValue key:(NSString *)key24Byte IV:(NSString *)IV{
    // first of all we need to prepare keyif([key length] != 24)
        return@"Require 24 byte key, call function generate24ByteKeySameAsAndroidDotNet with a 16Byte key same as used in Android and .NET"; //temporary error messageNSData *keyData = [key24Byte dataUsingEncoding:NSUTF8StringEncoding];
    // our key is ready, let's prepare other buffers and moved bytes lengthNSData *encryptData = [encryptValue dataUsingEncoding:NSUTF8StringEncoding];
    size_t resultBufferSize = [encryptData length] + kCCBlockSize3DES;
    unsignedchar resultBuffer[resultBufferSize];
    size_t moved = 0;
    // DES-CBC requires an explicit Initialization Vector (IV)// IV - second half of md5 keyNSMutableData *ivData = [[IV dataUsingEncoding:NSUTF8StringEncoding]mutableCopy];
    NSMutableData *iv = [NSMutableData dataWithData:ivData];
    CCCryptorStatus cryptorStatus = CCCrypt(kCCEncrypt, kCCAlgorithm3DES,
                                            kCCOptionPKCS7Padding , [keyData bytes],
                                            kCCKeySize3DES, [iv bytes],
                                            [encryptData bytes], [encryptData length],
                                            resultBuffer, resultBufferSize, &moved);
    if (cryptorStatus == kCCSuccess) {
        return [[NSData dataWithBytes:resultBuffer length:moved] base64EncodedStringWithOptions:0];
    } else {
        returnnil;
    }
}
iOS
-(NSString *)generate24ByteKeySameAsAndroidDotNet:(NSString *)key{
    NSString *new24ByteKey = key;
    ;
    new24ByteKey = [new24ByteKey stringByAppendingString:[key substringWithRange:NSMakeRange(0, 8)]];
    return new24ByteKey;
}
Solution 2:
As @Jugal Desai mentioned, the key difference between iOS and Android/.Net is that the later ones automatically fill the key (with size 16 bytes) with another 8 bytes from the start of the key! You saved me :) Here I provide the simple fix in Swift 3:
....
YOUR_KEY_SIZE_16 = YOUR_KEY_SIZE_16 + YOUR_KEY_SIZE_16[0...7]
....
Sample complete code (MD5 for key hash + ECB + PKCS7Padding) with base64 result:
functripleDesEncrypt(keyString: String, pass: String) -> String{
    let keyData = keyString.data(using: .utf8)!var digestData =Data(count: Int(CC_MD5_DIGEST_LENGTH))
    _= digestData.withUnsafeMutableBytes {digestBytes in
        keyData.withUnsafeBytes {messageBytes inCC_MD5(messageBytes, CC_LONG(keyData.count), digestBytes)
        }
    }
    digestData = digestData + digestData[0...7]
    let data = pass.data(using: .utf8)!let dataNS = data asNSDatalet cryptData    =NSMutableData(length: Int(dataNS.length) + kCCBlockSize3DES)!let keyLength              = size_t(kCCKeySize3DES)
    let operation: CCOperation=UInt32(kCCEncrypt)
    let algoritm:  CCAlgorithm=UInt32(kCCAlgorithm3DES)
    let options:   CCOptions=UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
    var numBytesEncrypted :size_t =0let cryptStatus =CCCrypt(operation,
        algoritm,
        options,
        (digestData asNSData).bytes,
        keyLength,
        nil,
        dataNS.bytes,
        dataNS.length,
        cryptData.mutableBytes,
        cryptData.length,
        &numBytesEncrypted)
    ifUInt32(cryptStatus) ==UInt32(kCCSuccess) {
        cryptData.length =Int(numBytesEncrypted)
        // Not all data is a UTF-8 string so Base64 is usedlet base64cryptString = cryptData.base64EncodedString(options: NSData.Base64EncodingOptions.lineLength76Characters)
        return base64cryptString
    } else {
        print("Error: \(cryptStatus)")
    }
    return""
}
Solution 3:
How serious in decrypted?
- (NSString *)encrypt:(NSString *)encryptValue key:(NSString *)key24Byte IV:(NSString *)IV{
    // first of all we need to prepare keyif([key length] != 24)
        return@"Require 24 byte key, call function generate24ByteKeySameAsAndroidDotNet with a 16Byte key same as used in Android and .NET"; //temporary error messageNSData *keyData = [key24Byte dataUsingEncoding:NSUTF8StringEncoding];
    // our key is ready, let's prepare other buffers and moved bytes lengthNSData *encryptData = [encryptValue dataUsingEncoding:NSUTF8StringEncoding];
    size_t resultBufferSize = [encryptData length] + kCCBlockSize3DES;
    unsignedchar resultBuffer[resultBufferSize];
    size_t moved = 0;
    // DES-CBC requires an explicit Initialization Vector (IV)// IV - second half of md5 keyNSMutableData *ivData = [[IV dataUsingEncoding:NSUTF8StringEncoding]mutableCopy];
    NSMutableData *iv = [NSMutableData dataWithData:ivData];
    CCCryptorStatus cryptorStatus = CCCrypt(kCCEncrypt, kCCAlgorithm3DES,
                                            kCCOptionPKCS7Padding , [keyData bytes],
                                            kCCKeySize3DES, [iv bytes],
                                            [encryptData bytes], [encryptData length],
                                            resultBuffer, resultBufferSize, &moved);
    if (cryptorStatus == kCCSuccess) {
        return [[NSData dataWithBytes:resultBuffer length:moved] base64EncodedStringWithOptions:0];
    } else {
        returnnil;
    }
}
Post a Comment for "Encryption For Ios 3des Not Same As Android And .net"