MD5加密
MD5加密的特点:
- 不可逆运算
- 对不同的数据加密的结果是定长的32位字符(不管文件多大都一样)
- 对相同的数据加密,得到的结果是一样的(也就是复制)。
- 抗修改性 : 信息“指纹”,对原数据进行任何改动,哪怕只修改一个字节,所得到的 MD5 值都有很大区别.
- 弱抗碰撞 : 已知原数据和其 MD5 值,想找到一个具有相同 MD5 值的数据(即伪造数据)是非常困难的.
- 强抗碰撞: 想找到两个不同数据,使他们具有相同的 MD5 值,是非常困难的
MD5 应用:
一致性验证:MD5将整个文件当做一个大文本信息,通过不可逆的字符串变换算法,产生一个唯一的MD5信息摘要,就像每个人都有自己独一无二的指纹,MD5对任何文件产生一个独一无二的数字指纹。
注意点:加盐
“盐”就是一串比较复杂的字符串。加盐的目的是加强加密的复杂度,这么破解起来就更加麻烦,当然这个“盐”越长越复杂,加密后破解起来就越麻烦。
算法实现:
// 0、引入框架
#import <CommonCrypto/CommonDigest.h>
- (NSString *)md5_32:(NSString *)text upperCase:(BOOL)uppuerCase {
// 1、转化为UTF8字符串
const char *chars = [text UTF8String];
// 2、设置一个接收字符数组
unsigned char digest[CC_MD5_DIGEST_LENGTH];
// 3、把str字符串转换成为32位的16进制数列,存到result中
CC_MD5(chars, (int)strlen(chars), digest);
NSMutableString *result = [NSMutableString stringWithCapacity:1];
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
// 4、将16字节的16进制转成32字节的16进制字符串
[result appendFormat:@"%02x", digest[i]];
}
if (uppuerCase) {
return [result uppercaseString];
} else {
return [result lowercaseString];
}
}
- (NSString *)md5_16:(NSString *)text upperCase:(BOOL)uppuerCase {
NSString *md5_32 = [self md5_32:text upperCase:uppuerCase];
// 从32位中提取9~24位
return [[md5_32 substringToIndex:24] substringFromIndex:8];
}
对称加密
简介:
对称加密算法又称传统加密算法。
加密和解密使用同一个密钥。
加密解密过程:
明文->密钥加密->密文,密文->密钥解密->明文。
优缺点:
- 算法公开,计算量小,加密速度快,加密效率高
- 双方使用相同的钥匙,安全性得不到保证
注意事项:
- 密钥的保密工作非常重要
- 密钥要求定期更换
经典加密算法:
- DES(Data Encryption Standard):数据加密标准(现在用的比较少,因为它的加密强度不够,能够暴力破解)
- 3DES:原理和DES几乎是一样的,只是使用3个密钥,对相同的数据执行三次加密,增强加密强度。(缺点:要维护3个密钥,大大增加了维护成本)
- AES(Advanced Encryption Standard):高级加密标准,目前美国国家安全局使用的,苹果的钥匙串访问采用的就AES加密。是现在公认的最安全的加密方式,是对称密钥加密中最流行的算法。
AES加密实现
// 导入框架
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>
// 对NSData加密
- (NSData *)AESEncryptWithData:(NSData *)data Key:(NSString *)key
{
char keyPtr[kCCKeySizeAES128 + 1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [data length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
char ivPtr[kCCBlockSizeAES128 + 1];
memset(ivPtr, 0, sizeof(ivPtr));
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
keyPtr,
kCCBlockSizeAES128,
ivPtr,
[data bytes],
dataLength,
buffer,
bufferSize,
&numBytesEncrypted);
if(cryptStatus == kCCSuccess)
{
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
// 对NSData解密
- (NSData *)AESDecryptWithData:(NSData *)data andKey:(NSString *)key
{
char keyPtr[kCCKeySizeAES128 + 1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [data length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeAES128, NULL, [data bytes], dataLength, buffer, bufferSize, &numBytesDecrypted);
if(cryptStatus == kCCSuccess)
{
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free(buffer);
return nil;
}
// 对NSString加密(实际上是先把字符串转化为NSData进行加密,再把加密后的NSData转化为字符串)
- (NSString *)AESEncryptWithString:(NSString *)string andKey:(NSString *)key
{
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
//对数据进行加密
NSData *result = [self AESEncryptWithData:data Key:key];
NSLog(@"%@", result);
NSData *endData = [result base64EncodedDataWithOptions:NSDataBase64Encoding64CharacterLineLength];
return [[NSString alloc] initWithData:endData encoding:NSUTF8StringEncoding];
}
// 对NSString解密(实际上是先把字符串转化为NSData进行解密,再把解密后的NSData转化为字符串)
- (NSString *)AESDecryptWithString:(NSString *)string andKey:(NSString *)key
{
NSData *result = [self AESDecryptWithData:[[NSData alloc] initWithBase64EncodedString:string options:NSDataBase64DecodingIgnoreUnknownCharacters] andKey:key];
if(result && result.length > 0)
{
NSString *str = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
return str;
}
return nil;
}
函数解析:
CCCryptorStatus CCCrypt(
CCOperation op, /* 用来代表加密或者解密,kCCEncrypt = 加密,kCCDecrypt = 解密 */
CCAlgorithm alg, /* 用来代表加密算法,有kCCAlgorithmAES128... */
CCOptions options, /* 填充模式,iOS中只提供了kCCOptionPKCS7Padding和kCCOptionECBMode两种,这个在于后台和安卓交互时要注意一点。 */
const void *key, /* 密钥长度,一般使用char keyPtr[kCCKeySizeAES256+1] */
size_t keyLength, /* 加密信息的比特数 */
const void *iv, /* 偏移向量,CBC模式下需要,不传默认16位0 */
const void *dataIn, /* 加解密的数据data.bytes */
size_t dataInLength, /* 加解密的数据的大小 */
void *dataOut, /* 用来输出加密结果 */
size_t dataOutAvailable,/* 输出加密结果的大小 */
size_t *dataOutMoved) /* 输出加密结果的大小 */
API_AVAILABLE(macos(10.4), ios(2.0));/* 缓冲区空间 */
非对称加密RSA
简介:
- 对称加密算法又称现代加密算法。
- 非对称加密是计算机通信安全的基石,保证了加密数据不会被破解。
- 非对称加密算法需要两个密钥:公开密钥(publickey) 和私有密(privatekey)
- 公开密钥和私有密钥是一对
- 如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密。
- 如果用私有密钥对数据进行加密,只有用对应的公开密钥才能解密。
特点:
- 算法强度复杂,安全性依赖于算法与密钥。
- 加密解密速度慢。
与对称加密算法的对比:
- 对称加密只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。
- 非对称加密有两种密钥,其中一个是公开的。
RSA应用场景:
由于RSA算法的加密解密速度要比对称算法速度慢很多,在实际应用中,通常采取数据本身的加密和解密使用对称加密算法(AES)。
用RSA算法加密并传输对称算法所需的密钥。
RSA实现
RSA的实现主要是使用Security.framework框架的SecKeyEncrypt和SecKeyDecrypt函数。
签名验签
SHA1+RSA签名验签实现
主要使用到Security.framework框架的SecKeyRawSign函数与SecKeyRawVerify函数。
加密方案
通讯加密方案:非对称加密+对称加密,例如RSA+AES、sm2+sm4。
每次通信客户端随机生成AES秘钥,用AES秘钥加密报文,用RSA共钥加密AES秘钥。将加密后的报文y以及一些必要信息包在头部发送到服务器。后台首先用RSA秘钥解密得到AES秘钥,再用AES秘钥解密报文。
虽然RSA加密算法的安全性很高,但是RSA加解密的速度非常慢而且RSA不能加密过长的报文,这就限制了单独使用RSA加密传输的报文。AES算法的安全性不及RSA但是对加密报文的长度是没有限制的而且加解密运算速度很快。
键盘加密
用户输入的密文采取一次一秘的方案。在每次密码输入键盘谈起之前向后台请求随机因子,用户密码的加密和随机因子以某种方式绑在一起。这就保证了:
- 同样的密码用户每次传输的秘文都是不一样的,被截取也是没有关系的。
- 即使知道了客户端的加密算法和解密秘钥没有后台的随机因子,密码也是不会被破解。