1.1 单向散列函数
单向散列函数(One-way hash function),也称之为消息摘要函数(Message Digest Function),哈希函数,它可以根据消息的内容计算出一个散列值;
输出的散列值,也被称为消息摘要(message digest)、指纹(fingerprint);
1.2 单向散列函数的特点
1.散列值的长度与消息的长度<mark>无关</mark>,无论消息是1bit、10M、100G,单向散列函数都会计算出<mark>固定长度</mark>的散列值,如下图:
单向散列函数2.计算速度快,能快速的计算出散列值;
3.消息不同,散列值也不同;
4.具备单向性:无法通过散列值反推出原始消息内容
单向性2.1 单向散列函数常见类型
·MD4:具有3轮16步,输出位长度为128位。
·MD5:具有4轮16步,输出位长128位。
·SHA-1:具有4个20阶的步长和160位的输出位长度。
·SHA-256:具有64轮单步,输出位长度为256位。
·SHA-384:实际上与SHA-512相同,除了输出被截断为383位。
·SHA-512:具有80个单步的轮数和512位的输出位长度。
2.1.1 MD4:
MD4(RFC 1320)是 MIT 的 Ronald L. Rivest 在 1990 年设计的,MD 是 Message Digest 的缩写。它适用在32位字长的处理器上用高速软件实现--它是基于 32 位操作数的位操作来实现的。它的安全性不像RSA那样基于数学假设,尽管 Den Boer、Bosselaers 和 Dobbertin 很快就用分析和差分成功的攻击了它3轮变换中的 2 轮,证明了它并不像期望的那样安全,但它的整个算法并没有真正被破解过,Rivest 也很快进行了改进。
2.1.2 MD5:
MD5(RFC 1321)是 Rivest 于1991年对MD4的改进版本。它对输入仍以512位分组,其输出是4个32位字的级联,与 MD4 相同。它较MD4所做的改进是:
- 加入了第四轮
- 每一步都有唯一的加法常数;
- 第二轮中的G函数从((X ∧ Y) ∨ (X ∧ Z) ∨ (Y ∧ Z)) 变为 ((X ∧ Z) ∨ (Y ∧ ~Z))以减小其对称性;
- 每一步都加入了前一步的结果,以加快"雪崩效应";
- 改变了第2轮和第3轮中访问输入子分组的顺序,减小了形式的相似程度;
- 近似优化了每轮的循环左移位移量,以期加快"雪崩效应",各轮的循环左移都不同。
尽管MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好。
使用终端查看字符串或者文件的MD5值:
md5 -s 字符串
md5 文件路径
//字符串
md5 -s 24324
MD5 ("24324") = fb2e636577105f243646d6f1e199f0ba
//文件
MD5 /Users/i/Desktop/2.pdf
MD5 (/Users/i/Desktop/2.pdf) = bd32d590689394cae6a3f234a33ca93c
iOS实现字符串转MD5:
#import "NSString+MD5.h"
@implementation NSString (MD5)
- (NSString *)MD5String{
//传入参数,转化成char
const char * str = [self UTF8String];
//开辟一个16字节(128位:md5加密出来就是128位/bit)的空间(一个字节=8字位=8个二进制数)
unsigned char md[CC_MD5_DIGEST_LENGTH];
/*
extern unsigned char * CC_MD5(const void *data, CC_LONG len, unsigned char *md)官方封装好的加密方法
把str字符串转换成了32位的16进制数列(这个过程不可逆转) 存储到了md这个空间中
*/
CC_MD5(str, (int)strlen(str), md);
//创建一个可变字符串收集结果
NSMutableString * ret = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH];
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
/**
X 表示以十六进制形式输入/输出
02 表示不足两位,前面补0输出;出过两位不影响
printf("%02X", 0x123); //打印出:123
printf("%02X", 0x1); //打印出:01
*/
[ret appendFormat:@"%02X",md[i]];
}
//返回一个长度为32的字符串
return ret;
}
@end
ios实现NSData转H5
#import "NSData+MD5.h"
#import <CommonCrypto/CommonDigest.h>
@implementation NSData (MD5)
-(NSData *)MD5Data{
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(self.bytes, (CC_LONG)self.length, result);
return [NSData dataWithBytes:result length:CC_MD5_DIGEST_LENGTH];
}
@end
2.1.3 SHA1-SHA224-SHA256-SHA384-SHA512:
- (NSString *) sha1String{
NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, (unsigned int)data.length, digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for(int i=0; i<CC_SHA1_DIGEST_LENGTH; i++) {
[output appendFormat:@"%02x", digest[i]];
}
return output;
}
-(NSString *)sha224String{
const char *cstr=[self cStringUsingEncoding:NSUTF8StringEncoding];
NSData*data=[NSData dataWithBytes:cstr length:self.length];
uint8_t digest[CC_SHA224_DIGEST_LENGTH];
CC_SHA224(data.bytes, (unsigned int)data.length, digest);
NSMutableString*output=[NSMutableString stringWithCapacity:CC_SHA224_DIGEST_LENGTH*2];
for(int i=0; i < CC_SHA224_DIGEST_LENGTH; i++){
[output appendFormat:@"%02x", digest[i]];
}
return output;
}
- (NSString *)sha256String{
const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:self.length];
uint8_t digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(data.bytes,(CC_LONG)data.length, digest);
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++){
[output appendFormat:@"%02x", digest[i]];
}
return output;
}
- (NSString *)sha384String
{
const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:self.length];
uint8_t digest[CC_SHA384_DIGEST_LENGTH];
CC_SHA384(data.bytes,(CC_LONG) data.length, digest);
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA384_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA384_DIGEST_LENGTH; i++){
[output appendFormat:@"%02x", digest[i]];
}
return output;
}
- (NSString *)sha512String
{
const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:self.length];
uint8_t digest[CC_SHA512_DIGEST_LENGTH];
CC_SHA512(data.bytes, (CC_LONG)data.length, digest);
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA512_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA512_DIGEST_LENGTH; i++){
[output appendFormat:@"%02x", digest[i]];
}
return output;
}
3 单向散列函数的应用
3.1 某些大型软件的官网会公布软件的散列值,防止软件被篡改
软件生成散列值防伪例如: vnc官网下载链接,会有软件的SHA256生成的散列值:
3.2 服务器存放的用户的密码不是明文的,而是对应密码的散列值,比如SHA2(密码)
用户密码服务端存放示例服务器中存放的不是用户密码的明文,如果存放的是密码明文,风险太高,一般存放的是对应用户名的密码的散列值,在用户登录的时候,通过散列值与数据库中的散列值对比,如果相同则登录成功.
网友评论