API网络数据安全

TCP/IP作为互联网使用的标准协议集,在设计之初就是建立在接入主机互相信任的前提下,缺乏对安全方面的考虑,并且为了保证网络的开放性,TCP/IP协议的内容是完全公开的。因此,只使用TCP/IP协议在互联网上传输的数据,实际上都是不安全的。

在SDK开发场景下,通常会在API设计时加入一些网络安全的措施,这里主要从数据防泄露、内容防篡改、身份放伪装、请求防重放几个方面分析如何保证API网络数据安全。

1 数据防泄露

为了保证数据的机密性,一般会对数据做加密操作,这样即便数据在传输时被抓取,也需要解密才能获取真实数据。而要加密就需要用到加密算法,下面按两种粗略的分类介绍下不同加密算法的特点,如何选择合适的加密算法,以及加密算法使用的密钥该如何管理。

1.1 公开加密与非公开加密算法

按照算法是否公开的特点,加密算法可分为公开算法和非公开算法。

公开加密算法

加密算法公开,密码的安全性基于密钥的安全;

非公开加密算法

加密算法不公开,只有开发人员知道,密码的安全性基于加密算法的安全;

建议

建议使用公开加密算法。

公开算法因为受全世界的密码学者研究,经受了很大的考验,加密强度有保障。而非公开算法除了作者之外基本上没人看过,加密的强度没有保障。一旦加密方式泄露,非公开加密算法需要做修改算法这种复杂操作来补救,而公开加密算法本来就是公开的,只要密钥不泄露就是安全的,即使密钥泄露也只需更换密钥的简单操作即可。

1.2 对称加密与非对称加密算法

按照密钥的特点,公开加密算法又可分为对称算法和非对称算法:

对称(私钥)加密算法

只有一个密钥,加密和解密使用同一个密钥。

特点:计算量小、速度快、密钥交换复杂(Diffie-Hellman密钥交换算法)。

常见的对称加密算法:DES,AES,TDEA,Blowfish,RC,IDEA。

非对称(公钥)加密算法:

有一对密钥,可公开的公钥与不可公开的私钥,用其中一个密钥对数据进行加密后,只有用对应的另一个密钥才能解密。

特点:计算量大,速度较慢,支持数字签名,密钥交换简单。

常见的非对称加密算法:RSA,Elgamal,Rabin,ECC,D-H。

建议

实际使用中通常采用非对称加密算法管理对称算法的密钥,然后用对称加密算法加密数据,这样我们就集成了两类加密算法的优点,既实现了加密速度快的优点,又实现了安全方便管理密钥的优点。

在这里插入图片描述

1.3 密钥管理

加密的安全性除了加密算法的选择外,很大程度上都依赖于密钥的安全。通常来讲,一个足够安全的密钥管理体系需要涵盖密钥的整个生命周期,通常包含生成、分发、验证、更新、存储、备份、销毁。

密钥生成

密钥生成可以通过在线或离线的协商方式实现,大部分采用随机过程或伪随机过程来生成密钥,这样可以保证密钥生成的不可预测。密钥应该足够长,密钥越长,破解难度就越大,当然,密钥过长也会导致运行速度变慢,应该根据实际需要的安全级别来选择,一般来说,RSA建议采用1024位,ECC建议采用160位,AES采用128位。

密钥分发

生成密钥后,通常需要将它发送给另外的成员,为了增强保密性,可以将密钥拆分成多个部分然后用不同的信道发送出去,也可以通过手工线下分发。在SDK开发中,手工分发一般用于非对称加密的公钥,对称加密的密钥则通过网络的形式分发,并且在网络上分发时发会使用非对称加密算法加密。

密钥验证

为了保证在密钥分发过程中接收密钥的正确,通常会在传输密钥时增加一些纠错位,当密钥在传输中发生错误时,能很容易就检查出来,并且根据需要决定是否重传密钥。

密钥更新

