优雅实现接口的签名机制(一)

498 阅读6分钟

前言

有没有想过签名是什么?为什么是先摘要再加密?明明摘要可以加盐值来保证完整性,为什么还要再加密呢?为什么不先签名再摘要呢?

先说结论:

  1. 签名机制指的是对客户端通过摘要和对称(或者非对称)加密算法对请求API的参数进行签名,服务端进行验证的过程;服务端验证是先使用摘要算法计算接收数据的进行摘要得到Q,然后再使用公钥解密签名得到B,再判断A和B是否相等,不相等则代表客户端请求内容被篡改或者重放或者客户端请求参数错误。
  2. 摘要能搞一定程度上保证数据完整性?,但是因为数据和摘要都存在篡改风险,攻击者在篡改数据时也可以篡改摘要,所以配合加密算法债能验证验证完整性?(设存在一个中间攻击者,能够解开待验证信息和消息验证码。由于单向散列函数是公开的算法,中间攻击者就可以篡改待验证信息,重新生成消息验证码?)
  3. 摘要算法加盐值能提高安全性?但是不够保持完整性,所以还要加密?
  4. 如果先签名,再摘要,对原始数据直接签名,时间过长,效率不高?

这里的签名机制用的对称加密,接收方与发送方共享密钥,是通过aksk机制实现。我们通过aksk来验证某个请求的发送者身份。ak标识用户,sk是验证用户的密钥,用户用户加密认证字符和服务端验证认证字符串的密钥,其必须保密。

签名计算方式

最后签名值放到请求头的Authorization字段中,格式为:

       SignedHeaders=<SignedHeaders> ,Signature=<Signature>

  1. SignedHeaders为签名请求头。

  2. Signature按照以下伪代码计算签名值:

    Signature = HexEncode(SecretMethod(HexEncode(Hash(raw), secret, signAlgorithm)

    • 其中text可以未经任何处理的原始text,
    • HexEncode:小写返回的base16编码
    • SecretMethod: 签名算法
    • Text: 带签名字符串,以UTF-8编码
    • Secret: 签名密钥,二进制数据
    • signAlgorithm:签名算法
    • Hash: hash摘要算法

动手实现接口的签名

已经实现,放到二中

签名相关

签名协议

待补充

签名算法

计算签名时实际用的签名算法,可以是对称或非对称加密算法

摘要函数

不可逆,所以可以的中实现数据的完整性,也可以用来对敏感信息进行加密对请求负载进行签名;

Java常用的几种加密和解密方式 - 掘金 (juejin.cn)

加密、摘要、签名、证书,一次说明白! - 掘金 (juejin.cn)

加密技术科普 - 掘金 (juejin.cn)

编码相关

请求编码

请求及返回结果都使用UTF-8字符进行编码

规范化

我们在规范化需要加密的字符串时,可以按照如下规则:

  • 统一转换为小写字符
  • 去除首位空格
  • 字符代码顺序排序
  • 字符之间用冒号(:)拼接

url encode编码

RFC3986 协议规定 URL 只允许包含以下四种字符:

1、英文字母(a-zA-Z)

2、数字(0-9)

3、-_.~ 4个特殊字符

4、所有保留字符,RFC3986 中指定了以下字符为保留字符(英文字符): ! * ' ( ) ; : @ & = + $ , / ? # [ ]

其中保留字符会被编码为%xx(16进制),其中xx就是这个字节对应的hex编码。  Jdk的urlencoder

percent encode 编码

规则如下:

  1. 字符AZ、az、0~9以及字符-_.~不编码。
  2. 其他字符编码成%XY的格式,其中XY是字符对应ASCII码的16进制。示例:半角双引号(")对应%22
  3. 扩展的UTF-8字符,编码成%XY%ZA…的格式。
  4. 空格( )编码成%20,而不是加号(+)。该编码方式与application/x-www-form-urlencodedMIME格式编码算法相似,但又有所不同。

如果您使用的是Java标准库中的java.net.URLEncoder,可以先用标准库中percentEncode编码,随后将编码后的字符中加号(+)替换为%20、星号(*)替换为%2A%7E替换为波浪号(~),即可得到上述规则描述的编码字符串

阿里云的percent编码方式

base64 encode 编码

base64编码,它将字节数据中的每6个bit使用字母(a-zA-Z)、数字(0-9)、+、/总共64个字符等效表示,故每3个字节(8bit)会被编码为4个base64中的字符。  由于数据中的字节数不一定是3的整数倍,当字节数对3求模后,多1个字节时,那个字节会被编码为2个字符加2个=号(填充字符),多2个字节时,这2个字节会被编码为3个字符加1个=号(填充字符),刚好整除时,则不需要=号填充

链接:juejin.cn/post/700631…

base16编码

它将字节数据中的每4个bit使用数字(0-9)、字母(A-F)共16个字符等效表示

Hex编码

十六进制编码,即base16;;

数字签名可以认证数据的来源?

因为数字签名是,请求方先摘要再用非对称加密的私钥进行加密,而接收方是用从请求方获取到的公钥进行解密,如果能成功验证数字签名,可以说明请求来自合法的发送方。

加密相关

高级加密标准 —— AES

高级加密标准(Advanced Encryption Standard, AES),又称 Rijndael [rain-dahl]加密法,是目前最流行的对称加密算法之一。

    相对于 DES 算法,AES 算法的主要优点如下:

  • 1 、密钥长度更大: 密钥长度最小为 12 bit,最大为 256 bit。用穷举法难以破解;

  • 2 、使用 WTS 设计策略,可对抗差分和线性密码分析;

  • 3 、计算性能高: 计算和内存开销低,适用于受限设备。

链接:juejin.cn/post/699554…

AES 是高级加密标准,是 DES 的增强版,比 DES 的加密强度更高。它由四个不同阶段组成:字节代替,行移位,列混淆,轮密钥加,每个阶段是可逆的,将所有的四个阶段求逆,很容易证明解密函数可以恢复明文。

Java常用的几种加密和解密方式 - 掘金 (juejin.cn)

HMAC(Hash Message Authentication Code)散列消息鉴别码

Java常用的几种加密和解密方式 - 掘金 (juejin.cn)

HMAC是一种使用单向散列函数来构造消息认证码的方法,其中HMAC中的H就是Hash的意思。使用一个密钥生成一个固定大小的小数据块,即MAC,并将其加入到消息中,然后传输,接收方利用与发送方共享的密钥进行鉴别认证。是一种对称加密方法。