算法要求
对称加密算法SM4,非对称加密算法SM2,哈希算法SM3,签名算法SM2。
GMSignatureSpi#sha256WithSM2、GMSignatureSpi#sm3WithSM2
1. 秘钥建立
所有接入API服务网关的接入方密钥对均按如下要求建立。
a) 根据实际业务场景,接入方可分为发送方或接收方。
b) API网关应用线上(Web界面)或者线下分发秘钥对,确保秘钥的生成规律不能为 其他方所获知。
c) 接入方可根据自身需求,定期更新接入方密钥对。
d) 秘钥应采用对称国密算法 。
- 客户端向服务器端申请RSA公钥;服务器生成一个RSA秘钥对,将公钥发送给客户端。我们起名为「Server公钥」
- 客户端收到服务器给出的「Server公钥」,客户端生成自己的RSA秘钥对,我们起名为「Client公钥」,客户端使用「Server公钥」去加密自己的「Client公钥」,发送给服务器
- 服务器收到客户端的请求,使用「Server私钥」解密得到「Client公钥」
- 服务器生成一个「AES秘钥」,使用「Client公钥」加密「AES秘钥」发送给客户端
- 客户端使用「Client私钥」解密得到「AES秘钥」
后续双方的交互使用「AES秘钥」进行加解密,秘钥交换流程完成。
2. API网关安全(应用交互)
而不同场景的API网关对API调用方的安全要求等级也会不同,通常对外网的安全要求会比内网要高。 最终可以形成如下这张API资产访问清单。
服务对象 | 使用环境 | 网关场景 | 安全要求 |
合作机构 | 外网 | 2B-API | 高 |
外部用户 | 外网 | 2C-API | 高 |
内部用户 | 外网/内网 | 2G-API | 中 |
内部应用 | 内网 | 2S-API | 中 |
API安全治理的实践思路
用过API网关的同学都知道,它的核心能力主要是流量路由转发及分流。所以,缺省情况下,它并不会启用安全控制 能力,因此,你需要根据实际使用场景,选择开启不同的安全控制能力。
API网关一般都支持如下安全控制能力
控制能力 | 防范场景 |
请求限流 | 防止攻击者频繁请求API,导致资源耗尽无法正常响应 |
签名验签 | 防止攻击者伪造身份请求API,或篡改请求报文数据 |
加密解密 | 防止攻击者通过非法手段拦截报文后,获取敏感数据 |
防重请求 | 防止攻击者通过非法手段获取报文后,重复请求API |
用户鉴权 | 防止攻击者在匿名情况下请求API,获取数据或攻击程序 |
访问约束 | 防止攻击者利用漏洞,采用不安全的方法或跨域请求API |
前文有提到过, 不同场景的API网关对API调用方的安全要求也会不同。 所以,并不是说所有API网关都要实现或开启以上控制能力,根据实践使用经验,参考如下
控制能力 | 2B网关 | 2C网关 | 2G网关 | 2S网关 |
请求限流 | 必须 | 必须 | 可选 | 可选 |
签名验签 | 必须 | *无需 | *无需 | 可选 |
加密解密 | 必须 | *可选 | *可选 | 可选 |
防重请求 | 必须 | *可选 | *可选 | 可选 |
用户鉴权 | 必须 | 必须 | 必须 | 可选 |
访问约束 | 必须 | 必须 | 必须 | 必须 |
注:*代表在移动端环境下为必须。
可以发现,面向公网的API安全控制要求要远远高于内网。所以说, 在API安全治理的优先级上,建议采取先外后内的实践策略** ,毕竟面向公网的API处在一个完全开放的环境下,它更容易受到致命性的攻击。
以下内容从这几种常见的安全类型。
2.1 报文的签名机制
报文签名用来验证通讯报文的完整性和防篡改校验(敏感信息(比如身份信息、银行信息等)不在此处处理)。 采用App Secret Key + HMAC方式。
这种方式的主要特征有 1)引入App Secret Key来标识API调用者身份,2)引入HMAC防止消息被篡改。
HMAC:为了防止消息在传递过程中被篡改,引入MAC( Message Authentication Code),这是一种给消息签名的技术。在实现中,首先对消息进行MAC,得到一个摘要字串。接收方得到消息后,进行同样的计算,然后比较这两个MAC字符串,如果一致,则表明没有被修改过。而HMAC( Hash-based Authenticsation Code),指的是,利用Hash技术完成这一过程,比如使用SHA-256算法。
App Secret Key:抽象出一个应用的概念,用来标识调用者的身份,每一个应用可以生成一个或多个Secret Id/Key。API所有者只给有权限的API访问者颁发相应的Secret Id/Key。API访问者请求时带上应用标识,服务端就可以识别调用者的信息,并进行更细粒度的权限管理。
HMAC+App Secret Key:API访问者发送请求时,可以对应用标识使用HMAC计算出摘要字串,在HTTP头的 sign字段中放入相关信息发送到服务端。服务端会查询相关应用的信息,并验证签名,验证通过,返回200,否则返回401。
网关需要验证API调用方上送的签名是否正确;API调用方收到应答,也需要验证签名是否正确,如果API调用方未正确验证签名,存在潜在的风险,API调用方自行承担因此而产生的所有损失。
2.1.1 签名机制
接入系统调用该类函数,对签名串使用SM3算法做摘要,将摘要转换为十六进制字符串后,再使用各自私钥对摘要做签名,并对结果进行Base64编码。最后,将生成的签名赋值给signature,填入到HTTP 报文头。
公共请求参数(HTTP头信息)
app_key | String | 是 | 应用的app_key |
signature | String | 是 | 签名 |
X-Ca-Timestamp | String | 是 | 时间戳,格式为yyyy-MM-dd HH:mm:ss,例如:2011-06-16 13:23:30。时间戳,格式为yyyy-MM-dd HH:mm:ss,例如:2011-06-16 13:23:30。API服务端允许客户端请求时间误差为10分钟 |
2.1.2 验签机制
对于报文的验签处理机制如下:
首先,将报文体数据SM3算法做摘要,将摘要转换为十六进制字符串后,再使用对方公钥对摘要和报文中的签名信息做签名验证操作。
2.2 防重放攻击
在API网关的签名中,提供X-Ca-Timestamp、X-Ca-Nonce两个可选HEADER,客户端调用API时一起使用这两个参数,可以达到防止重放攻击的目的。
原理
- 请求所有的内容都被加入签名计算,所以请求的任何修改,都会造成签名失败。不修改内容X-Ca-Timestamp:发起请求的时间,可以取自机器的本地实现。当API网关收到请求时,会校验这个参数的有效性,误差不超过15分钟。X-Ca-Nonce:这个是请求的唯一标识,一般使用UUID来标识。API网关收到这个参数后会校验这个参数的有效性,同样的值,15分内只能被使用一次。
2.3敏感数据
敏感信息(比如身份信息、银行信息等)采用一次一密的方案,敏感信息加密密钥仅在使用时生成,且每个密钥仅使用一次,通过网关给出的公钥加密后Base64出现在报文中。。
在应用系统接入API网关模式下,敏感信息传输时加密与解密流程概要描述如下。
a) 发送方通过应用系统方式向API网关传输敏感信息的场景:
1) 发送方生成敏感信息密钥;
2) 发送方使用敏感信息密钥 对敏感信息进行加密;
3) 发送方使用API网关的公钥 ,对敏感信息密钥进行加密;
4) 发送方使用自身的私钥,进行数字签名;
5) 发送方将加密后的敏感信息密钥密文、使用对称秘钥加密后的敏感信息密文以及发送方数字签名发送给API网关;
6) API网关使用发送方的公钥,进行验签;
8) API网关使用自身的私钥,对加密后的敏感信息密钥密钥进行解密;
9)API网关使用敏感信息密钥明文,对敏感信息解密得到明文。
3. 用户密码传输(浏览器)
TLS 能保证的只是传输过程中第三方抓包看到的是密文,但防不了在客户端和服务端截取数据的黑客,要在服务端截取数据比较难,但在客户端截取还是比较容易的。最简单的,你在浏览器访问知乎、京东等知名网站并用抓包工具抓取请求,就会发现,虽然是HTTPS请求,但看到的数据并非密文,而是明文的。对HTTPS的攻击手段也不少,比如降级攻击、中间人攻击等。
所以,只用HTTPS做防护是不够的,我们还需要对密码进行非对称加密。非对称加密算法主要有:RSA ECC
要怎么做呢?慢哈希+Slat(盐)。Slat的存在主要是为了让破解密码的成本增加。建议每个用户的Salt值不同(最好对不同用户的密码随机生成不同的salt,salt库和密码库分离开),这样就没办法用彩虹表进行批量破解。再加上慢哈,暴力破解的成本也呈指数级增加,何为慢哈希?所谓慢哈希,其实就是指执行这个哈希函数非常慢,这样暴力破解需要枚举遍历所有可能结果时,就需要花上非常非常长的时间。慢哈希算法主要有: Argon2、Scrypt、Bcrypt、PBKDF2
TLS是基础,密码再进行单独加密,加密算法要用非对称加密;
如果用户登录时密码错误,那错误提示语不要直接提示“密码错误”,只需要给出一个大概的提示,比如“用户名或密码错误”;
密码错误次数连续超过N次,比如6次,则将用户锁定一段时间:
数据库用慢哈希+Salt的方案进行存储,不同用户用不同Salt值。
增加多重校验,比如登录设备检测、指纹识别、人脸识别、手机验证码等
4 . 问题
- 请问在上面的这个流程中,如果在第一步客户端向浏览器请求公钥因为是走明文的,如果这时候服务端返回的公钥被中间人替换掉了,中间人把自己的公钥给到前端,这样后续的请求是不是就就不再安全了?这样的话这个流程是不是可以认为不算是安全的呢?
答案1:关于中间人攻击,就需要引入第三方来解决信任问题,https 的 ssl 证书就可以,比如我请求www.renfei.net,你说你(中间人)是www.renfei.net,那你就出具 ssl 证书证明你是,如果证书对不上,那我就不信任你,不会继续交换秘钥了。申请 ssl 证书的时候会审核域名所有权,不是随便就能申请的,所以假冒的服务器端(中间人)是无法出具证书证明自己是www.renfei.net的。
- 请问客户端和服务端之间如果全程都是https的话,那还还有必要对信息进行加密吗?
我觉得还是有必要的,首先明确一点https也是可以被抓包解密的,前提是拿到设备。分享一次我的事迹,我曾经抓包支付宝APP,想改数据包里的内容,虽然是https,依然能抓取并拿到里面的内容,但是支付宝在传输的时候还是加密了,也就是说 https 里面还是加密的内容,这就造成我无法修改数据包,除非我反编译支付宝的APP,拿到加密算法,再伪造APP请求。
- 您好,对于秘钥交换逻辑有个问题,为何我前端还要在生成一次RSA秘钥给到后端公钥,然后由后端生成AES对称秘钥给前端呢,如果是前端生成AES对象秘钥然后通过后端的公钥加密给到后端,这样会有什么风险吗? 一、客户端向服务器端申请RSA公钥;服务器生成一个RSA秘钥对,将公钥发送给客户端。我们起名为「Server公钥」 二、客户端收到服务器给出的「Server公钥」,客户端生成一个「AES秘钥」,客户端使用「Server公钥」去加密自己的「AES秘钥」,发送给服务器 三、服务器客户端使用「Server私钥」解密客户端发送的「AES秘钥」进行存储
您的逻辑上是没问题的,我是根据行业习惯来的,不信任客户端产生的东西,或者说接口传进来的我都不信任,如果由客户端生成AES的话,后端还需要判断这个秘钥的强度,增加了后端的工作量,不如直接不信任客户端,都由后端决定用什么密码,什么时候下发新的密码
5. 参考文档
https://www.renfei.net/posts/1003346
https://cloud.tencent.com/developer/article/1925022
版权声明:内容来源于互联网和用户投稿 如有侵权请联系删除