iOS 逆向開發(fā)09:HASH算法

iOS 逆向開發(fā) 文章匯總

目錄


一、HASH概述

Hash,一般翻譯做“散列”,也有直接音譯為“哈希”的,就是把任意長(zhǎng)度的輸入通過散列算法變換成固定長(zhǎng)度的輸出,該輸出就是散列值。這種轉(zhuǎn)換是一種壓縮映射,也就是,散列值的空間通常遠(yuǎn)小于輸入的空間,不同的輸入可能會(huì)散列成相同的輸出(Hash碰撞),所以不可能從散列值來(lái)確定唯一的輸入值。簡(jiǎn)單的說就是一種將任意長(zhǎng)度的消息壓縮到某一固定長(zhǎng)度的消息摘要的函數(shù)。

1.1 常見的Hash算法

  • MD5
  • SHA1、SHA265、SHA512


1.2 Hash的特點(diǎn)

  • 算法是公開的
  • 對(duì)相同數(shù)據(jù)運(yùn)算,得到的結(jié)果是一樣的
  • 對(duì)不同數(shù)據(jù)運(yùn)算,如MD5得到的結(jié)果默認(rèn)是128位(2^128),32個(gè)字符(16進(jìn)制標(biāo)識(shí):16^32)。
  • Hash結(jié)果無(wú)法逆運(yùn)算,因此Hash不能作為加密算法
  • 信息摘要,信息“指紋”,是用來(lái)做數(shù)據(jù)識(shí)別的。


1.3 Hash用途

  • 用戶密碼的加密
  • 搜索引擎:關(guān)鍵詞Hash相加
  • 版權(quán):網(wǎng)站保存原文件的Hash值,供用戶下載的文件加了鹽,Hash不一樣。網(wǎng)盤保存的文件通過Hash值去重(同時(shí)也要防止Hash碰撞)。文件修改文件名和文件后綴不會(huì)改變Hash值(壓縮/Base64可以改變Hash值)。
  • 數(shù)字簽名


二、用戶密碼加密

通過運(yùn)用HASH算法,給用戶的密碼進(jìn)行加密。

用戶密碼加密方式

  • 直接使用MD5
  • MD5加鹽
  • HMAC加密方案
  • 添點(diǎn)東西

思考:直接使用RSA加密傳輸用戶密碼的優(yōu)缺點(diǎn)?

  • 優(yōu)點(diǎn):在網(wǎng)絡(luò)傳輸泄露的風(fēng)險(xiǎn)低
  • 缺點(diǎn):服務(wù)端收到加密后的密碼解密明文保存到數(shù)據(jù)庫(kù)中非常不安全。
    • 如果服務(wù)端不解密保存到數(shù)據(jù)庫(kù)的就是密文,那么黑客直接抓包拿到請(qǐng)求中的密文也能繞過RSA解密。
    • RSA中的公鑰和私鑰對(duì)程序員是公開的,程序員的泄露也是很大的風(fēng)險(xiǎn)。


HASH加密用戶密碼

HASH加密用戶密碼后服務(wù)器中就不會(huì)出現(xiàn)明文密碼了

#import "NSString+Hash.h" --->文末

NSString *pwd = @"123456";
pwd = pwd.md5String;
NSLog(@"現(xiàn)在的密碼是:%@",pwd);//e10adc3949ba59abbe56e057f20f883e

存在的問題:通過查詢HASH值可以查詢出很多明文。查詢網(wǎng)址


改進(jìn):加鹽

/* 加鹽 */
static NSString *salt = @"LKSJDFLKJ&^&@@";

NSString *pwd = @"123456";
pwd = [pwd stringByAppendingString:salt].md5String;
NSLog(@"現(xiàn)在的密碼是:%@",pwd);//2359298f49af5695a4b846e95bdea467

存在的問題:固定鹽對(duì)開發(fā)者的依賴很大


HAMC:服務(wù)器發(fā)鹽

NSString *pwd = @"123456";
//HMAC 加密方式!! KEY 由服務(wù)器提供。 給定hmac一個(gè)Key,對(duì)明文進(jìn)行兩次散列
//一個(gè)賬號(hào),一個(gè)KEY!!
pwd = [pwd hmacMD5StringWithKey:@"differ"];

