Encrypt iOS and Decrypt Node.js AES

前端 未结 2 1859
梦如初夏
梦如初夏 2020-12-09 07:44

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 relat

2条回答
  •  盖世英雄少女心
    2020-12-09 07:57

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

提交回复
热议问题