9.加密
2021-11-17 本文已影响0人
LucXion
AES 高级加密算法
- 对称加密
- 提供三种秘钥长度,128位,192位,256位,除非有特殊需要,一般推荐使用128位,在安全和性能之间有很好的平衡
- AES 只是一个接收固定长度秘钥和16字节大小的分组,然后生成另外一个16字节大小的分组的数学函数。
- AES 没有提供认证机制来处理对密文的意外或故意损坏。但可以为AES 添加差错校验。
如何将密码转化为秘钥,PBKDF2:生成一个很大的随机数(盐),标准推荐最少达到64位,盐和密码将会搭配使用来阻止相同密码生成相同秘钥。循环执行PBKDF2若干次,最终的数据就是你的秘钥。这个过程称为扩展,要解密数据,只需要保留盐和循环次数。
#import <CommonCrypto/CommonKeyDerivation.h>
#import "RNCryptor/RNCryptor.h"
NSData *salt = [self randomDataOfLenght:8];
- (NSData *)randomDataOfLenght:(size_t)length {
NSMutableData *data = [NSMutableData dataWithLength:length];
int result = SecRandomCopyBytes(kSecRandomDefault, length, data.mutableBytes);
NSAssert(result == 0, @"Unable to generate random bytes:%d",errno);
return data;
}
/*
struct _RNCryptorKeyDerivationSettings
{
size_t keySize;
size_t saltSize;
uint32_t PBKDFAlgorithm;(CCPBKDFAlgorithm,SHA256通常会是倾向的选择,它是特定大小的SHA-2)
uint32_t PRF;(CCPseudoRandomAlgorithm,伪随机函数,用来生成很长的统计上随机的一系列数)
uint rounds;
BOOL hasV2Password; // See Issue #77. V2 incorrectly handled multi-byte characters.
} RNCryptorKeyDerivationSettings;
*/
// 生成秘钥,盐和循环次数必须和密文存储到一起
+ (NSData *)keyForPassword:(NSString*)password salt:(NSData *)salt settings:(RNCryptorKeyDerivationSettings)keySettings {
NSMutableData *derivedKey = [NSMutableData dataWithLength:keySettings.keySize];
size_t passwordLength = [password lengthOfBytesUsingEncoding:kCFStringEncodingUTF8];
int result = CCKeyDerivationPBKDF(keySettings.PBKDFAlgorithm, password.UTF8String, password.length, salt.bytes, salt.length, keySettings.PRF, keySettings.rounds, derivedKey.mutableBytes, derivedKey.length);
NSAssert(result == 0, @"Unable to generate random bytes:%d",errno);
return derivedKey;
}
AES 模式和填充
AES一次处理128位的输入数据,但大多数需要加密的数据都不是16字节,所以需要选择合适的模式。模式是一种算法,用于将数据分组串起来,使得任何数据都可以加密。
- EBC:最简单的模式,电子密码本,适用于加密大量随机分组的情况,一般不予考虑,如果两个普通文本分组一样,生成的密文就会完全相同,不够安全。
- CBC:密码分组链模式,每个分组的密文都会同下一个未加密的普通文本分组进行异或运算。缺点是加密过程无法并行,并且普通文本必须是分组大小(16字节)的整数倍(可以通过填充来实现)。
填充:iOS唯一支持的填充方式,PKCS #7(kCCOptionPKCS7Padding),会在源数据后面追加n个值为n的字节,如果数据分组刚好匹配,那么会追加整个分组的0x10,这意味着密文可能比普通文本多出一个分组。有一种称作密文盗用(ciphertext stealing)的方法跟CBC兼容,但iOS只支持CBC。
如果面临无法使用填充的情况,推荐使用密码反馈(Cipher Feedback, CFB)、输出反馈(Output Feedback OFB)
如果需要避免初始化向量的开销,计数器(Count,CTR)模式会比较有用
XTS是针对随机访问数据的一个特定模式,尤其是在加密的文件系统上
加密和压缩
加密数据前先压缩一下数据,可以让数据变得更小。记住必须在加密前压缩,不能加密压缩过的数据,如果你能把加密过的数据压缩的更小,那就意味着密文中有重复的片段,着又说明加密的算法不够强大。大多数情况下,加密后的数据压缩后比原始普通文本数据要大。