存在的問題:可以直接使用Hash值進(jìn)行登錄


HAMC+時(shí)間戳


三、數(shù)字簽名

為什么用簽名這個(gè)詞.因?yàn)槔贤庀矚g用支票,支票上面的簽名能夠證明這玩意是你的.那么數(shù)字簽名顧名思義,就是用于鑒別數(shù)字信息的方法

  1. 為了防止傳輸中的數(shù)據(jù)被篡改需要將數(shù)據(jù)數(shù)據(jù)的Hash值一起傳遞給客戶端
  2. 為了防止數(shù)據(jù)數(shù)據(jù)的Hash值同時(shí)被篡改,數(shù)據(jù)的Hash值通過RSA再加密一次


四、總結(jié)

  • RSA終端代碼、RSA代碼演示。
  • RSA的特點(diǎn)
    • RSA的安全系數(shù)非常高(因?yàn)檎麄€(gè)業(yè)務(wù)邏輯非常安全)
    • 加密效率非常低(不能做大數(shù)據(jù)加密)
    • 用來(lái)加密關(guān)鍵數(shù)據(jù)!(對(duì)稱加密的Key,數(shù)字簽名中的Hash值)
  • HASH
    • 不可逆運(yùn)算
    • 相同的數(shù)據(jù)結(jié)果相同
    • 不同的數(shù)據(jù)長(zhǎng)度相同
    • 一般用于做數(shù)據(jù)的識(shí)別(密碼、版權(quán)、百度云數(shù)據(jù)識(shí)別)
  • 密碼加密
    • HMAC (比較好的方案)
    • HASH+時(shí)間戳。這樣的方式,每次加密結(jié)果不一樣(受時(shí)間的影響比較大)
  • 數(shù)字簽名(重點(diǎn)! ! )
    • 算法: RSA + HASH
    • 目的:驗(yàn)證數(shù)據(jù)的完整性,不被篡改!
    • 邏輯:1.將原始數(shù)據(jù)進(jìn)行HASH;2.使用RSA加密HASH值(這部分?jǐn)?shù)據(jù)就是原始數(shù)據(jù)的簽名信息)3.將原始數(shù)據(jù)+數(shù)字簽名 一起打包發(fā)送











NSString+Hash.h

#import <Foundation/Foundation.h>

@interface NSString (Hash)
    
#pragma mark - 散列函數(shù)
    /**
     *  計(jì)算MD5散列結(jié)果
     *
     *  終端測(cè)試命令:
     *  @code
     *  md5 -s "string"
     *  @endcode
     *
     *  <p>提示:隨著 MD5 碰撞生成器的出現(xiàn),MD5 算法不應(yīng)被用于任何軟件完整性檢查或代碼簽名的用途。<p>
     *
     *  @return 32個(gè)字符的MD5散列字符串
     */
- (NSString *)md5String;
    
    /**
     *  計(jì)算SHA1散列結(jié)果
     *
     *  終端測(cè)試命令:
     *  @code
     *  echo -n "string" | openssl sha1
     *  @endcode
     *
     *  @return 40個(gè)字符的SHA1散列字符串
     */
- (NSString *)sha1String;
    
    /**
     *  計(jì)算SHA256散列結(jié)果
     *
     *  終端測(cè)試命令:
     *  @code
     *  echo -n "string" | openssl sha256
     *  @endcode
     *
     *  @return 64個(gè)字符的SHA256散列字符串
     */
- (NSString *)sha256String;
    
    /**
     *  計(jì)算SHA 512散列結(jié)果
     *
     *  終端測(cè)試命令:
     *  @code
     *  echo -n "string" | openssl sha512
     *  @endcode
     *
     *  @return 128個(gè)字符的SHA 512散列字符串
     */
- (NSString *)sha512String;
    
#pragma mark - HMAC 散列函數(shù)
    /**
     *  計(jì)算HMAC MD5散列結(jié)果
     *
     *  終端測(cè)試命令:
     *  @code
     *  echo -n "string" | openssl dgst -md5 -hmac "key"
     *  @endcode
     *
     *  @return 32個(gè)字符的HMAC MD5散列字符串
     */
