Javascript 加密iOS并解密Node.js AES

Javascript 加密iOS并解密Node.js AES,javascript,iphone,ios,node.js,encryption,Javascript,Iphone,Ios,Node.js,Encryption,我在Node.js服务器和Objective-C客户端上到处寻找一种解决方案,使用AES(或其他适当的方法)进行加密,反之亦然 我对密码学比较陌生,我不知道为什么我的加密文本在每种语言中是不同的 这就是我到目前为止所做的: Node.js加密方法 var node_cryptojs = require("node-cryptojs-aes"); var CryptoJS = node_cryptojs.CryptoJS; var textToEncrypt = 'Hello'; var

我在Node.js服务器和Objective-C客户端上到处寻找一种解决方案,使用AES(或其他适当的方法)进行加密,反之亦然

我对密码学比较陌生,我不知道为什么我的加密文本在每种语言中是不同的

这就是我到目前为止所做的:

Node.js加密方法

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
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
Objective-C加密方法

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
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
我挠头已经很久了,想尽了一切办法。如果需要,可以显示库中的底层加密方法。AESCrypt库中的密钥应用了SHAR256散列,但我已经删除了它,并且认为字符串编码存在一些错误匹配

  • 您确定两个库中使用的密钥相同吗?你说你取出了AESCrypt中的SHA-256部件,现在库如何使用密码参数?AES算法只能使用长度为16、24或32字节的密钥。您的密码长度为16字节,但您是否在加密函数中将相应的参数更改为128(而不是256)? 你知道CryptoJS是如何使用密钥参数的吗?您确定它是直接使用的,还是在传递给底层原始AES加密函数之前可能会进行一些处理(例如,哈希)

  • CryptoJS库使用什么加密模式?它的文档没有说。考虑到它需要静脉注射,可能是CBC,但你必须查看来源才能确定。 AESCrypt的文档声称使用CBC模式,但您没有在任何地方给它静脉注射。这一定意味着它在某个地方生成自己的,或者总是使用一个固定的。(这一半违背了CBC模式的目的,但那是另一回事)。所以你需要弄清楚静脉注射到底是什么


  • TL;DR:除非您确保在两个库中使用相同的密钥和密钥长度、相同的模式和相同的IV,否则您将拥有不同的密码文本。

    我在这里发布这篇文章,因为肯定会有其他人试图互操作Node.js和iOS。每个人似乎都很想把所有东西都保持在正确的结构、缓冲区、字符串等中。我知道我做到了。下面是一个逐步创建密钥、创建iv、加密、解密并放入base64以便于传输的过程:

    JavaScript(Node.js使用CryptoJS模块)

    使用CommonCrypto的iOS SDK

        // 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);
    
    输出应相同

        // 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);
    
        /*
            Hash : AEIHWLT/cTUfXdYJ+oai6sZ4tXlc4QQcYTbI9If/Moc=
            Key : WdHhJ19dSBURBA25HZSpbCJ4KnNEEgwzqjgyTBqa3eg=
            IV : ludWXFqwWeLOkmhutxiwHw==
            Encrypted : D3JpubesPMgQTiXbaoxAIw==
            Decrypted : Hello World!
        */
    

    希望这能为其他人节省我所浪费的时间:)

    在经历了这么多失败的开始之后,它为我节省了时间。我想为@Aku组织一次游行!谢谢你(是的,因为我已经挣扎了几个小时)。谢谢!比使用RNCryptor更好