消息签名和签名验证

为防止中间人攻击,发送者必须对请求和响应消息进行签名,接收者必须验证签名。

ZOLOZ 服务强制性验证每条请求消息的签名,因此商户必须正确对请求进行签名。ZOLOZ 服务同时也对响应消息进行签名,但商户可自行决定是否验证响应消息签名。ZOLOZ 仍强烈建议商户验证所有响应消息签名。

消息签名

消息签名流程

下图展示了从商户角度如何进行请求消息签名,以及从ZOLOZ 服务角度如何进行响应消息签名。

消息签名活动图.png

图 1. 消息签名活动图

消息签名步骤

消息签名步骤如下:

1. 获取私钥

消息签名必须使用私钥。

  • 对于请求消息,商户端必须生成一个 RSA 2048 密钥对。生成的密钥对包含一个私钥。商户可使用该私钥对请求消息进行签名。
  • 对于响应消息,商户账户创建账号时,ZOLOZ 系统会生成一个 RSA 2048 密钥对。生成的密钥对对于每个商户都是唯一的,并且包含一个私钥。ZOLOZ 服务可使用该私钥对响应消息进行签名。

2. 构建待签名内容

待签名内容是由若干元素组成的字符串,请求消息和响应消息各有不同内容。

请求消息

商户待签名内容字符串构建格式如下:

copy
<Request Method> <Request URI>
<Client ID>.<Request Time>.<Request Body>

因此,构建待签名内容字符串须按以下顺序连接各元素字符串:

    1. 请求方法
    2. 空格符 (" ")
    3. 请求 URI
    4. 换行符 ("\n")
    5. 客户端 ID
    6. 点字符 (".")
    7. 设置 Request-Time header 字段的请求时间
    8. 点字符 (".")
    9. 请求正文

以下是一个商户待签名内容字符串的示例:

copy
POST /api/v1/zoloz/authentication/test
2089012345678900.2020-01-01T08:00:00+0800.{
  "title": "hello",
  "description": "just for demonstration."
}
响应消息

ZOLOZ 服务待签名内容字符串与商户待验证内容字符串相同。有关更多信息,请参见此文中的 构建待验证内容(响应消息)

3. 计算签名

计算签名公式:

copy
SIGNATURE=base64urlsafe_encode(sha256withrsa_sign($CONTENT_TO_BE_SIGNED, $PRIVATE_KEY))

计算签名的方法如下:

  • sha256withrsa_sign:该方法为提供的内容生成数字签名。有关更多信息,请参见 sha256withrsa_sign
  • base64urlsafe_encode:该方法为生成的数字签名进行编码。有关更多信息,请参见 base64urlsafe_encode

输入参数:

输出参数:

  • SIGNATURE:最终生成的签名字符串。

4. header 中配置签名

HTTP request header 或者 HTTP response header Signature 字段中生成的签名字符串,格式如下:

copy
Signature: algorithm=RSA256, signature=<SIGNATURE>

签名验证

签名验证流程

下图展示了从 ZOLOZ 服务角度如何进行请求消息签名验证,以及从商户角度如何进行响应消息签名验证。

签名验证活动图.png

图 2. 签名验证活动图

签名验证步骤

签名验证步骤如下:

1. 获取公钥

验证签名必须使用公钥。

  • 对于请求消息,ZOLOZ 服务使用的公钥来自商户生成的 RSA 2048 密钥对。在发送任何请求之前,必须先在 ZOLOZ 系统中注册公钥。 ZOLOZ 服务可使用已注册的公钥来验证商户发送的每个请求签名。
  • 对于响应消息,商户必须获得 ZOLOZ 服务提供的公钥。商户创建账号时,ZOLOZ 系统会生成一个 RSA 2048 密钥对,含有公钥。商户可使用该公钥验证从 ZOLOZ 返回的每个响应签名。

有关如何在 ZOLOZ 系统中注册请求公钥、或从 ZOLOZ 系统获取响应公钥的更多信息,请参见 获取 API 凭证

2. 构建待验证内容

待验证内容是由若干元素组成的字符串,请求消息和响应消息各有不同内容。

请求消息

ZOLOZ 服务待验证内容字符串与商户签名内容字符串相同。有关更多信息,请参见此文中的 构建待签名内容 (请求消息)

响应消息

商户待验证内容字符串构建格式如下:

copy
<Request Method> <Request URI>
<Client ID>.<Response Time>.<Response Body>

因此,构建待验证内容字符串须按以下顺序连接各元素字符串:

    1. 请求方法
    2. 空格符 (" ")
    3. 请求 URI
    4. 换行符 ("\n")
    5. 客户端 ID
    6. 点字符 (".")
    7. 设置 Response-Time header 字段的响应时间
    8. 点字符 (".")
    9. 响应正文

以下是一个待验证内容字符串的示例:

copy
POST /api/v1/zoloz/authentication/test
2089012345678900.2020-01-01T08:00:01+0800.{
  "title": "hello",
  "description": "just for demonstration."
}

3. header 中提取签名

HTTP request header 或者 HTTP response header Signature 字段中提取签名。

copy
Signature: algorithm=RSA256, signature=<SIGNATURE_TO_BE_EXTRACTED>

4. 验证签名

检查提取的签名是否匹配待验证内容字符串的公式:

copy
IS_SIGNATURE_VALID=sha256withrsa_verify($CONTENT_TO_BE_VALIDATED, base64urlsafe_decode($SIGNATURE), $PUBLIC_KEY))

验证签名方法:

  • base64urlsafe_decode:用于解码步骤 3 中提取的签名。有关更多信息,请参见 base64urlsafe_decode
  • sha256withrsa_verify:用于验证签名。有关更多信息,请参见 sha256withrsa_verify

输入参数:

输出参数:

  • IS_SIGNATURE_VALID:布尔值,说明提取的签名是否匹配待验证内容字符串。