- (NSString *)hmacMD5StringWithKey:(NSString *)key;
    
    /**
     *  計(jì)算HMAC SHA1散列結(jié)果
     *
     *  終端測(cè)試命令:
     *  @code
     *  echo -n "string" | openssl sha1 -hmac "key"
     *  @endcode
     *
     *  @return 40個(gè)字符的HMAC SHA1散列字符串
     */
- (NSString *)hmacSHA1StringWithKey:(NSString *)key;
    
    /**
     *  計(jì)算HMAC SHA256散列結(jié)果
     *
     *  終端測(cè)試命令:
     *  @code
     *  echo -n "string" | openssl sha256 -hmac "key"
     *  @endcode
     *
     *  @return 64個(gè)字符的HMAC SHA256散列字符串
     */
- (NSString *)hmacSHA256StringWithKey:(NSString *)key;
    
    /**
     *  計(jì)算HMAC SHA512散列結(jié)果
     *
     *  終端測(cè)試命令:
     *  @code
     *  echo -n "string" | openssl sha512 -hmac "key"
     *  @endcode
     *
     *  @return 128個(gè)字符的HMAC SHA512散列字符串
     */
- (NSString *)hmacSHA512StringWithKey:(NSString *)key;
    
#pragma mark - 文件散列函數(shù)
    
    /**
     *  計(jì)算文件的MD5散列結(jié)果
     *
     *  終端測(cè)試命令:
     *  @code
     *  md5 file.dat
     *  @endcode
     *
     *  @return 32個(gè)字符的MD5散列字符串
     */
- (NSString *)fileMD5Hash;
    
    /**
     *  計(jì)算文件的SHA1散列結(jié)果
     *
     *  終端測(cè)試命令:
     *  @code
     *  openssl sha1 file.dat
     *  @endcode
     *
     *  @return 40個(gè)字符的SHA1散列字符串
     */
- (NSString *)fileSHA1Hash;
    
    /**
     *  計(jì)算文件的SHA256散列結(jié)果
     *
     *  終端測(cè)試命令:
     *  @code
     *  openssl sha256 file.dat
     *  @endcode
     *
     *  @return 64個(gè)字符的SHA256散列字符串
     */
- (NSString *)fileSHA256Hash;
    
    /**
     *  計(jì)算文件的SHA512散列結(jié)果
     *
     *  終端測(cè)試命令:
     *  @code
     *  openssl sha512 file.dat
     *  @endcode
     *
     *  @return 128個(gè)字符的SHA512散列字符串
     */
- (NSString *)fileSHA512Hash;
    
@end

NSString+Hash.m

#import "NSString+Hash.h"
#import <CommonCrypto/CommonCrypto.h>

@implementation NSString (Hash)
    
#pragma mark - 散列函數(shù)
- (NSString *)md5String {
    const char *str = self.UTF8String;
    uint8_t buffer[CC_MD5_DIGEST_LENGTH];
    
    CC_MD5(str, (CC_LONG)strlen(str), buffer);
    
    return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
}
    
- (NSString *)sha1String {
    const char *str = self.UTF8String;
    uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
    
    CC_SHA1(str, (CC_LONG)strlen(str), buffer);
    
    return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
}
    
- (NSString *)sha256String {
    const char *str = self.UTF8String;
    uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
    
    CC_SHA256(str, (CC_LONG)strlen(str), buffer);
    
    return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
}
    
- (NSString *)sha512String {
    const char *str = self.UTF8String;
    uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
    
    CC_SHA512(str, (CC_LONG)strlen(str), buffer);
    
    return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
}
    
#pragma mark - HMAC 散列函數(shù)
- (NSString *)hmacMD5StringWithKey:(NSString *)key {
    const char *keyData = key.UTF8String;
    const char *strData = self.UTF8String;
    uint8_t buffer[CC_MD5_DIGEST_LENGTH];
    
    CCHmac(kCCHmacAlgMD5, keyData, strlen(keyData), strData, strlen(strData), buffer);
    
    return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
}
    