密钥使用时通常会设置一个密钥有效期,比如对于非对称加密算法,由于私钥一般放在服务端相对安全,因此有效期可以设长一些,比如1个月或1年不等,密钥过期后再直接生成一对即可。而对称加密中的密钥的有效期一般会很短,比如1天,一种比较容易的密钥更新方法就是从旧的密钥中通过单向函数产生新的密钥,双方使用同一个单向函数即可保证更新成相同的密钥,当然,由于SDK端的不安全性,还是建议每次都重新生成一个密钥并进行密钥分发。

密钥存储

对非对称加密来说,公钥由于本来就可以公开,因此对如何存储没什么讲究,私钥一般存储在离线的物理设备中,可以把密钥拆分成几部分并存储在不同的地方,此外,还可以用加密的方式对密钥进行加密存储。

密钥备份

密钥的备份的方式有密钥托管、秘密共享、秘密分割等方式。最简单的方式是将密钥交给独立的托管中心保管,一旦密钥丢失可以想托管中心索取。秘密分割、秘密共享则是把密钥分割成许多碎片,把这些碎片拼在一起或凑齐其中一部分就可以重现密钥。

密钥销毁

密钥替换之后,旧的密钥必须销毁。

2 内容防篡改

数据在网络的传输过程中,很有可能被拦截并对内容进行篡改,对于这种情况,通常在传输内容中增加特定哈希算法生成的hash值,用来校验内容是否被篡改过,以保证数据的完整性。

3.1 哈希函数

哈希函数也叫散列函数或摘要函数,它能把任意长度的输入转化为固定长度的输出,并且这种转换过程是不可逆的,常见的哈希函数有md4、md5、sha-1等等。

具体在做防篡改方案时,通常会在请求或响应的内容体中增加一个校验参数sign,为了增加破解的难度,校验参数一般不会只是简单地对内容进行哈希运算生成,而是使用一种被称为加盐哈希的操作。具体做法可以是在内容中增加一些别的参数,比如SDK开发场景中通常会由开发者平台生成一个appSecretKey,可以把这个key放入请求内容中的特定位置,然后在再用哈希函数生成hash值,这之后还可以根据需要多进行几次哈希操作,比如先用md5做哈希计算生成hash值,再把这个值当成盐放到下次的sha-1计算中等等。

接收端在接收到内容时使用同样的哈希操作计算sign值,并将两个sign值进行比对,如果不一样则说明内容被篡改过了。

下面是一个简单的例子,参数可以直接拼接在url后也可以放到请求body中:

http://127.0.0.1/index/Info?uid=123123&sign=80b886d71449cb33355d017893720666

3 身份防伪装

在网络通信中,通信双方的身份验证也是网络安全中非常重要的一环,它既可以保证网络通信双方的身份,又可以防止通过网络完成交易时,交易方宣称交易没发生过的抵赖行为,保证了通信双方身份的可鉴别和通信过程的不可抵赖。在SDK开发中,由于api接口是对外公开的,因此对客户端的身份校验一般不会很严格,主要是对服务端的身份验证。

3.1 Token身份验证

服务端为了防止接口的未授权调用,通常会生成一个用于标识客户端身份的token,客户端在调用接口时在请求头中添加token,服务端检查token是否有效,如果有效则说明客户端的身份可靠,可以返回响应数据,通常会对token设置一个有效期以防止token泄露后的长期非法调用。

3.2 数字签名

服务端一般通过数字签名的方式支持身份验证,数字签名是非对称加密算法的另一种用法,用私钥加密,用公钥解密,它可以提供和现实中亲笔签名相似的效果,在技术上和法律上都有保证。

数字签名与验证过程:

  1. 发送方用哈希函数从报文文本中生成一个hash值;
  2. 发送方用自己的私钥对这个hash值进行加密形成自己的数字签名;
  3. 发送方将数字签名和报文一起发送给接收方;
  4. 接收方收到报文后,用同样的哈希函数从原始报文中计算出hash值;
  5. 接收方再用发送方的公钥来对报文附加的数字签名进行解密得出另一个hash值;
  6. 如果两个hash值相同,那么接收方就能确认该数字签名是发送方的;
    在这里插入图片描述

4 请求防重放

