Java实现SM3签名摘要生成(报文+口令)完整方案

Java实现SM3签名摘要生成(报文+口令)完整方案

1. 实现思路

要实现「报文+口令生成SM3签名摘要」需要:

  1. 将原始报文和口令按约定规则拼接
  2. 使用SM3算法生成摘要(32字节十六进制字符串)
  3. 可选添加时间戳等防重放攻击要素

2. 完整代码实现

(1)SM3签名工具类

import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.util.encoders.Hex;
import java.nio.charset.StandardCharsets;
import java.time.Instant;

public class Sm3SignUtil {

    /**
     * 生成带口令的SM3签名
     * @param message 原始报文
     * @param password 签名口令
     * @return 32字节十六进制签名摘要
     */
    public static String generateSignature(String message, String password) {
        // 1. 拼接报文和口令(按业务约定格式)
        String rawData = message + "|" + password;
        
        // 2. 计算SM3摘要
        SM3Digest digest = new SM3Digest();
        byte[] bytes = rawData.getBytes(StandardCharsets.UTF_8);
        digest.update(bytes, 0, bytes.length);
        
        byte[] hash = new byte[digest.getDigestSize()];
        digest.doFinal(hash, 0);
        return Hex.toHexString(hash);
    }

    /**
     * 生成带时间戳的签名(防重放)
     * @param timestamp 时间戳(秒级)
     */
    public static String generateSignatureWithTimestamp(String message, String password, long timestamp) {
        String rawData = message + "|" + password + "|" + timestamp;
        // ...剩余逻辑同上...
    }

    /**
     * 验证签名
     * @return 是否验证通过
     */
    public static boolean verifySignature(String message, String password, String signature) {
        String calculatedSig = generateSignature(message, password);
        return calculatedSig.equals(signature);
    }
}

(2)使用示例

public class Main {
    public static void main(String[] args) {
        String originalMessage = "amount=100&orderId=123456";
        String password = "mySecret@2023";
        
        // 1. 生成签名
        String signature = Sm3SignUtil.generateSignature(originalMessage, password);
        System.out.println("SM3签名结果: " + signature);
        
        // 2. 验证签名
        boolean isValid = Sm3SignUtil.verifySignature(originalMessage, password, signature);
        System.out.println("签名验证结果: " + isValid);
    }
}

输出示例:

SM3签名结果: 6607f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0
签名验证结果: true

3. 关键增强功能

(1)添加时间戳防重放

// 生成带时间戳的签名
long timestamp = Instant.now().getEpochSecond();
String signature = Sm3SignUtil.generateSignatureWithTimestamp(
    originalMessage, 
    password,
    timestamp
);

// 验证时检查时间戳有效性(如5分钟内有效)
boolean isExpired = (Instant.now().getEpochSecond() - timestamp) > 300;

(2)加盐增强安全性

public static String generateSignatureWithSalt(String message, String password, String salt) {
    String rawData = message + "|" + password + "|" + salt;
    // ...SM3计算逻辑...
}

(3)二进制数据支持

public static String generateSignature(byte[] messageBytes, String password) {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    bos.write(messageBytes);
    bos.write(password.getBytes(StandardCharsets.UTF_8));
    byte[] combined = bos.toByteArray();
    
    SM3Digest digest = new SM3Digest();
    digest.update(combined, 0, combined.length);
    // ...后续计算...
}

4. 生产环境建议

  1. 口令管理

    • 口令不应硬编码,建议从安全配置中心获取
    • 定期轮换口令(如每月更换)
  2. 签名规范

    // 推荐拼接格式(避免歧义)
    String format = "%s||%s||%d"; // 报文||口令||时间戳
    
  3. 性能优化

    // 使用线程局部变量复用SM3Digest实例(需测试线程安全性)
    private static final ThreadLocal<SM3Digest> digestHolder = 
        ThreadLocal.withInitial(SM3Digest::new);
    
  4. 审计日志

    • 记录签名生成/验证的关键参数(脱敏后)

5. 完整流程图示

原始报文 + 口令 → 按规则拼接 → SM3哈希计算 → 32字节签名摘要

6. 与加密方案的结合使用

典型安全通信流程:

  1. 客户端

    String signature = Sm3SignUtil.generateSignature(message, password);
    String encrypted = Sm4WithBase64Util.encryptWithBase64(message, key, iv);
    // 发送encrypted和signature
    
  2. 服务端

    String decrypted = Sm4WithBase64Util.decryptWithBase64(encrypted, key, iv);
    boolean isValid = Sm3SignUtil.verifySignature(decrypted, password, signature);
    

你可能感兴趣的:(java,java,开发语言)