- (NSString *)hmacSHA1StringWithKey:(NSString *)key {
    const char *keyData = key.UTF8String;
    const char *strData = self.UTF8String;
    uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
    
    CCHmac(kCCHmacAlgSHA1, keyData, strlen(keyData), strData, strlen(strData), buffer);
    
    return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
}
    
- (NSString *)hmacSHA256StringWithKey:(NSString *)key {
    const char *keyData = key.UTF8String;
    const char *strData = self.UTF8String;
    uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
    
    CCHmac(kCCHmacAlgSHA256, keyData, strlen(keyData), strData, strlen(strData), buffer);
    
    return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
}
    
- (NSString *)hmacSHA512StringWithKey:(NSString *)key {
    const char *keyData = key.UTF8String;
    const char *strData = self.UTF8String;
    uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
    
    CCHmac(kCCHmacAlgSHA512, keyData, strlen(keyData), strData, strlen(strData), buffer);
    
    return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
}
    
#pragma mark - 文件散列函數(shù)
    
#define FileHashDefaultChunkSizeForReadingData 4096
    
- (NSString *)fileMD5Hash {
    NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self];
    if (fp == nil) {
        return nil;
    }
    
    CC_MD5_CTX hashCtx;
    CC_MD5_Init(&hashCtx);
    
    while (YES) {
        @autoreleasepool {
            NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
            
            CC_MD5_Update(&hashCtx, data.bytes, (CC_LONG)data.length);
            
            if (data.length == 0) {
                break;
            }
        }
    }
    [fp closeFile];
    
    uint8_t buffer[CC_MD5_DIGEST_LENGTH];
    CC_MD5_Final(buffer, &hashCtx);
    
    return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
}
    
- (NSString *)fileSHA1Hash {
    NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self];
    if (fp == nil) {
        return nil;
    }
    
    CC_SHA1_CTX hashCtx;
    CC_SHA1_Init(&hashCtx);
    
    while (YES) {
        @autoreleasepool {
            NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
            
            CC_SHA1_Update(&hashCtx, data.bytes, (CC_LONG)data.length);
            
            if (data.length == 0) {
                break;
            }
        }
    }
    [fp closeFile];
    
    uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1_Final(buffer, &hashCtx);
    
    return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
}
    
- (NSString *)fileSHA256Hash {
    NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self];
    if (fp == nil) {
        return nil;
    }
    
    CC_SHA256_CTX hashCtx;
    CC_SHA256_Init(&hashCtx);
    
    while (YES) {
        @autoreleasepool {
            NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
            
            CC_SHA256_Update(&hashCtx, data.bytes, (CC_LONG)data.length);
            
            if (data.length == 0) {
                break;
            }
        }
    }
    [fp closeFile];
    
    uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
    CC_SHA256_Final(buffer, &hashCtx);
    
    return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
}
    
- (NSString *)fileSHA512Hash {
    NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self];
    if (fp == nil) {
        return nil;
    }
    
    CC_SHA512_CTX hashCtx;
    CC_SHA512_Init(&hashCtx);
    
    while (YES) {
        @autoreleasepool {
            NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
            
            CC_SHA512_Update(&hashCtx, data.bytes, (CC_LONG)data.length);
            
            if (data.length == 0) {
                break;
            }
        }
    }
    [fp closeFile];
    
    uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
    CC_SHA512_Final(buffer, &hashCtx);
    
    return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
}
    
#pragma mark - 助手方法
    /**
     *  返回二進(jìn)制 Bytes 流的字符串表示形式
     *
     *  @param bytes  二進(jìn)制 Bytes 數(shù)組
     *  @param length 數(shù)組長(zhǎng)度
     *
     *  @return 字符串表示形式
     */
- (NSString *)stringFromBytes:(uint8_t *)bytes length:(int)length {
    NSMutableString *strM = [NSMutableString string];
    
    for (int i = 0; i < length; i++) {
        [strM appendFormat:@"%02x", bytes[i]];
    }
    
    return [strM copy];
}
    
@end
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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