PHP、iOS 使用JSPatch基本與RSA,AES加密

來源:互聯網
上載者:User
在使用JSPatch時,JS指令碼理論上可以調用任意OC方法,許可權非常大,若經過HTTP傳輸時,被中間人攻擊篡改js代碼,則會造成很大危害。

鑒於此種情況

1. 伺服器盡量使用https傳輸2. 對傳輸的代碼做好加密和校正

接下來,以伺服器端使用php,移動端iOS,主要對第二種方式進行處理

RSA演算法

RSA是目前最有影響力的公開金鑰加密演算法,它能夠抵抗到目前為止已知的絕大多數密碼攻擊,已被ISO推薦為公開金鑰資料加密標準。

RSA演算法是一種非對稱式加密演算法,常被用於加密資料傳輸.如果配合上數字摘要演算法, 也可以用於檔案簽名.

RSA演算法是一種非對稱演算法,演算法需要一對密鑰,使用其中一個加密,需要使用另外一個才能解密。我們在進行RSA加密通訊時,就把公開金鑰放在用戶端,私密金鑰留在伺服器。

一般來說
1.公開金鑰加密,私密金鑰解密2.私密金鑰對檔案進行簽名,公開金鑰對簽名進行驗證

公開金鑰、私密金鑰產生

  1. 使用openSSL命令產生密鑰

openssl req -x509 -out public_key.der -outform der -new -newkey rsa:1024 -keyout private_key.pem

按照提示,填入私密金鑰的密碼(之後會使用),簽署憑證的組織名、郵件等資訊之後,就會產生包含有公開金鑰的認證檔案public_key.der和私密金鑰檔案private_key.pem。

public_key.der檔案用於分發到ios用戶端進行公開金鑰加解密,而private_key.pem檔案留在伺服器端供php使用

openssl rsa -in private_key.pem -pubout -out public_key.pem

此命令會根據輸入的私密金鑰檔案產生pem格式的公開金鑰檔案,這也是把private_key放在服務端的原因

服務端php代碼(ThinkPHP架構,加密解密代碼與架構無直接關係)

       
 

如果得不到resourceID,先查看是否開啟openssl擴充,之後查看private_key是否私自添加了縮排等。

=============

iOS使用JSPatch

JSPatch指令碼的執行許可權很高,若在傳輸過程中被中間人篡改,會帶來很大的安全問題,為了防止這種情況出現,我們在傳輸過程中對JS檔案進行了RSA簽名加密,流程如下:

服務端:

  1. 計算 JS 內容 MD5 值。
  2. 用 RSA 私密金鑰對 MD5 值進行加密,與JS內容一起下發給用戶端。

用戶端:

  1. 拿到加密資料,用 RSA 公開金鑰解密出 MD5 值。
  2. 本地計算返回的 JS 內容 MD5 值。
  3. 對比上述的兩個 MD5 值,若相等則校正通過,取 JS 檔案儲存到本地。由於 RSA 是非對稱式加密,在沒有私密金鑰的情況下第三方無法加密對應的 MD5 值,也就無法偽造 JS 檔案,杜絕了 JS 檔案在傳輸過程被篡改的可能。

服務端php代碼

