加密iOS和Decrypt Node.js AES

我已经搜索了一个解决方案的高低,并在Node.js服务器和Objective-C客户端上加密,反之亦然,使用AES(或其他适当的话)

我对密码学比较陌生,并且理解为什么我的加密文本在每种语言中都不同,这是我所不知道的。

这是我到目前为止:

Node.js加密方法使用此CryptoJS库 – 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加密方法使用AESCrypt库

 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 

多年来我一直在摸不着头脑,尝试了我能想到的一切。 如果需要,可以从库中显示基础加密方法。 有一个SHAR256哈希应用于AESCrypt库中的键,但我删除了它,并认为有一些不匹配的字符串编码。

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

  2. CryptoJS库使用什么样的加密方式? 它的文档没有说。 鉴于它要求IV,它可能是CBC,但你必须看看来源才能确定。 AESCrypt的文档声称使用CBC模式,但您不会在任何地方给它IV。 这必须意味着它在某个地方生成它,或者总是使用固定的。 (这一半击败了CBC模式的目的,但这是另一个故事)。 所以你需要弄清楚实际上是什么。

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

我在这里发布这个,因为必然会有其他人尝试互操作Node.js和iOS。 每个人似乎都挂断了所有东西都在正确的结构,缓冲区,字符串等。我知道我做了。 因此,这是一个逐步创建密钥,创建iv,加密,解密和放置在base64中以便于传输的过程:

JavaScript(使用CryptoJS模块的Node.js)

  // 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使用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); 

输出应该是相同的

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

希望这能节省别人我浪费的时间:)