App安全

  常常作的網絡參數加密解密,以及防止數據重放以外,還提到了防範反編譯的風險,其實Apple算比較安全的了,反編譯過來也就看到.h文件....但把代碼混淆仍是會比較好些。html

1、iOS 中的網絡加密

  公司的接口通常會兩種協議的,一種HTTP,一種HTTPS的,HTTP 只要請求,服務器就會響應,若是咱們不對請求和響應作出加密處理,全部信息都是會被檢測劫持到的,是很不安全的,客戶端加密可使用我這套工具類進行處理: 文章地址
  可是不論在任什麼時候候,都應該將服務置於HTTPS上,由於它能夠避免中間人攻擊的問題,還自帶了基於非對稱密鑰的加密通道!使用HTTPS後,能夠省去各類加解密技術。

介紹下HTTPS交互原理

簡答說,HTTPS 就是 HTTP協議加了一層SSL協議的加密處理,SSL 證書就是遵照 SSL協議,由受信任的數字證書頒發機構CA(如GlobalSign,wosign),在驗證服務器身份後頒發,這是須要花錢滴,簽發後的證書做爲公鑰通常放在服務器的根目錄下,便於客戶端請求返回給客戶端,私鑰在服務器的內部中心保存,用於解密公鑰。java

HTTPS 客戶端與服務器交互過程:

一、客戶端發送請求,服務器返回公鑰給客戶端;
二、客戶端生成對稱加密祕鑰,用公鑰對其進行加密後,返回給服務器;
三、服務器收到後,利用私鑰解開獲得對稱加密祕鑰,保存;
四、以後的交互都使用對稱加密後的數據進行交互。ios

談下證書
簡單說,證書有兩種,一種是正經的:算法

一種是不正經的:sql

介紹下咱們須要作什麼

若是遇到正經的證書,咱們直接用AFNetworking 直接請求就行了,AFNetworking 內部幫咱們封裝了HTTPS的請求方式,可是大部分公司接口都是不正經的證書,這時須要咱們作如下幾步:
一、將服務器的公鑰證書拖到Xcode中
二、修改驗證模式數據庫

manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];

原理:
簡單來講,就是你本能夠修改AFN這個設置來容許客戶端接收服務器的任何證書,可是這麼作有個問題,就是你沒法驗證證書是不是你的服務器後端的證書,給中間人攻擊,即經過重定向路由來分析僞造你的服務器端打開了大門。vim

AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
securityPolicy.allowInvalidCertificates = YES;
解決方法:AFNetworking是容許內嵌證書的,經過內嵌證書,AFNetworking就經過比對服務器端證書、內嵌的證書、站點域名是否一致來驗證鏈接的服務器是否正確。因爲CA證書驗證是經過站點域名進行驗證的,若是你的服務器後端有綁定的域名,這是最方便的。將你的服務器端證書,若是是pem格式的,用下面的命令轉成cer格式
openssl x509 -in <你的服務器證書>.pem -outform der -out server.cer

而後將生成的server.cer文件,若是有自建ca,再加上ca的cer格式證書,引入到app的bundle裏,AFNetworking在後端

AFSecurityPolicy *securityPolicy = [AFSecurityPolicy AFSSLPinningModeCertificate];

或者數組

AFSecurityPolicy *securityPolicy = [AFSecurityPolicy AFSSLPinningModePublicKey];

狀況下,會自動掃描bundle中.cer的文件,並引入,這樣就能夠經過自簽證書來驗證服務器惟一性了。瀏覽器

AFSecurityPolicy分三種驗證模式:

AFSSLPinningModeNone

這個模式表示不作SSL pinning,
只跟瀏覽器同樣在系統的信任機構列表裏驗證服務端返回的證書。若證書是信任機構簽發的就會經過,如果本身服務器生成的證書就不會經過。

AFSSLPinningModeCertificate

這個模式表示用證書綁定方式驗證證書,須要客戶端保存有服務端的證書拷貝,這裏驗證分兩步,第一步驗證證書的域名有效期等信息,第二步是對比服務端返回的證書跟客戶端返回的是否一致。

AFSSLPinningModePublicKey

這個模式一樣是用證書綁定方式驗證,客戶端要有服務端的證書拷貝,
只是驗證時只驗證證書裏的公鑰,不驗證證書的有效期等信息。只要公鑰是正確的,就能保證通訊不會被竊聽,由於中間人沒有私鑰,沒法解開經過公鑰加密的數據。

 

