网络知识 娱乐 报文签名和敏感数据加密(前后端应用交互)

报文签名和敏感数据加密(前后端应用交互)

算法要求

对称加密算法SM4,非对称加密算法SM2,哈希算法SM3,签名算法SM2。

GMSignatureSpi#sha256WithSM2、GMSignatureSpi#sm3WithSM2

1. 秘钥建立

所有接入API服务网关的接入方密钥对均按如下要求建立。

a) 根据实际业务场景,接入方可分为发送方或接收方。

b) API网关应用线上(Web界面)或者线下分发秘钥对,确保秘钥的生成规律不能为 其他方所获知。

c) 接入方可根据自身需求,定期更新接入方密钥对。

d) 秘钥应采用对称国密算法 。

  1. 客户端向服务器端申请RSA公钥;服务器生成一个RSA秘钥对,将公钥发送给客户端。我们起名为「Server公钥」
  2. 客户端收到服务器给出的「Server公钥」,客户端生成自己的RSA秘钥对,我们起名为「Client公钥」,客户端使用「Server公钥」去加密自己的「Client公钥」,发送给服务器
  3. 服务器收到客户端的请求,使用「Server私钥」解密得到「Client公钥」
  4. 服务器生成一个「AES秘钥」,使用「Client公钥」加密「AES秘钥」发送给客户端
  5. 客户端使用「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. 请问在上面的这个流程中,如果在第一步客户端向浏览器请求公钥因为是走明文的,如果这时候服务端返回的公钥被中间人替换掉了,中间人把自己的公钥给到前端,这样后续的请求是不是就就不再安全了?这样的话这个流程是不是可以认为不算是安全的呢?

答案1:关于中间人攻击,就需要引入第三方来解决信任问题,https 的 ssl 证书就可以,比如我请求www.renfei.net,你说你(中间人)是www.renfei.net,那你就出具 ssl 证书证明你是,如果证书对不上,那我就不信任你,不会继续交换秘钥了。申请 ssl 证书的时候会审核域名所有权,不是随便就能申请的,所以假冒的服务器端(中间人)是无法出具证书证明自己是www.renfei.net的。

  1. 请问客户端和服务端之间如果全程都是https的话,那还还有必要对信息进行加密吗?

我觉得还是有必要的,首先明确一点https也是可以被抓包解密的,前提是拿到设备。分享一次我的事迹,我曾经抓包支付宝APP,想改数据包里的内容,虽然是https,依然能抓取并拿到里面的内容,但是支付宝在传输的时候还是加密了,也就是说 https 里面还是加密的内容,这就造成我无法修改数据包,除非我反编译支付宝的APP,拿到加密算法,再伪造APP请求。

  1. 您好,对于秘钥交换逻辑有个问题,为何我前端还要在生成一次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