接口通讯及认证签名

统一平台和客户端的通讯采用JSON格式,通讯双方发送和接收数据都必须进行签名和验签,签名串保存在sign变量名下,签名算法描述如下:

加签算法
将请求参数以参数名按字典序排序(升序,即A在首位),然后将参数值连接成字符串,接着使用通信密码对其进行AES加密,最后对加密结果进行sha256运算得出签名串

签名算法代码示例:
(PHP语言版)

  /**
   * 得到签名串
   *
   * @param array $order 发送到统一平台的参数信息数组
   * @param null  $key   加密密钥 一般不用传递
   *
   * @return string
   */
  public function getSign($order = [], $key = NULL) {
    unset($order['sign']);
    ksort($order);
    if (empty($key)) {
      $key = $this->config->get('key'); //取回通讯密码
    }
    $str = implode('', $order); //这里用空连接符也意在避免参数存在但无值时签名不同的问题
    $str = (new AES())->aesEncrypt($str, $key);
    $sign = hash('sha256', $str);
    return $sign;
  }

验证签名如下:

    //这里假设$jsonArr是响应json解码后的数组
    //其必须是完整的,否则验证不会成功,因为签名串保护所有数据
    if (!isset($jsonArr['sign']) || $jsonArr['sign'] != $this->getSign($jsonArr)) {
        return false; //响应签名错误
      }

当签名验证错误时,必须拒绝后续处理

AES加密算法如下:

<?php

/**
 * AES加密类, 加密算法aes-128-cbc,分组长度128比特  加密模式为CBC
 */
class AES{

  /**
   * 使用AES加密算法加密文本
   *
   * @param $plainText String 明文 不限制位数 即便是空字符""都行
   * @param $key       String 对称密钥 不限制位数 即便是空字符""都行,但建议在16个字符
   *
   * @return string base64转码后的密文
   */
  public function aesEncrypt($plainText, $key) {
    $iv = substr(hash('sha256', $key), 0, 16); //产生初始化加密向量
    return  openssl_encrypt($plainText, 'aes-128-cbc', $key, 0, $iv); 
  }

  /**
   * AES解密
   *
   * @param $cipherText String 密文
   * @param $key        String 对称密钥
   *
   * @return string
   */
  public function aesDecrypt($cipherText, $key) {
    $iv = substr(hash('sha256', $key), 0, 16);
    return openssl_decrypt($cipherText, 'aes-128-cbc', $key, 0, $iv);
  }

}

 以上加密算法结果示例:

明文:$str='未来很美科技';
密码:$key='admin';
密文:‘CUasyTzO1iEQg9+iZJvE+6O+B+x1JeR34LeXikbnnYg=’
注意:以上不带引号

即:
$str='未来很美科技';
$key='admin';
echo $str = (new AES())->aesEncrypt($str, $key);
输出: CUasyTzO1iEQg9+iZJvE+6O+B+x1JeR34LeXikbnnYg=