APP 中常用的混合加密

2,025 阅读5分钟
原文链接: www.jianshu.com

title: APP中常用的混合加密
date: 2017-02-28 17:54:49

tags:

要点

  1. 非对称加密的实现在网络传输中的运用
  2. 混合加密思路
  3. 缺陷与提高

关于在App网络通信中,保证信息的安全再重要不过了,苹果去年就宣告要强制使用https来进行App通信加密,但由于种种原因至今没有实施,但是数据完全非常重要,所以要足够引起重视,在公司没有引入Https加密以前,之前在公司采用的是混合加密的方法,分享出来供大家进行参考讨论。

基本思路:客户端随机生成DES密钥A,然后将A通过RSA加密生成密钥B存在字典值“ks”中,将密钥A通过DES加密的实际传输参数放在字典值“loc”中,这样服务器收到参数后会先用私钥进行解密获取对应的密钥A,然后通过密钥A对称解密“loc”中的参数,最后得到实际参数。

//
//  RedGiftEncry.m
//  hexiProNew
//
//  Created by Xiaohr on 15/8/15.
//  20160728 添加用户数据记录接口
//

#import "RedGiftEncry.h"
#import "CRSA.h"
#import "JSONKit.h"
#import "EncryInfo.h"
#import "SecurityDES.h"
@interface RedGiftEncry()

@property (strong,nonatomic)NSString *DESkey; //存储随机生成的DES密钥
@property (strong,nonatomic)NSString *RSAEncryedString; //存储根据DES生成的RSA密钥
@end;

@implementation RedGiftEncry

/**
 进行网编请求的参数调用该方法进行加密

 @param param 参数字典
 @param EncryAppID 标识符
 @return 加密后的参数
 */
+(NSDictionary *)RedGiftEncry:(NSMutableDictionary *)param EncryType:(NSString *)EncryAppID{
    NSDictionary* dicadd = [NSDictionary dictionaryWithObjectsAndKeys:
                                 EncryAppID,@"appid",
                                 @"V1000",@"vid"
                                 , nil];
    [param addEntriesFromDictionary:dicadd];

    NSString *str = [param JSONString];
    NSString *DESkey = [RedGiftEncry shareRedGiftEncry].DESkey;
    NSString *sendstr = [SecurityDES encrypt:str withKey:DESkey];

    NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:
                         [RedGiftEncry shareRedGiftEncry].RSAEncryedString,@"ks",
                         sendstr,@"loc",
                         nil];
    return dic;
}

+(NSString *)getCurrentEncryDesbyRSA:(NSString *)DESKey{
    CRSA *rsa = [CRSA shareInstance];
    [rsa createRSAPublicKey:RSA_PUBLIC_KEY];
    // RSA加密后的DES Key
    NSString *encryptDESKey = [rsa encryptByRsa:DESKey withKeyType:KeyTypePublic];
    return encryptDESKey;
}

+(RedGiftEncry * )shareRedGiftEncry{
    static dispatch_once_t Encrypred;
    static RedGiftEncry *currentUser;
    dispatch_once(&Encrypred, ^{
        currentUser = [[RedGiftEncry alloc] init];
        currentUser.DESkey = [SecurityDES getDESKey];
        currentUser.RSAEncryedString = [RedGiftEncry getCurrentEncryDesbyRSA:currentUser.DESkey];
    });
    return currentUser;
}

@end

什么是CRSA.h引入的是什么

OpenSSL库,OpenSSL 是一个安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用。

OC上实现RSA常用的库,值得注意的是引入这个库进来后要在 Build Setting的Header Search Path里面添加该库上的上一级目录进去,比如:$(PROJECT_DIR)/HexiShop/Base/Encry 不然编译不通过。

什么是JSONKit.h

iOS上效率较高的Json转换器,能够将Dic字典转化为String

什么是SecurityDES.h

封装好的一套DES对称加解密工具,主要调用其getDESKey这个方法生成随机8位DES密钥和进行加密

加密之类的事情我们引入的第三方库就已经帮我们做好了,剩下的就相当于堆积木组装起来就好了。
进行单例初始化后会一句话调用就搞定

[[RedGiftEncry shareRedGiftEncry] RedGiftEncry:(NSMutableDictionary *)param EncryType:(NSString *)EncryAppID];

但是关于效率和安全性来讲这样做的麻烦就大了

  1. 不同客户端生成的密钥A是不同的,难道每次服务器都要去做RSA解密吗?这样消耗太大,当然服务器可以存一个列表记录对应的密钥B的密钥A,然后进行处理,这样最好不过了。
  2. 为什么要把密钥存放在App本地,难道不担心被逆向破解吗?针对第二点确实是存在的比较大的安全隐患,可以改为每次通过接口从服务器获取,但是也可能中途被窃取,让中间人有机可乘,所以可以采用网络编程安全套接字的办法建立可靠传输后再传证书数据,不过还是会遭遇,防不乘防。

在没有HTTPS加密的时候确实还是挺危险的,安全也不是绝对的,只是相对的安全而已。

还是HTTPS更加的可靠,在应用层下面添加了SSL层进行加密后再进行下发,通信加密也不能被窃听,而且传输CA数字证书是服务器分发的,有两个重要作用:
https协议中身份认证的部分是由数字证书来完成的,证书由公钥、证书主体、数字签名等内容组成,在客户端发起SSL请求后,服务端会将数字证书发给客户端,客户端会对证书进行验证,并获取用于秘钥交换的非对称密钥。
参考:为什么要使用HTTPS代替HTTP
数字证书有两个作用:
身份授权。确保浏览器访问的网站是经过CA验证的可信任的网站。
分发公钥。每个数字证书都包含了注册者生成的公钥。在SSL握手时会通过certificate消息传输给客户端。
申请一个受信任的数字证书通常有如下流程:

终端实体(可以是一个终端硬件或者网站)生成公私钥和证书请求。
RA(证书注册及审核机构)检查实体的合法性。如果个人或者小网站,这一步不是必须的。
CA(证书签发机构)签发证书,发送给申请者。
证书更新到repository(负责数字证书及CRL内容存储和分发),终端后续从repository更新证书,查询证书状态等。