/*     * 加密一個字串,返回RSA加密後的內容     * aString 需要加密的字串     * return encrypted rsa加密後的字串     */    public function enjscode($aString) {        $pi_key = openssl_pkey_get_private(self::PRIVATE_KEY);//這個函數可用來判斷私密金鑰是否是可用的,可用返回資源id Resource id        openssl_private_encrypt($aString, $encrypted, $pi_key);//私密金鑰加密        $encrypted = base64_encode($encrypted);//加密後的內容通常含有特殊字元,需要編碼轉換下,在網路間通過url傳輸時要注意base64編碼是否是url安全的        return $encrypted;    }    //JS    public function jscode() {        //$headers = $this->verifyHeaders();        //驗證header        //$this->verifyHeadersWithHeaders($headers);        $data['con'] = "defineClass('FindViewController',{viewDidLoad: function() {self.super().viewDidLoad();self.setTitle('發現哈哈');_selectedIndex = 0;self.initView();}})";        $data['isUpdate'] = 'true';       //首先計算js內容的md5值,再將md5值進行RSA加密        $data["ver"] = self::enjscode(md5($data['con']));        $data1['con'] = "require('UIAlertView');defineClass('CircleHotPageViewController',{tableView_didSelectRowAtIndexPath:function(tableView,indexPath){tableView.deselectRowAtIndexPath_animated(indexPath, YES);var alert = UIAlertView.alloc().initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles('只是提示而已', '測試JSPath!', null, '知道了', null, null);alert.show();}})";        $data1['isUpdate'] = 'true';        $data1["ver"] = self::enjscode(md5($data1['con']));        $this->json_out('200','0','',$da);    }
iOS端代碼

由於iOS端原生加解密並不是很好用,所以在此使用github上已經封裝好的RSA加解密方法,下載請點擊 RSA加密解密

  1. 匯入Security.framework
  2. 把public_key.pem中的public_key取出
#define rsa_public_key @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdg086h7CIhMPG0EdzE/RacFc3rfpBkKYSQhX2OgObuICugbolSqiaUa6CZc4Ock988ubc6MKUqiLjGfNdOJ3Iod7ryqDb7z4cI08uphhyR6CmhgZZyu6DFzpoudMFQPKr3/vpGZ8Z/Vu7TGJwnuhkpEAUuSoMrYaSKj2qnGmNXQIDAQAB"

3.在didFinishLaunchingWithOptions方法中進行網路請求,從網路斷擷取內容data

    /*     *  擷取內容為     *  con         js內容     *  isUpdate    是否更新(無用)     *  ver         驗證內容,有con 計算md5,再進行rsa加密得來  ->  用戶端首頁解密得到con的md5值,將此md5值與擷取的js內容的md5值進行比較     *           *  若值相等,則說明無篡改;否則,說明被篡改,放棄儲存     */    - (void)upJSHandle:(NSDictionary *)response {    NSMutableString *jsString = [NSMutableString string];    for (NSDictionary *di in (NSArray *)response) {        NSString *js = di[@"con"];       //計算擷取到的js內容的md5值        NSString *jsMd5 = [MiscTool md5:js];        //解密擷取js內容的md5        NSString *cdMd5 = [RSA decryptString:di[@"ver"] publicKey:rsa_public_key];        NSLog(@"cd bicode = %@",cdMd5);        //校正        if (![jsMd5 isEqualToString:cdMd5]) {//經過校正,不相等,說明內容被篡改,直接返回不儲存            NSLog(@"zz 內容被篡改!!!");            return;        }        [jsString appendString:js];        //將代碼下載到本地,儲存成檔案Document/up.js, 各個方法之間使用 ***** 分隔字元        [jsString appendString:@"*****"];        }        //擷取儲存js檔案內容        NSString *jsPath = [self jsFilePath];        NSLog(@"js xx = 寫入 %@",jsString);        //將jsString 進行aes對稱式加密        //jsString = [self aes:jsString].mutableCopy;        //NSLog(@"xx 加密後 = %@",jsString);        NSData *jsData = [jsString dataUsingEncoding:(NSUTF8StringEncoding)];        //寫入檔案        [jsData writeToFile:jsPath atomically:YES];        //執行        [self execUpJsWithJsArray:[self readJs]];    }

4.在applicationDidBecomeActive方法,讀取js檔案,並執行

    #pragma mark -- js 讀取    - (NSArray *)readJs {        NSString *file = [self jsFilePath];        NSFileManager *fileManager = [NSFileManager defaultManager];        if(![fileManager fileExistsAtPath:file]) {//如果不存在            return @[];        }        NSString *jsString = [NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil];        //取出後,將jsString 解密        //jsString = [self cdAes:jsString];        //NSLog(@"xx 解密後 = %@",jsString);        NSArray *jsArray = [jsString componentsSeparatedByString:@"*****"];        return jsArray;    }    - (void)execUpJsWithJsArray:(NSArray *)jsArray {        if (jsArray.count == 0) {            return;        }        [JPEngine startEngine];        for (NSString *js in jsArray) {            if ([js isEqualToString:@""] || js == nil) {                continue;            }            NSLog(@"read js = %@",js);            [JPEngine evaluateScript:js];        }    }    - (void)applicationDidBecomeActive:(UIApplication *)application {    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.    //每次進入時執行js    [self execUpJsWithJsArray:[self readJs]];      }

本機存放區

本機存放區的指令碼被篡改的機會小很多,只在越獄機器上有點風險,對此可以在下載完指令碼儲存到本地時進行對稱式加密,每次讀取時解密。

aes加密解密
    /*     *  進行aes對稱式加密     */    - (NSString *)aes:(NSString *)aString {        NSString *biCode = [SecurityUtil encryptAESData:aString app_key:aesKey];        //NSLog(@"xx 加密: %@",st);        return biCode;    }    /*     *  對字串進行aes解密     */    - (NSString *)cdAes:(NSString *)aString {        //NSData *EncryptData1 = [GTMBase64 decodeString:[SecurityUtil encryptAESData:string app_key:aesKey]]; // 解密前進行 GTMBase 64 編碼        NSData *EncryptData = [GTMBase64 decodeString:aString];        NSString *unCode = [SecurityUtil decryptAESData:EncryptData app_key:aesKey];        //NSLog(@"xx 解密:%@", string1);        return unCode;    }
  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.