除了證書加密:

  用 POST 請求提交用戶的隱私數據,仍是不能徹底解決安全問題。所以:咱們常常會用到加密技術,好比說在登陸的時候,咱們會先把密碼用MD5加密再傳輸給服務器 或者 直接對全部的參數進行加密再POST到服務器。

1.數據安全介紹
  • 最基礎的是咱們發送網絡請求時,使用getpost方式發送請求。二者具體區別就不作解釋了,只是引出相關安全性問題

    • get:將參數暴露在外,(絕對不安全-->明文請求或者傻瓜式請求)。
    • post:將參數放到請求體body中,(相對於get比較安全-->可是咱們能夠很容易用一些軟件截獲請求數據。好比說Charles(青花瓷)
  • Charles(大部分app的數據來源都使用該工具來抓包,並作網絡測試)

    • 注意:Charles在使用中的亂碼問題,能夠顯示包內容,而後打開info.plist文件,找到java目錄下面的VMOptions,在後面添加一項:-Dfile.encoding=UTF-8
  • 數據安全的原則

    • 在網絡上不容許傳輸用戶隱私數據的明文,(即:App網絡傳輸安全,指對數據從客戶端傳輸到Server中間過程的加密,防止網絡世界當中其餘節點對數據的竊聽)。
    • 在本地不容許保存用戶隱私數據的明文,(即:App數據存儲安全,主要指在磁盤作數據持久化的時候所作的加密)。
    • App代碼安全,(即:包括代碼混淆,加密或者app加殼)。
  • 要想很是安全的傳輸數據,建議使用https。抓包不能夠,可是中間人攻擊則有可能。建議雙向驗證防止中間人攻擊,能夠參考下文篇章。

 

二、經常使用加密算法

編碼方案   Base64

哈希(散列)函數 MD5(消息摘要算法)

                    SHA1

                    SHA256

對稱加密算法  DES

                    AES

非對稱加密算法  RSA

HTTPS           HTTP+SSL協議

 

三、經常使用加密方式

1.經過簡單 BASE64編碼 防止數據明文傳輸

2.對普通請求、返回數據,生成MD5校驗(MD5中加入動態密鑰),進行數據完整性(簡單防篡改,安全性較低,優勢:快速)校驗

3.對於重要數據,使用RSA進行數字簽名,起到防篡改做

4.對於比較敏感的數據,如用戶信息(登錄、註冊等),客戶端發送使用RSA加密,服務器返回使用DES(AES)加密

5.要想很是安全的傳輸數據,建議使用https。抓包不能夠,可是中間人攻擊則有可能。建議雙向驗證防止中間人攻擊

4.Base64編碼方案
  1. Base64簡單說明
    描述:Base64能夠成爲密碼學的基石,很是重要。
    特色:能夠將任意的二進制數據進行Base64編碼
    結果:全部的數據都能被編碼爲並只用65個字符(A~Z a~z 0~9 + / =)就能表示的文本文件。
    注意:對文件進行base64編碼後文件數據的變化:編碼後的數據~=編碼前數據的4/3,會大1/3左右。

  2. Base64編碼原理和處理過程

  1. Base64實現代碼
// 對一個字符串進行base64編碼,而且返回
-(NSString *)base64EncodeString:(NSString *)string {
    // 1.先轉換爲二進制數據
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; // 2.對二進制數據進行base64編碼,完成以後返回字符串 return [data base64EncodedStringWithOptions:0]; } // 對base64編碼以後的字符串解碼,而且返回 -(NSString *)base64DecodeString:(NSString *)string { // 注意:該字符串是base64編碼後的字符串 // 1.轉換爲二進制數據(完成了解碼的過程) NSData *data = [[NSData alloc]initWithBase64EncodedString:string options:0]; // 2.把二進制數據在轉換爲字符串 return [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]; } //---------------------------<#我是分割線#>------------------------------//  NSLog(@"%@",[self base64EncodeString:@"A"]); NSLog(@"%@",[self base64DecodeString:@"QQ=="]);

PS.終端執行編碼和解碼

如:
編碼:base64 123.png -o 123.txt 解碼:base64 123.txt -o test.png -D
4.加密實現代碼

哈希(散列)函數
特色:

  • 算法是公開的
  • 對相同的數據加密,獲得的結果是同樣的"
  • 對不一樣的數據加密,獲得的結果是定長的,MD5對不一樣的數據進行加密,獲得的結果都是 32 個字符長度的字符串
  • 信息摘要,信息"指紋",是用來作數據識別的!
  • 不能逆推反算(重要)

用途:

  • 版權 對文件進行散列判斷該文件是不是正版或原版的
  • 文件完整性驗證 對整個文件進行散列,比較散列值判斷文件是否完整或被篡改
  • 密碼加密,服務器並不須要知道用戶真實的密碼!
  • 搜索:
    如:百度搜索-->老司機 皮皮蝦 蒼老師
    或是 【蒼老師 老司機 皮皮蝦 】
    上面兩種方式搜索出來的內容是同樣的
    • 如何判斷:對搜索的每一個關鍵字進行三列,獲得三個相對應的結果,按位相加結果若是是同樣的,那搜索的內容就是同樣的!
  • 經典加密算法:MD五、SHA一、SHA512
MD5消息摘要算法
  • 簡單介紹:

    • MD5:全稱是Message Digest Algorithm 5,譯爲「消息摘要算法第5版」(經MD二、MD3和MD4發展而來)
    • 效果:對輸入信息生成惟一的128位散列值(32個字符),即 32個16進制的數字。
  • 特色:

    • 輸入兩個不一樣的明文不會獲得相同的輸出值
    • 根據輸出值,不能獲得原始的明文,即其過程不可逆(只能加密, 不能解密)
  • 應用:

    • 如今的MD5已再也不是絕對安全(如:暴力破解的網站),對此,能夠對MD5稍做改進,以增長解密的難度。
    • 解決:加鹽(Salt):在明文的固定位置插入隨機串,而後再進行MD5(先加密,後亂序:先對明文進行MD5,而後對加密獲得的MD5串的字符進行亂序)
  • 注意點:

    • 開發中,必定要和後臺開發人員約定好,MD5加密的位數是16位仍是32位(大多數都是32位的),16位的能夠經過32位的轉換獲得。
    • MD5加密區分 大小寫,使用時要和後臺約定好。
    • MD5公認被破解不表明其可逆,而是一段字符串加密後的密文,能夠經過強大運算計算出字符串加密後的密文對應的原始字符串,但也不是絕對的被破解。
  • PS.暴力破解是指經過將明文和生成的密文進行配對,生成強大的數據庫,在數據庫中搜索,在這裏就能夠破解密碼。破解網址 http://www.cmd5.com

提高MD5加密安全性,解決辦法

  • 1.先明文加鹽,而後再進行MD5。即明文後拼接字符串(此時拼接的字符串要 足夠長+足夠鹹+足夠複雜),再進行MD5加密。如:#define salt @"1342*&%&shlfhs390(*^^6R%@@KFGKF"
  • 2.先加密+亂序

  • 3.亂序|加鹽,屢次MD5加密等

  • 4.使用消息認證機制HMAC:給定一個"祕鑰",對明文進行加密,而且作"兩次散列"!-> 獲得的結果,仍是 32 個字符,相對安全(KEY是服務器傳給你的,不是你寫死的)。

消息認證機制(HMAC)簡單說明

  • 原理
    • 消息的發送者和接收者有一個共享密鑰
    • 發送者使用共享密鑰對消息加密計算獲得MAC值(消息認證碼)
    • 消息接收者使用共享密鑰對消息加密計算獲得MAC值
    • 比較兩個MAC值是否一致
  • 使用
    • 客戶端須要在發送的時候把(消息)+(消息·HMAC)一塊兒發送給服務器
    • 服務器接收到數據後,對拿到的消息用共享的KEY進行HMAC,比較是否一致,若是一致則信任

簡單示例

#pragma mark - md5加密方法
- (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]; } #pragma mark - HMACMD5加密方法 - (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]; } /** * 返回二進制 Bytes 流的字符串表示形式 * @param bytes 二進制 Bytes 數組 * @param length 數組長度 * @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]; } //---------------------------<#我是分割線#>------------------------------// // md5加密調用 NSLog(@"%@",[@"520it" md5String]); // (明文+加鹽)MD5加密調用 NSLog(@"%@",[[@"520it" stringByAppendingString:salt] md5String]); // hmacMD5加密調用(先加密+亂序) NSLog(@"%@",[@"520it" hmacMD5StringWithKey:@"xiaomage"]);
對稱加密算法AES和DES
  • 對稱加密的特色
    • 加密/解密使用相同的密鑰
    • 加密和解密的過程是可逆的
  • 經典算法
    • DES 數據加密標準
    • AES 高級加密標準
  • 提示:
    • 加密過程是先加密,再base64編碼
    • 解密過程是先base64解碼,再解密

簡單示例

/**
 *  加密字符串並返回base64編碼字符串
 *
 *  @param string    要加密的字符串
 *  @param keyString 加密密鑰
 *  @param iv        初始化向量(8個字節)
 *
 *  @return 返回加密後的base64編碼字符串
 */
- (NSString *)encryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv;
/**
 *  解密字符串
 *
 *  @param string    加密並base64編碼後的字符串
 *  @param keyString 解密密鑰
 *  @param iv        初始化向量(8個字節)
 *
 *  @return 返回解密後的字符串
 */
- (NSString *)decryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv; // 調用 EncryptionTools *encrypt = [EncryptionTools sharedEncryptionTools]; NSLog(@"%@",[encrypt encryptString:@"LN123" keyString:@"LN" iv:nil]); NSLog(@"%@",[encrypt decryptString:@"OPcTMDB5paivqtYo9Fj+hQ==" keyString:@"LN" iv:nil]);
非對稱加密RSA
  • 非對稱加密的特色
    • 使用 公鑰 加密,使用 私鑰 解密
    • 使用 私鑰 加密,使用 公鑰 解密(私鑰簽名,公鑰驗籤)
    • 公鑰是公開的,私鑰保密
    • 加密處理安全,可是性能極差
  • 經典算法-->RSA

簡單示例

// 公鑰加密時調用類方法:
+ (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey;
+ (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey; // 私鑰解密時調用類方法 + (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey; + (NSData *)decryptData:(NSData *)data privateKey:(NSString *)privacy; /** 調用 */ NSString *str = [RSAUtil encryptString: @"LN" publicKey:RSA_Public_key]; NSLog(@"RSA公鑰加密數據-->\n%@",str); NSString *str1 = [RSAUtil decryptString:str privateKey:RSA_Privite_key]; NSLog(@"RSA私鑰解密數據-->%@",str1);

MAC上生成公鑰、私鑰的方法,及使用

 # MAC上生成公鑰、私鑰的方法
 @code
 1.打開終端,切換到本身想輸出的文件夾下 2.輸入指令:openssl(openssl是生成各類祕鑰的工具,mac已經嵌入) 3.輸入指令:genrsa -out rsa_private_key.pem 1024 (生成私鑰,java端使用的) 4.輸入指令:rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout (生成公鑰) 5.輸入指令:pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt(私鑰轉格式,在ios端使用私鑰解密時用這個私鑰) 注意:在MAC上生成三個.pem格式的文件,一個公鑰,兩個私鑰,均可以在終端經過指令vim xxx.pem 打開,裏面是字符串,第三步生成的私鑰是java端用來解密數據的,第五步轉換格式的私鑰iOS端能夠用來調試公鑰、私鑰解密(由於私鑰不留在客戶端) iOS端公鑰加密私鑰解密、java端公鑰加密私鑰解密,java端私鑰加密公鑰解密都容易作到,iOS不能私鑰加密公鑰解密,只能用於驗籤 @endcode
5.HTTPS基本使用
  • https簡單說明

    • HTTPS(全稱:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全爲目標的HTTP通道,簡單講是HTTP的安全版。
    • 在HTTP下加入SSL層,HTTPS的安全基礎是SSL,所以加密的詳細內容就須要SSL。 它是一個URI scheme(抽象標識符體系),句法類同http:體系。用於安全的HTTP數據傳輸。
    • HTTPS:URL代表它使用了HTTP,但HTTPS存在不一樣於HTTP的默認端口及一個加密/身份驗證層(在HTTP與TCP之間)。
  • 注意

    • HTTPS的主要思想是在不安全的網絡上建立一安全信道,並可在使用適當的加密包和服務器證書可被驗證且可被信任時,對竊聽和中間人攻擊提供合理的保護。
    • HTTPS的信任繼承基於預先安裝在瀏覽器中的證書頒發機構(如VeriSign、Microsoft等)(意即「我信任證書頒發機構告訴我應該信任的」)。
    • 所以,一個到某網站的HTTPS鏈接可被信任,若是服務器搭建本身的https 也就是說採用自認證的方式來創建https信道,這樣通常在客戶端是不被信任的。
    • 因此咱們通常在瀏覽器訪問一些https站點的時候會有一個提示,問你是否繼續。
  • HTTPS和HTTP區別

    • https協議須要到ca申請證書,通常免費證書不多,須要交費。
    • http是超文本傳輸協議,信息是明文傳輸,https 則是具備安全性的ssl加密傳輸協議
    • http和https使用的是徹底不一樣的鏈接方式,用的端口也不同,前者是80後者是443
    • http的鏈接很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,比http協議安全。
  • 實現代碼

方案一:若是是本身使用NSURLSession來封裝網絡請求

// 1.建立session
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
// 2.建立Task
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://kyfw.12306.cn/otn"]] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { // 3.解析數據 NSLog(@"%@---%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding],error); }]; // 4.執行task [dataTask resume]; #pragma mark - 遵照<NSURLSessionDataDelegate> // 若是發送的請求是https的,那麼纔會調用該方法 -(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler { /** 判斷服務器傳給咱們的信任的類型,只有是【服務器信任的時候,才安裝證書】 NSURLSessionAuthChallengeDisposition 如何處理證書 NSURLAuthenticationMethodServerTrust 服務器信任 */ if(![challenge.protectionSpace.authenticationMethod isEqualToString:@"NSURLAuthenticationMethodServerTrust"]) { return; } NSLog(@"%@",challenge.protectionSpace); /* NSURLCredential 受權信息 NSURLSessionAuthChallengeUseCredential = 0, 使用該證書 安裝該證書 NSURLSessionAuthChallengePerformDefaultHandling = 1, 默認採用的方式,該證書被忽略 NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2, 取消請求,證書忽略 NSURLSessionAuthChallengeRejectProtectionSpace = 3, 拒絕 */ NSURLCredential *credential = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential,credential); // 注意:並非全部的https的請求都須要安裝證書(受權)的,請求一些大型的網站有的是強制安裝的,如:蘋果官網https://www.apple.com }

方案二:若是使用AFN網絡請求

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

// 更改解析方式(請求網頁源碼應使用原始解析)
manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // 設置對證書的處理方式 // 容許自簽名證書,必須的 manager.securityPolicy.allowInvalidCertificates = YES; // 是否驗證域名的CN字段(不是必須的,可是若是寫YES,則必須導入證書) manager.securityPolicy.validatesDomainName = NO; [manager GET:@"https://kyfw.12306.cn/otn" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"success---%@",[[NSString alloc]initWithData:responseObject encoding:NSUTF8StringEncoding]); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"error---%@",error); }];
6.數據安全--加密解密效果

 

 

2、如何有效防止API的重放攻擊

  API重放攻擊(Replay Attacks)又稱重播攻擊、回放攻擊,這種攻擊會不斷惡意或欺詐性地重複一個有效的API請求。攻擊者利用網絡監聽或者其餘方式盜取API請求,進行必定的處理後,再把它從新發給認證服務器,是黑客經常使用的攻擊方式之一。

  

HTTPS數據加密是否能夠防止重放攻擊?

否,加密能夠有效防止明文數據被監聽,可是卻防止不了重放攻擊。

通常使用以時間戳做爲傳參,後臺協商響應時間差範圍,參考三次握手協議兩邊商量序列號,當發過來的序列號爲服務器也存在的序列號則丟棄。

使用簽名防止重放攻擊

  使用簽名以後,能夠對請求的身份進行驗證。但不一樣阻止重放攻擊,即攻擊者截獲請求後,不對請求進行任何調整。直接使用截獲的內容從新高頻率發送請求。

  API網關提供了一套有效防止重放攻擊的方法。開啓API網關的重放,須要您使用「阿里雲APP」的認證方式。經過這種簽名認證方式,每一個請求只能被使用一次,從而防止重放。

  阿里雲APP:是基於請求內容計算的數字簽名,用於API網關識別用戶身份。客戶端調用API時,須要在請求中添加計算的簽名。API網關在收到請求後會使用一樣的方法計算簽名,同用戶計算的簽名進行比較,相同則驗證經過,不一樣則認證失敗。這種認證的簽名方式請參照:請求籤名

  在API網關的簽名中,提供X-Ca-Timestamp、X-Ca-Nonce兩個可選HEADER,客戶端調用API時一塊兒使用這兩個參數,能夠達到防止重放攻擊的目的。

  

原理

  1. 請求全部的內容都被加入簽名計算,因此請求的任何修改,都會形成簽名失敗。
  2. 不修改內容

    • X-Ca-Timestamp:發起請求的時間,能夠取自機器的本地實現。當API網關收到請求時,會校驗這個參數的有效性,偏差不超過15分鐘。

    • X-Ca-Nonce:這個是請求的惟一標識,通常使用UUID來標識。API網關收到這個參數後會校驗這個參數的有效性,一樣的值,15份內只能被使用一次。

 

 3、代碼混淆

1、在項目根目錄下新建confuse.sh 和 gbFunc.list 文件

 

說明:

 

confuse.sh 文件在編譯過程當中會執行gbFunc.list 用於自動混淆代碼時,存放過濾出來須要混淆的方法名

 

touch confuse.sh

touch gbFunc.list

 

2、新建GBConfuse.h

 

說明:

 

GBConfuse.h 是在自動混淆代碼時,將會把自動生成的字符串定義成宏,存放在此文件,也便於查看。

注意:須要把.h文件移到項目文件外,由於放項目文件中,到時被反編譯過來,仍是能獲得GBConfuse.h裏面的東西的,就能經過比對,獲得方法。(後面用class-dump反編譯過來就明白了...)

在confuse.sh中添加以下代碼

#!/usr/bin/env bash

TABLENAME=symbols SYMBOL_DB_FILE="symbols" #func.list路徑 STRING_SYMBOL_FILE="$PROJECT_DIR/GBFunc.list" #項目文件路徑 CONFUSE_FILE="$PROJECT_DIR/Safedemo" #Confuse.h路徑 HEAD_FILE="$PROJECT_DIR/GBConfuse.h" export LC_CTYPE=C #取以.m或.h結尾的文件以+號或-號開頭的行 |去掉全部+號或-號|用空格代替符號|n個空格跟着<號 替換成 <號|開頭不能是IBAction|用空格split字串取第二部分|排序|去重複|刪除空行|刪掉以init開頭的行>寫進func.list grep -h -r -I "^[-+]" $CONFUSE_FILE --include '*.[mh]' |sed "s/[+-]//g"|sed "s/[();,: *^/{]/ /g"|sed "s/[ ]*</</"| sed "/^[ ]*IBAction/d"|awk '{split($0,b," "); print b[2]; }'| sort|uniq |sed "/^$/d"|sed -n "/^GBSAFE_/p" >$STRING_SYMBOL_FILE #維護數據庫方便往後做排重,如下代碼來自念茜的微博 createTable() { echo "create table $TABLENAME(src text, des text);" | sqlite3 $SYMBOL_DB_FILE } insertValue() { echo "insert into $TABLENAME values('$1' ,'$2');" | sqlite3 $SYMBOL_DB_FILE } query() { echo "select * from $TABLENAME where src='$1';" | sqlite3 $SYMBOL_DB_FILE } ramdomString() { openssl rand -base64 64 | tr -cd 'a-zA-Z' |head -c 16 } rm -f $SYMBOL_DB_FILE rm -f $HEAD_FILE createTable touch $HEAD_FILE #這裏也要作修改 echo '#ifndef GBConfuse_h #define CodeConfuse' >> $HEAD_FILE echo "//confuse string at `date`" >> $HEAD_FILE cat "$STRING_SYMBOL_FILE" | while read -ra line; do if [[ ! -z "$line" ]]; then ramdom=`ramdomString` echo $line $ramdom insertValue $line $ramdom echo "#define $line $ramdom" >> $HEAD_FILE fi done echo "#endif" >> $HEAD_FILE sqlite3 $SYMBOL_DB_FILE .dump

須要修改的代碼在於文件路徑:

添加 Run Script

添加 PCH 文件

在ViewController中添加以"GBSAFE_"爲前綴的測試方法

測試

運行報錯以下:

 

緣由是.sh文件沒有權限,因此須要去開啓權限。

在confuse.sh文件目錄下,執行命令:

chmod 755 confuse.sh

運行成功!

 

先打包一個.ipa安裝包進行測試!

 

先不進行代碼混淆:

把.ipa文件類型改爲.zip,解壓獲得.app文件

新建Hear文件夾用於保存反編譯後獲得的文件:

用class-dump進行反編譯

class-dump -H 要破解的可執行文件路徑 -o 破解後的頭文件存放路徑

獲得沒有進行代碼混淆的文件:

 

能夠看到都是項目中一些.h文件,打開能夠看到完整的方法名....

 

而後客戶說測試公司說不安全...

 

須要進行代碼混淆...

在PCH文件中,引用GBConfuse.h:

 

從新打包..就能夠獲得混淆後的.ipa..

 

下面就是混淆後的結果。

總結:

 

其實,原理應該就是在編譯過程當中,把須要混淆的代碼生成隨機字符串進行替換....

相關文章
相關標籤/搜索