iOS開(kāi)發(fā)單向散列函數(shù):MD5及SHA1-SHA224-SHA256-SHA384-SHA512

1.1 單向散列函數(shù)

單向散列函數(shù)(One-way hash function),也稱之為消息摘要函數(shù)(Message Digest Function),哈希函數(shù),它可以根據(jù)消息的內(nèi)容計(jì)算出一個(gè)散列值;
輸出的散列值,也被稱為消息摘要(message digest)、指紋(fingerprint);

1.2 單向散列函數(shù)的特點(diǎn)

1.散列值的長(zhǎng)度與消息的長(zhǎng)度<mark>無(wú)關(guān)</mark>,無(wú)論消息是1bit、10M、100G,單向散列函數(shù)都會(huì)計(jì)算出<mark>固定長(zhǎng)度</mark>的散列值,如下圖:

單向散列函數(shù)

2.計(jì)算速度快,能快速的計(jì)算出散列值;

3.消息不同,散列值也不同;

4.具備單向性:無(wú)法通過(guò)散列值反推出原始消息內(nèi)容

單向性

2.1 單向散列函數(shù)常見(jiàn)類(lèi)型

·MD4:具有3輪16步,輸出位長(zhǎng)度為128位。
·MD5:具有4輪16步,輸出位長(zhǎng)128位。
·SHA-1:具有4個(gè)20階的步長(zhǎng)和160位的輸出位長(zhǎng)度。
·SHA-256:具有64輪單步,輸出位長(zhǎng)度為256位。
·SHA-384:實(shí)際上與SHA-512相同,除了輸出被截?cái)酁?83位。
·SHA-512:具有80個(gè)單步的輪數(shù)和512位的輸出位長(zhǎng)度。


2.1.1 MD4:

MD4(RFC 1320)是 MIT 的 Ronald L. Rivest 在 1990 年設(shè)計(jì)的,MD 是 Message Digest 的縮寫(xiě)。它適用在32位字長(zhǎng)的處理器上用高速軟件實(shí)現(xiàn)--它是基于 32 位操作數(shù)的位操作來(lái)實(shí)現(xiàn)的。它的安全性不像RSA那樣基于數(shù)學(xué)假設(shè),盡管 Den Boer、Bosselaers 和 Dobbertin 很快就用分析和差分成功的攻擊了它3輪變換中的 2 輪,證明了它并不像期望的那樣安全,但它的整個(gè)算法并沒(méi)有真正被破解過(guò),Rivest 也很快進(jìn)行了改進(jìn)。


2.1.2 MD5:

MD5(RFC 1321)是 Rivest 于1991年對(duì)MD4的改進(jìn)版本。它對(duì)輸入仍以512位分組,其輸出是4個(gè)32位字的級(jí)聯(lián),與 MD4 相同。它較MD4所做的改進(jìn)是:

  1. 加入了第四輪
  2. 每一步都有唯一的加法常數(shù);
  3. 第二輪中的G函數(shù)從((X ∧ Y) ∨ (X ∧ Z) ∨ (Y ∧ Z)) 變?yōu)?((X ∧ Z) ∨ (Y ∧ ~Z))以減小其對(duì)稱性;
  4. 每一步都加入了前一步的結(jié)果,以加快"雪崩效應(yīng)";
  5. 改變了第2輪和第3輪中訪問(wèn)輸入子分組的順序,減小了形式的相似程度;
  6. 近似優(yōu)化了每輪的循環(huán)左移位移量,以期加快"雪崩效應(yīng)",各輪的循環(huán)左移都不同。
    盡管MD5比MD4來(lái)得復(fù)雜,并且速度較之要慢一點(diǎn),但更安全,在抗分析和抗差分方面表現(xiàn)更好。

使用終端查看字符串或者文件的MD5值:
md5 -s 字符串
md5 文件路徑

//字符串
md5 -s 24324
MD5 ("24324") = fb2e636577105f243646d6f1e199f0ba

//文件
MD5 /Users/i/Desktop/2.pdf
MD5 (/Users/i/Desktop/2.pdf) = bd32d590689394cae6a3f234a33ca93c

iOS實(shí)現(xiàn)字符串轉(zhuǎn)MD5:

#import "NSString+MD5.h"
@implementation NSString (MD5)

- (NSString *)MD5String{
    //傳入?yún)?shù),轉(zhuǎn)化成char
    const char * str = [self UTF8String];
    //開(kāi)辟一個(gè)16字節(jié)(128位:md5加密出來(lái)就是128位/bit)的空間(一個(gè)字節(jié)=8字位=8個(gè)二進(jìn)制數(shù))
    unsigned char md[CC_MD5_DIGEST_LENGTH];
    /*
     extern unsigned char * CC_MD5(const void *data, CC_LONG len, unsigned char *md)官方封裝好的加密方法
     把str字符串轉(zhuǎn)換成了32位的16進(jìn)制數(shù)列(這個(gè)過(guò)程不可逆轉(zhuǎn)) 存儲(chǔ)到了md這個(gè)空間中
     */
    CC_MD5(str, (int)strlen(str), md);
    //創(chuàng)建一個(gè)可變字符串收集結(jié)果
    NSMutableString * ret = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH];
    for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        /**
         X 表示以十六進(jìn)制形式輸入/輸出
         02 表示不足兩位,前面補(bǔ)0輸出;出過(guò)兩位不影響
         printf("%02X", 0x123); //打印出:123
         printf("%02X", 0x1); //打印出:01
         */
        [ret appendFormat:@"%02X",md[i]];
    }
    //返回一個(gè)長(zhǎng)度為32的字符串
    return ret;
}
@end

ios實(shí)現(xiàn)NSData轉(zhuǎn)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 單向散列函數(shù)的應(yīng)用

3.1 某些大型軟件的官網(wǎng)會(huì)公布軟件的散列值,防止軟件被篡改

軟件生成散列值防偽

例如: vnc官網(wǎng)下載鏈接,會(huì)有軟件的SHA256生成的散列值:

vnc官網(wǎng)軟件散列值示例

3.2 服務(wù)器存放的用戶的密碼不是明文的,而是對(duì)應(yīng)密碼的散列值,比如SHA2(密碼)

用戶密碼服務(wù)端存放示例

服務(wù)器中存放的不是用戶密碼的明文,如果存放的是密碼明文,風(fēng)險(xiǎn)太高,一般存放的是對(duì)應(yīng)用戶名的密碼的散列值,在用戶登錄的時(shí)候,通過(guò)散列值與數(shù)據(jù)庫(kù)中的散列值對(duì)比,如果相同則登錄成功.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容