Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Encrypt iOS and Decrypt Node.js AES

I have searched high and low for a solution which and encrypt on Node.js server and Objective-C client, and vise versa using AES (or other if appropriate)

I am relatively new to cryptography, and understanding why my encrypted text is different in each language is beyond my knowledge.

This is what I have so far:

Node.js crypto methods Using this CryptoJS Library - node-cryptojs-aes

var node_cryptojs = require("node-cryptojs-aes");
var CryptoJS = node_cryptojs.CryptoJS;

    var textToEncrypt = 'Hello';
var key_clear = 'a16byteslongkey!';

//encrypted + decrypted

var encrypted = CryptoJS.AES.encrypt(clearText, key_clear, { iv: null });
var decrypted = CryptoJS.AES.decrypt(encrypted, key_clear, { iv: null });

//Outputs   
    console.log("encrypted: " + encrypted);     //encrypted: U2FsdGVkX1/ILXOjqIw2Vvz6DzRh1LMHgEQhDm3OunY=
console.log("decrypted: " + decrypted.toString(CryptoJS.enc.Utf8));   // decrypted: Hello

Objective-C crypto methods Using AESCrypt library

NSString* textToEncrypt = @"Hello";

// encrypt
NSString* encryptedText = [AESCrypt encrypt:textToEncrypt password:@"a16byteslongkey!"];

// decrypt
NSString* decryptedText = [AESCrypt decrypt:encryptedText password:@"a16byteslongkey!"];

// output
NSLog(@"Text to encrypt: %@", textToEncrypt);    // Text to encrypt: Hello
NSLog(@"Encrypted text: %@", encryptedText);     // Encrypted text: wY80MJyxRRJdE+eKw6kaIA==
NSLog(@"Decrypted text: %@", decryptedText);     // Decrypted text: Hello

I've been scratching my head for ages and tried everything I can think of. Can show underlying crypto methods from the libraries if required. There is SHAR256 hash applied to the key in AESCrypt library but I have removed this, and think there is some missmatch with the string encoding.

like image 211
karlsburg Avatar asked Dec 11 '22 11:12

karlsburg


1 Answers

I'm posting this here because there are bound to be others trying to interop Node.js and iOS. Everyone seems to get hung up on keeping everything in the correct structures, buffers, strings etc. I know I did. So here is a step-by-step process to creating a key, creating an iv, encrypting, decrypting and placing in base64 for easy transfer:

JavaScript (Node.js using the CryptoJS module)

    // Generate key from password and salt using SHA256 to hash and PDKDF2 to harden
    var password = "1234567890123456";
    var salt = "gettingsaltyfoo!";
    var hash = CryptoJS.SHA256(salt);
    var key = CryptoJS.PBKDF2(password, hash, { keySize: 256/32, iterations: 1000 });
    console.log("Hash :",hash.toString(CryptoJS.enc.Base64));
    console.log("Key :",key.toString(CryptoJS.enc.Base64));

    // Generate a random IV
    var iv = CryptoJS.lib.WordArray.random(128/8);
    console.log("IV :",iv.toString(CryptoJS.enc.Base64));

    // Encrypt message into base64
    var message = "Hello World!";
    var encrypted = CryptoJS.AES.encrypt(message, key, { iv: iv });
    var encrypted64 = encrypted.ciphertext.toString(CryptoJS.enc.Base64);
    console.log("Encrypted :",encrypted64);

    // Decrypt base64 into message again
    var cipherParams = CryptoJS.lib.CipherParams.create({ ciphertext: CryptoJS.enc.Base64.parse(encrypted64) });
    var decrypted = CryptoJS.AES.decrypt(cipherParams, key, { iv: iv }).toString(CryptoJS.enc.Utf8);
    console.log("Decrypted :",decrypted);

iOS SDK using CommonCrypto

    // Generate key from password and salt using SHA256 to hash and PDKDF2 to harden
    NSString* password = @"1234567890123456";
    NSString* salt = @"gettingsaltyfoo!";
    NSMutableData* hash = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
    NSMutableData* key = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
    CC_SHA256(salt.UTF8String, (CC_LONG)strlen(salt.UTF8String), hash.mutableBytes);
    CCKeyDerivationPBKDF(kCCPBKDF2, password.UTF8String, strlen(password.UTF8String), hash.bytes, hash.length, kCCPRFHmacAlgSHA1, 1000, key.mutableBytes, key.length);
    NSLog(@"Hash : %@",[hash base64EncodedStringWithOptions:0]);
    NSLog(@"Key : %@",[key base64EncodedStringWithOptions:0]);

    // Generate a random IV (or use the base64 version from node.js)
    NSString* iv64 = @"ludWXFqwWeLOkmhutxiwHw==";       // Taken from node.js CryptoJS IV output
    NSData* iv = [[NSData alloc] initWithBase64EncodedString:iv64 options:0];
    NSLog(@"IV : %@",[iv base64EncodedStringWithOptions:0]);

    // Encrypt message into base64
    NSData* message = [@"Hello World!" dataUsingEncoding:NSUTF8StringEncoding];
    NSMutableData* encrypted = [NSMutableData dataWithLength:message.length + kCCBlockSizeAES128];
    size_t bytesEncrypted = 0;
    CCCrypt(kCCEncrypt,
            kCCAlgorithmAES128,
            kCCOptionPKCS7Padding,
            key.bytes,
            key.length,
            iv.bytes,
            message.bytes, message.length,
            encrypted.mutableBytes, encrypted.length, &bytesEncrypted);
    NSString* encrypted64 = [[NSMutableData dataWithBytes:encrypted.mutableBytes length:bytesEncrypted] base64EncodedStringWithOptions:0];
    NSLog(@"Encrypted : %@",encrypted64);

    // Decrypt base 64 into message again
    NSData* encryptedWithout64 = [[NSData alloc] initWithBase64EncodedString:encrypted64 options:0];
    NSMutableData* decrypted = [NSMutableData dataWithLength:encryptedWithout64.length + kCCBlockSizeAES128];
    size_t bytesDecrypted = 0;
    CCCrypt(kCCDecrypt,
            kCCAlgorithmAES128,
            kCCOptionPKCS7Padding,
            key.bytes,
            key.length,
            iv.bytes,
            encryptedWithout64.bytes, encryptedWithout64.length,
            decrypted.mutableBytes, decrypted.length, &bytesDecrypted);
    NSData* outputMessage = [NSMutableData dataWithBytes:decrypted.mutableBytes length:bytesDecrypted];
    NSString* outputString = [[NSString alloc] initWithData:outputMessage encoding:NSUTF8StringEncoding];
    NSLog(@"Decrypted : %@",outputString);

The output should be the same

    /*
        Hash : AEIHWLT/cTUfXdYJ+oai6sZ4tXlc4QQcYTbI9If/Moc=
        Key : WdHhJ19dSBURBA25HZSpbCJ4KnNEEgwzqjgyTBqa3eg=
        IV : ludWXFqwWeLOkmhutxiwHw==
        Encrypted : D3JpubesPMgQTiXbaoxAIw==
        Decrypted : Hello World!
    */

Hopefully this saves someone else the time I've wasted :)

like image 96
Aku Avatar answered Dec 17 '22 17:12

Aku