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; }

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

Laravel simplifies handling temporary session data using its intuitive flash methods. This is perfect for displaying brief messages, alerts, or notifications within your application. Data persists only for the subsequent request by default: $request-

The PHP Client URL (cURL) extension is a powerful tool for developers, enabling seamless interaction with remote servers and REST APIs. By leveraging libcurl, a well-respected multi-protocol file transfer library, PHP cURL facilitates efficient execution of various network protocols, including HTTP, HTTPS, and FTP. This extension offers granular control over HTTP requests, supports multiple concurrent operations, and provides built-in security features.

Laravel provides concise HTTP response simulation syntax, simplifying HTTP interaction testing. This approach significantly reduces code redundancy while making your test simulation more intuitive. The basic implementation provides a variety of response type shortcuts: use Illuminate\Support\Facades\Http; Http::fake([ 'google.com' => 'Hello World', 'github.com' => ['foo' => 'bar'], 'forge.laravel.com' =>

Do you want to provide real-time, instant solutions to your customers' most pressing problems? Live chat lets you have real-time conversations with customers and resolve their problems instantly. It allows you to provide faster service to your custom

Article discusses late static binding (LSB) in PHP, introduced in PHP 5.3, allowing runtime resolution of static method calls for more flexible inheritance.Main issue: LSB vs. traditional polymorphism; LSB's practical applications and potential perfo

PHP logging is essential for monitoring and debugging web applications, as well as capturing critical events, errors, and runtime behavior. It provides valuable insights into system performance, helps identify issues, and supports faster troubleshoot

The Storage::download method of the Laravel framework provides a concise API for safely handling file downloads while managing abstractions of file storage. Here is an example of using Storage::download() in the example controller:

Laravel simplifies HTTP verb handling in incoming requests, streamlining diverse operation management within your applications. The method() and isMethod() methods efficiently identify and validate request types. This feature is crucial for building
