PHP、iOS 使用JSPatch基本与RSA,AES加密
在使用JSPatch时,JS脚本理论上可以调用任意OC方法,权限非常大,若经过HTTP传输时,被中间人攻击篡改js代码,则会造成很大危害。
鉴于此种情况
1. 服务器尽量使用https传输2. 对传输的代码做好加密和校验
接下来,以服务器端使用php,移动端iOS,主要对第二种方式进行处理
RSA算法
一般来说RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。
RSA算法是一种非对称加密算法,常被用于加密数据传输.如果配合上数字摘要算法, 也可以用于文件签名.
RSA算法是一种非对称算法,算法需要一对密钥,使用其中一个加密,需要使用另外一个才能解密。我们在进行RSA加密通讯时,就把公钥放在客户端,私钥留在服务器。
1.公钥加密,私钥解密2.私钥对文件进行签名,公钥对签名进行验证
公钥、私钥生成
-
使用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框架,加密解密代码与框架无直接关系)
<?php /** * Created by PhpStorm. * User: and * Date: 16/2/1 * Time: 10:14 */ namespace Home\Controller; class RsaController extends CommenController { //使用文本打开之前获取的private_key.pem可得如下 const PRIVATE_KEY = '-----BEGIN PRIVATE KEY----- MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAN2DTzqHsIiEw8bQ R3MT9FpwVzet+kGQphJCFfY6A5u4gK6BuiVKqJpRroJlzg5yT3zy5tzowpSqIuMZ 8104ncih3uvKoNvvPhwjTy6mGHJHoKaGBlnK7oMXOmi50wVA8qvf++kZnxn9W7tM YnCe6GSkQBS5KgythpIqPaqcaY1dAgMBAAECgYEAjTfqacEZvV8OxRABjQ76qDGY mOm0cto51cgF4k0IAd21RAt2VdHr/T33yDAJFtKvdFQS9GD7s/VnemsP6K1wgMld AvV2+KAPK2ZcCNTktLLBmOikJtBYQZGBnaAlxKQD2RFr+YJRCORxSQfOgGVxzch6 tgXC7VyQmddYBvaOEq0CQQD0dRHMxvn8iTa1x+Df4ghE3XZwyG8rDIpMehfAQdm/ hgf5Z1DX56DOG0LD99OMH5wE+C8CHdSP9F842cFJrZjTAkEA5/jlFcQU3vW/6fmk XshHyaF40s9+5K84i/1EzTW/Wx08zZGql/WrTuQ8QllMAUDR6+kZvPLSPexA/8DS e8xjDwJAObn7fhPurIfqd3q/y56gvUJe2bs7JTtM3UpnmWrzdJq9/1M6cAGuo30k gwpe1lQQj8vbrfBFZckbQ12Im1F3KQJBAIBQCY+nnY/SyaxHfWc8S5E5cxbQ1bTz Q0kT+Cm2sDlbC9X93CogJvkFgFuG/2a2Dyf6EVWVzzuXYkDVzNfTr3sCQQCdTK7v I+C/aVcGFFYE0ZL5y3zxUtccBdhJNORb2fG5Oa7tqJH2bancuspeoArcpqElH7GQ Mm9YArj1T6E10X0E -----END PRIVATE KEY-----'; public function test() { //此处为了验证,所以取出publick_key.pem中的public_key $public_key = '-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdg086h7CIhMPG0EdzE/RacFc3 rfpBkKYSQhX2OgObuICugbolSqiaUa6CZc4Ock988ubc6MKUqiLjGfNdOJ3Iod7r yqDb7z4cI08uphhyR6CmhgZZyu6DFzpoudMFQPKr3/vpGZ8Z/Vu7TGJwnuhkpEAU uSoMrYaSKj2qnGmNXQIDAQAB -----END PUBLIC KEY-----'; //之前使用openssl生成private_key时填写的密码 $open_key = '123456'; $pi_key = openssl_pkey_get_private(self::PRIVATE_KEY,$open_key);//这个函数可用来判断私钥是否是可用的,可用返回资源id Resource id echo $pi_key,"\n"; $pu_key = openssl_pkey_get_public($public_key);//这个函数可用来判断公钥是否是可用的 echo $pu_key,"\n"; $data = "xiaohulu123";//原始数据 $encrypted = ""; $decrypted = ""; echo "source data:",$data,"\n"; echo "private key encrypt:\n"; openssl_public_encrypt($data,$encrypted,$pu_key);//公钥加密,私钥解密 $encrypted = base64_encode($encrypted);//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的 echo "公钥加密后:",$encrypted,"\n"; openssl_private_decrypt(base64_decode($encrypted),$decrypted,$pi_key);//私钥加密的内容通过公钥可用解密出来 echo "私钥解密:",$decrypted,"\n"; echo "\n","---------------------------------------","\n"; //私钥对数据进行签名,公钥解密验证 $bicode = ""; $cdbicode = ""; openssl_private_encrypt($data, $bicode, $pi_key); $bicode = base64_encode($bicode); echo "私钥签名:",$bicode,"\n"; openssl_public_decrypt(base64_decode($bicode), $cdbicode, $pu_key); echo "公钥验证签名:",$cdbicode,"\n"; } }
如果得不到resourceID,先查看是否开启openssl扩展,之后查看private_key是否私自添加了缩进等。
=============
iOS使用JSPatch
JSPatch脚本的执行权限很高,若在传输过程中被中间人篡改,会带来很大的安全问题,为了防止这种情况出现,我们在传输过程中对JS文件进行了RSA签名加密,流程如下:
服务端:
- 计算 JS 内容 MD5 值。
- 用 RSA 私钥对 MD5 值进行加密,与JS内容一起下发给客户端。
客户端:
- 拿到加密数据,用 RSA 公钥解密出 MD5 值。
- 本地计算返回的 JS 内容 MD5 值。
- 对比上述的两个 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端原生加解密并不是很好用,所以在此使用github上已经封装好的RSA加解密方法,下载请点击 RSA加密解密
- 导入Security.framework
- 把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]]; // 解密前进行 GTMBase64 编码 NSData *EncryptData = [GTMBase64 decodeString:aString]; NSString *unCode = [SecurityUtil decryptAESData:EncryptData app_key:aesKey]; //NSLog(@"xx 解密:%@", string1); return unCode; }

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

