鉴于此种情况
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框架,加密解密代码与框架无直接关系) 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加密解密
导入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; }