Skip to content Skip to sidebar Skip to footer

Encryption For Ios 3des Not Same As Android And .net

I'm trying do some encrypt something using 3des on the iOS that must match the results from java and .NET. Java code is : public class EncryptionHelper { // Encrypts string and en

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"

  1. Remove "& kCCModeCBC" from CCypher Mode.

  2. 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"