加解密iOS/Node.js安全查询
Encrypt and Decrypt iOS/Node.js Security Inquiry
我目前在两个平台上都使用 AES128,我的代码来自 answer
注意:我稍微更改了代码以偏离使用 IV,因为我认为它对我的应用程序来说太过分了。
node.js:
var CryptoJS = require("crypto-js");
var crypto = require('crypto');
var password = "1234567890123456";
var salt = "gettingsaltyfoo!";
var hash = CryptoJS.SHA256(salt);
var key = CryptoJS.PBKDF2(password, hash, { keySize: 256/32, iterations: 1000 });
var algorithm = 'aes128';
console.log(key.toString(CryptoJS.enc.Base64));
function encrypt(text){
var cipher = crypto.createCipher(algorithm,key.toString(CryptoJS.enc.Base64));
var crypted = cipher.update(text,'utf8','hex');
crypted += cipher.final('hex');
return crypted;
}
function decrypt(text){
var decipher = crypto.createDecipher(algorithm,key.toString(CryptoJS.enc.Base64));
var dec = decipher.update(text,'hex','utf8');
dec += decipher.final('utf8');
return dec;
}
iOS:
#import <CommonCrypto/CommonCrypto.h>
NSString* password = @"1234567890123456";
NSString* salt = @"gettingsaltyfoo!";
-(NSString *)decrypt:(NSString*)encrypted64{
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]);
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,
NULL,
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);
return outputString;
}
-(NSString *)encrypt:(NSString *)toEncrypt{
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);
NSData* message = [toEncrypt dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData* encrypted = [NSMutableData dataWithLength:message.length + kCCBlockSizeAES128];
size_t bytesEncrypted = 0;
CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
key.bytes,
key.length,
NULL,
message.bytes, message.length,
encrypted.mutableBytes, encrypted.length, &bytesEncrypted);
NSString* encrypted64 = [[NSMutableData dataWithBytes:encrypted.mutableBytes length:bytesEncrypted] base64EncodedStringWithOptions:0];
NSLog(@"Encrypted : %@",encrypted64);
return encrypted64;
}
我的问题: 如果我像这样硬编码盐可以吗?我正在尝试加密和解密密码(var 密码和 NSString 密码可能会被硬编码为某些内容)。我在网上读到我需要在我的数据库中保存我的盐和我的密码。如果我硬编码我的 salt 不好,我如何将它从 iOS 发送到 node.js 并与 salt 保持一致?我的 iOS 请求应该像这样吗?
{
key:"someKeyGeneratedOnTheSpotWithRandomSalt",
password:"somePasswordGeneratedFromKey"
}
并在我的后端通过从数据库中提取这些字段来检查密码?
{
key:"someKeyGeneratedWhenTheUserFirstSignedUp",
password:"somePasswordGeneratedFromTheOrginalKeyWhenUserFirstSignedUp"
}
然后使用两种场景生成的密钥和密码解密这两种密码?
或者有一个硬编码的盐是否可以,比如用户名,这样每个用户的密钥总是相同的?
基本上我对我的加密模型是否有正确的想法感到困惑。
感谢您的帮助。
通常使用随机盐并将其添加到加密数据之前。将 PBKDF2 迭代计数和版本号一起添加到前面也是很常见的,这有助于面向未来。最后,跳过 iv 会降低对第一个块的保护,您可以考虑使用身份验证哈希。
这类似于 RNCryptor 所做的。有关加密邮件的详细信息,请参阅 RNCryptor-Spec-v3.md。
备注:
我不明白 CC_SHA256 的盐,这不是必需的。
NSData* outputMessage = [NSMutableData dataWithBytes:decrypted.mutableBytes
length:bytesDecrypted];
不需要,设置decrypted
的长度即可
decrypted.length = bytesDecrypted;
并使用 decrypted
代替 outputMessage
.
我目前在两个平台上都使用 AES128,我的代码来自 answer
注意:我稍微更改了代码以偏离使用 IV,因为我认为它对我的应用程序来说太过分了。
node.js:
var CryptoJS = require("crypto-js");
var crypto = require('crypto');
var password = "1234567890123456";
var salt = "gettingsaltyfoo!";
var hash = CryptoJS.SHA256(salt);
var key = CryptoJS.PBKDF2(password, hash, { keySize: 256/32, iterations: 1000 });
var algorithm = 'aes128';
console.log(key.toString(CryptoJS.enc.Base64));
function encrypt(text){
var cipher = crypto.createCipher(algorithm,key.toString(CryptoJS.enc.Base64));
var crypted = cipher.update(text,'utf8','hex');
crypted += cipher.final('hex');
return crypted;
}
function decrypt(text){
var decipher = crypto.createDecipher(algorithm,key.toString(CryptoJS.enc.Base64));
var dec = decipher.update(text,'hex','utf8');
dec += decipher.final('utf8');
return dec;
}
iOS:
#import <CommonCrypto/CommonCrypto.h>
NSString* password = @"1234567890123456";
NSString* salt = @"gettingsaltyfoo!";
-(NSString *)decrypt:(NSString*)encrypted64{
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]);
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,
NULL,
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);
return outputString;
}
-(NSString *)encrypt:(NSString *)toEncrypt{
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);
NSData* message = [toEncrypt dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData* encrypted = [NSMutableData dataWithLength:message.length + kCCBlockSizeAES128];
size_t bytesEncrypted = 0;
CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
key.bytes,
key.length,
NULL,
message.bytes, message.length,
encrypted.mutableBytes, encrypted.length, &bytesEncrypted);
NSString* encrypted64 = [[NSMutableData dataWithBytes:encrypted.mutableBytes length:bytesEncrypted] base64EncodedStringWithOptions:0];
NSLog(@"Encrypted : %@",encrypted64);
return encrypted64;
}
我的问题: 如果我像这样硬编码盐可以吗?我正在尝试加密和解密密码(var 密码和 NSString 密码可能会被硬编码为某些内容)。我在网上读到我需要在我的数据库中保存我的盐和我的密码。如果我硬编码我的 salt 不好,我如何将它从 iOS 发送到 node.js 并与 salt 保持一致?我的 iOS 请求应该像这样吗?
{
key:"someKeyGeneratedOnTheSpotWithRandomSalt",
password:"somePasswordGeneratedFromKey"
}
并在我的后端通过从数据库中提取这些字段来检查密码?
{
key:"someKeyGeneratedWhenTheUserFirstSignedUp",
password:"somePasswordGeneratedFromTheOrginalKeyWhenUserFirstSignedUp"
}
然后使用两种场景生成的密钥和密码解密这两种密码?
或者有一个硬编码的盐是否可以,比如用户名,这样每个用户的密钥总是相同的?
基本上我对我的加密模型是否有正确的想法感到困惑。
感谢您的帮助。
通常使用随机盐并将其添加到加密数据之前。将 PBKDF2 迭代计数和版本号一起添加到前面也是很常见的,这有助于面向未来。最后,跳过 iv 会降低对第一个块的保护,您可以考虑使用身份验证哈希。
这类似于 RNCryptor 所做的。有关加密邮件的详细信息,请参阅 RNCryptor-Spec-v3.md。
备注:
我不明白 CC_SHA256 的盐,这不是必需的。
NSData* outputMessage = [NSMutableData dataWithBytes:decrypted.mutableBytes
length:bytesDecrypted];
不需要,设置decrypted
的长度即可
decrypted.length = bytesDecrypted;
并使用 decrypted
代替 outputMessage
.