Skip to main content

签名和验证签名

签名的目的是生成一个基于HMAC(Hash-based Message Authentication Code)的签名,这种签名机制是用来验证信息传输过程中信息的完整性和真实性的一种技术。使用HMAC进行签名时,会结合一个密钥和一个消息,通过哈希算法生成一个固定长度的值。这个过程中的关键步骤可以用以下通用的表达方式来描述:

  1. 收集参数:首先,你需要收集所有参与签名的参数。这些参数通常是键值对形式的,比如API请求中的参数。

  2. 排序:为了确保签名的一致性,无论参数的提交顺序如何,生成签名的过程中必须按照一定的规则(通常是字典序)对这些参数进行排序。

  3. 构造签名字符串:将排序后的参数按照特定的格式(例如key1=value1&key2=value2)拼接起来,形成一个字符串。这个字符串就是待签名的数据。

  4. 生成签名:使用密钥和哈希算法(SHA-256)对待签名数据进行HMAC运算,得到的结果就是签名。这个过程需要确保密钥的安全,只有知道密钥的双方才能验证签名的真实性。

  5. 输出签名:最后,通常会将生成的签名进行编码(如十六进制编码)后输出,以便于传输和验证。

  6. 提交签名:在头中提交字段OC-KeyOC-Signature,其中OC-Key是你的密钥的key,而不是密钥本身;OC-Signature是你计算得到的签名。;

HMAC 支持几乎所有编程语言,包括但不限于Python、Java、PHP等。每种语言都有处理哈希和HMAC的库或内置功能,关键在于遵循上述步骤,正确实现算法逻辑。

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

public class SignatureUtil {

    public static String computeHMAC(Map<String, String> params, String secret) throws NoSuchAlgorithmException, InvalidKeyException {
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);

        // 构造查询字符串
        StringBuilder dataToSign = new StringBuilder();
        for (String key : keys) {
            if (dataToSign.length() > 0) {
                dataToSign.append("&");
            }
            dataToSign.append(key).append("=").append(params.get(key));
        }

        // HMAC-SHA256加密
        SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(secretKeySpec);
        byte[] rawHmac = mac.doFinal(dataToSign.toString().getBytes());

        // 转换为十六进制字符串
        StringBuilder hexString = new StringBuilder();
        for (byte b : rawHmac) {
            hexString.append(String.format("%02x", b));
        }
        return hexString.toString();
    }
}