移动客户端与服务器端安全通信方案

公钥加密私钥解密是密送,保证消息即使公开也只有私钥持有者能读懂。

私钥加密公钥解密是签名,保证消息来源是私钥持有者。

数字签名只能验证数据的完整性,数据本身是否加密不属于数字签名的控制范围

CS

C客户端,S服务器端

在客户端软件发布前,客户端保存一个公钥,服务器保存一个私钥;客服端and服务器都保存一个固态key : solid_key

步骤1:

客户端随机生成一个对称密钥,称为动态key : dynamic_key,使用公钥加密内容(dynamic_key+账户+密码+其他需要的参数)。发送给服务器

步骤2:

服务器收到后使用私钥解密,并验证用户和密码是否正确,正确的话保存此dynamic_key在用户的信息中(如果原先已经有了dynamic_key就替换掉旧的); 返回数据:包括客户端登录成功的信息,返回一个Token(令牌,以后见牌如见人)和其他需要返回的参数(传输过程中不携带uid,用token标识用户唯一身份,更安全)。

步骤3:

使用本地保存的dynamic_key解密得到token和其他参数。 安全传输准备工作做完了。

步骤4:

每次传输数据对于加密的内容一律使用dynamic_key进行加密,按照协商好的签名规则进行签名signature(需要dynamic_key参与到签名规则中,以保障安全),并附以明文参数token、明文参数signature、密文参数params这三部分,然后把此内容发送给服务器。

signature = sha1(rawData + dynamic_key),服务器利用用户对应的 dynamic_key 使用相同的算法计算出签名 signature2 ,比对 signature 与 signature2 即可校验数据的完整性。 (貌似在数据全部加密的情况下,不需要签名的)

步骤5:

根据token找到保存的dynamic_key,然后进行解密(dynamic_key仅仅用来解密,对于解密的内容无法验证),然后根据签名规则验证签名;查看token是否匹配,如果匹配的话那么此次请求就是有效的,否则无效,需要重新登录;如果验证签名失败,直接返回错误。

更新公钥通知服务

服务器端首先需要用原来的私钥签名,客服端有原来的公钥验证签名,如果签名通过,客服端方可更新公钥;签名不通过,需要重新下载最新客户端安装包(包含新的公钥);

如果被网络截获,还需要知道固态key,才能够修改客户端本地公钥

image

优点:

安全性,除非入侵服务器拿到私钥,或者破解久经考验的非对称加解密算法,没有其他办法大规模攻破,相比其他单纯使用对称加密和非对称加密方法效果都要好。

缺点:

用户第一次握手验证时使用非对称加密的内容,服务器非对称解密消耗资源比较多,如果攻击者发送大量此类信息,容易导致服务器DDoS攻击。个人觉得暂时无法从根本上避免这个问题的发生,只能够加上一些措施增加其难度,从而过滤掉一部分攻击者,具体措施有很多种,比如自己软件写个加密算法,服务器会根据解密算法进行计算从而验证是否有效,再比如android的话把这些算法写在jni层,增加反编译破解的难度。

其他

下表解决“根据token获取对应用户uid”在redis中如果做持久存储的话,token失效无法被有效清除,导致占用内存的风险;

CREATE TABLE `lee_user_token` (
  `uid` int(11) NOT NULL DEFAULT '0' COMMENT '用户UID',
  `token` char(36) NOT NULL COMMENT 'uuid 生产的36位字符串',
  PRIMARY KEY (`uid`),
  UNIQUE KEY `i_token` (`token`,`uid`) USING BTREE
) ENGINE=MEMORY DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='这里只是存储 token 与 uid 的映射关系,不做登录过期有效性判断';

参考信息:

转载于:https://my.oschina.net/leeyisoft/blog/1828736

猜你喜欢

转载自blog.csdn.net/weixin_33758863/article/details/92059105