即使传输的数据是经过加密的,窃听者无法得到数据的准确定义,但从请求的地址分析出这些数据的作用之后,可以通过原封不动地多次发送这条请求进行攻击,就拿最简单的数据入库操作,如果API接口没有做对应的安全防护,将可能造成多次入库的严重后果。

为了避免这种情况,通常会在请求中增加一些用于校验的参数,比如时间戳、随机数、流水号等等,下面简单介绍一下这几种方式的特点,以及常用方案。

4.1 加时间戳

在请求中增加一个时间戳,服务端将时间戳跟当前时间对比,如果时间差大于一定值(比如1分钟),则可以认为该请求失效。这种方式无法防止在指定时间差内的重放攻击,比如时间差是1分钟的话,那么只需要在1分钟内完成重放攻击即可。

4.2 加随机数

在请求中增加一个随机数,服务端检查缓存中是否有相同的随机数,如果有则认为是无效请求,如果没有则将其加入缓存。这种方式的问题在于,服务端不可能缓存所有请求的随机数,只能缓存一部分,如果重放攻击内包含的随机数刚好被清除了,则依然能被攻击。

4.3 加流水号

在请求中增加一个递增的流水号,服务端如果收到的流水号不是连续递增的,就认为是无效请求。这种方式的缺点在于流水号的变化太过单调了,很容易就能被识别出来并做对应的修改。

4.4 时间戳+随机数

常用的方案是把时间戳和随机数配合使用,给每次请求都增加一个当前时间的时间戳timestamp,和一个随机数nonce。服务端收到请求时,先检查时间戳是否超时,如果超时则认为是无效请求,如果没超时再检查缓存中是否有相同的nonce,如果有则认为是无效请求,如果没有则将其加入缓存,服务端只需要缓存超时时间内的nonce记录即可。

下面是一个简单的例子,参数可以直接拼接在url后也可以放到请求body中,这里也可以直接用sign替代nonce所起的作用。

http://127.0.0.1/index/Info?uid=123123&timestamp=1480822356&nonce=8765890c21&sign=80b886d71449cb33355d017893720666

5 使用Https

前面介绍的这些网络安全的相关手段,如果实际开发中要严格按照上面的标准实现的话,还是需要花费一些时间的,那么有没有一种快速简单的方式来实现上面提到的那些功能呢,答案是有的,那就是直接使用Https。

5.1 SSL/TLS

Https实际上是由Http+SSL组成,SSL是Netscape公司研发的用于保障数据在互联网上安全传输的协议,SSL在更新到3.0时,IETF(互联网工程任务组)对SSL3.0进行了标准化,添加了少数机制,并将其更名为TLS。

SSL/TLS建立安全通信的过程大概可以分为三步:

  1. 对等协商支持的密钥算法;
  2. 基于公钥加密的对称密钥交换,基于证书的身份认证;
  3. 基于对称加密的数据传输保密

5.2 数字证书

使用Https时,需要用到数字证书,数字证书的原理其实还是前面说到的数字签名,一般数字证书都是由CA机构用私钥签发的,当然也有企业自己用私钥签发的数字证书,只是这种证书默认是不被信任的,使用数字证书可以有效地防止参数篡改和身份伪装。

数字证书的大致生成过程如下图:
在这里插入图片描述

数字证书的验证过程大致如下图:
在这里插入图片描述

在SDK开发中,使用CA颁发颁发的证书和使用自生成的证书差别并不大,主要区别在于,如果使用CA颁发的证书,只需在SDK中使用系统自带的信任证书库验证即可(系统默认内置CA机构根证书),如果使用自生成的证书,则需要在SDK中导入证书或公钥用于证书验证过程。

5.3 单向与双向认证

Https支持单向认证和双向认证,两者区别如下:

单向验证

客户端需要验证服务器的身份,服务端不需要验证客户端身份。

双向验证

客户端需要验证服务器身份,服务端也需要验证客户端身份。

使用单向验证还是双向验证,通常是由服务端提供的服务决定的。一般情况下服务器是对所有客户端开放的,所以默认的配置是单向验证。如果要限制访问的客户端,则需要在服务端开启双向验证。

6 API范例

这里简单描述使用Http协议下的一个安全API范例。
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值