在PHP中,應使用password_hash和password_verify函數實現安全的密碼哈希處理,不應使用MD5或SHA1。1)password_hash生成包含鹽值的哈希,增強安全性。 2)password_verify驗證密碼,通過比較哈希值確保安全。 3)MD5和SHA1易受攻擊且缺乏鹽值,不適合現代密碼安全。

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP類型提示提升代碼質量和可讀性。 1)標量類型提示:自PHP7.0起,允許在函數參數中指定基本數據類型,如int、float等。 2)返回類型提示:確保函數返回值類型的一致性。 3)聯合類型提示:自PHP8.0起,允許在函數參數或返回值中指定多個類型。 4)可空類型提示:允許包含null值,處理可能返回空值的函數。

PHP仍然具有活力,其在現代編程領域中依然佔據重要地位。 1)PHP的簡單易學和強大社區支持使其在Web開發中廣泛應用;2)其靈活性和穩定性使其在處理Web表單、數據庫操作和文件處理等方面表現出色;3)PHP不斷進化和優化,適用於初學者和經驗豐富的開發者。

PHP和Python各有優劣,選擇取決於項目需求和個人偏好。 1.PHP適合快速開發和維護大型Web應用。 2.Python在數據科學和機器學習領域佔據主導地位。

PHP適合web開發,特別是在快速開發和處理動態內容方面表現出色,但不擅長數據科學和企業級應用。與Python相比,PHP在web開發中更具優勢,但在數據科學領域不如Python;與Java相比,PHP在企業級應用中表現較差,但在web開發中更靈活;與JavaScript相比,PHP在後端開發中更簡潔,但在前端開發中不如JavaScript。
