SignUtil.java 2.61 KB
package com.diligrp.rider.util;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

/**
 * 开放平台签名工具
 * 签名算法:HmacSHA256
 * 签名字符串:appKey + timestamp + nonce,按字典序拼接后用 AppSecret 做 HMAC-SHA256
 */
public class SignUtil {

    /**
     * 生成签名
     * @param appKey    应用Key
     * @param timestamp 时间戳(秒)
     * @param nonce     随机字符串
     * @param appSecret 应用密钥
     */
    public static String sign(String appKey, String timestamp, String nonce, String appSecret) {
        // 拼接待签名字符串(字典序排列)
        String[] parts = {appKey, timestamp, nonce};
        java.util.Arrays.sort(parts);
        String signStr = String.join("", parts);
        return hmacSha256(signStr, appSecret);
    }

    public static boolean verify(String appKey, String timestamp, String nonce,
                                  String sign, String appSecret) {
        // 防重放:timestamp 与当前时间差不超过5分钟
        try {
            long ts = Long.parseLong(timestamp);
            long now = System.currentTimeMillis() / 1000;
            if (Math.abs(now - ts) > 300) return false;
        } catch (NumberFormatException e) {
            return false;
        }
        String expected = sign(appKey, timestamp, nonce, appSecret);
        return expected.equalsIgnoreCase(sign);
    }

    /** 生成随机 AppKey(32位) */
    public static String generateAppKey() {
        return UUID.randomUUID().toString().replace("-", "").substring(0, 16).toUpperCase();
    }

    /** 生成随机 AppSecret(64位) */
    public static String generateAppSecret() {
        return UUID.randomUUID().toString().replace("-", "")
                + UUID.randomUUID().toString().replace("-", "");
    }

    private static String hmacSha256(String data, String key) {
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
            byte[] bytes = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte b : bytes) sb.append(String.format("%02x", b));
            return sb.toString();
        } catch (Exception e) {
            throw new RuntimeException("签名计算失败", e);
        }
    }

    public static void main(String[] args) {
        System.out.println(SignUtil.sign("8444D338919C4498","1774854151","111","7e0d80b82acb426e90a8b74ad4f23114500e65737ed34ce4803710cd2d4a324e"));
    }
}