1、JAVA集成 SM2加密解密,及在线验证

        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.69</version>
            <scope>compile</scope>
        </dependency>

2.工具类编写





import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.security.SecureRandom;
public class SM2Util {

    private static final X9ECParameters SM2_EC_PARAMS = GMNamedCurves.getByName("sm2p256v1");
    private static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters(
            SM2_EC_PARAMS.getCurve(),
            SM2_EC_PARAMS.getG(),
            SM2_EC_PARAMS.getN()
    );
    private static final String CHARSET = "UTF-8";
    public static final int CIPHER_MODE_C1C2C3 = 0; 
    public static final int CIPHER_MODE_C1C3C2 = 1; 

    public static String encrypt(String plainText, String publicKeyHex, int cipherMode) throws Exception {
        byte[] plainBytes = plainText.getBytes(CHARSET);
        ECPoint publicKeyPoint = DOMAIN_PARAMS.getCurve().decodePoint(Hex.decode(publicKeyHex));
        ECPublicKeyParameters publicKeyParams = new ECPublicKeyParameters(publicKeyPoint, DOMAIN_PARAMS);

        SM2Engine sm2Engine = new SM2Engine();
        sm2Engine.init(true, new ParametersWithRandom(publicKeyParams, new SecureRandom()));
        byte[] c1c2c3Bytes = sm2Engine.processBlock(plainBytes, 0, plainBytes.length);

        byte[] finalCipherBytes;
        if (cipherMode == CIPHER_MODE_C1C3C2) {
            finalCipherBytes = convertC1C2C3ToC1C3C2(c1c2c3Bytes);
        } else {
            finalCipherBytes = c1c2c3Bytes;
        }
        return Hex.toHexString(finalCipherBytes);
    }

    private static byte[] convertC1C2C3ToC1C3C2(byte[] c1c2c3) {
        int c1Len = 65; 
        int c3Len = 32; 
        int c2Len = c1c2c3.length - c1Len - c3Len;

        byte[] c1 = new byte[c1Len];
        byte[] c2 = new byte[c2Len];
        byte[] c3 = new byte[c3Len];
        System.arraycopy(c1c2c3, 0, c1, 0, c1Len);
        System.arraycopy(c1c2c3, c1Len, c2, 0, c2Len);
        System.arraycopy(c1c2c3, c1Len + c2Len, c3, 0, c3Len);

        byte[] c1c3c2 = new byte[c1c2c3.length];
        System.arraycopy(c1, 0, c1c3c2, 0, c1Len);
        System.arraycopy(c3, 0, c1c3c2, c1Len, c3Len);
        System.arraycopy(c2, 0, c1c3c2, c1Len + c3Len, c2Len);
        return c1c3c2;
    }

    public static String decrypt(String cipherTextHex, String privateKeyHex) throws Exception {
        byte[] cipherBytes = Hex.decode(cipherTextHex);
        byte[] c1c2c3Bytes;

        int c1Len = 65;
        int c3Len = 32;
        if (cipherBytes.length > c1Len + c3Len) {
            int c2Len = cipherBytes.length - c1Len - c3Len;
            if (c2Len > 0) {
                byte[] c1 = new byte[c1Len];
                byte[] c3 = new byte[c3Len];
                byte[] c2 = new byte[c2Len];
                System.arraycopy(cipherBytes, 0, c1, 0, c1Len);
                System.arraycopy(cipherBytes, c1Len, c3, 0, c3Len);
                System.arraycopy(cipherBytes, c1Len + c3Len, c2, 0, c2Len);

                c1c2c3Bytes = new byte[cipherBytes.length];
                System.arraycopy(c1, 0, c1c2c3Bytes, 0, c1Len);
                System.arraycopy(c2, 0, c1c2c3Bytes, c1Len, c2Len);
                System.arraycopy(c3, 0, c1c2c3Bytes, c1Len + c2Len, c3Len);
            } else {
                c1c2c3Bytes = cipherBytes;
            }
        } else {
            c1c2c3Bytes = cipherBytes;
        }

        BigInteger privateKeyD = new BigInteger(privateKeyHex, 16);
        ECPrivateKeyParameters privateKeyParams = new ECPrivateKeyParameters(privateKeyD, DOMAIN_PARAMS);
        SM2Engine sm2Engine = new SM2Engine();
        sm2Engine.init(false, privateKeyParams);
        byte[] decryptedBytes = sm2Engine.processBlock(c1c2c3Bytes, 0, c1c2c3Bytes.length);
        return new String(decryptedBytes, CHARSET);
    }

    public static String decryptStandard(String cipherTextHex, String privateKeyHex) throws Exception {
        return decrypt(cipherTextHex, privateKeyHex);
    }

    public static String decryptLegacy(String cipherTextHex, String privateKeyHex) throws Exception {
        String base64Str = decrypt(cipherTextHex, privateKeyHex);
        byte[] decodedBytes = java.util.Base64.getDecoder().decode(base64Str);
        return new String(decodedBytes, CHARSET);
    }


    public static String[] generateKeys() throws Exception {
        ECKeyPairGenerator generator = new ECKeyPairGenerator();
        generator.init(new ECKeyGenerationParameters(DOMAIN_PARAMS, SecureRandom.getInstance("SHA1PRNG")));
        AsymmetricCipherKeyPair keyPair = generator.generateKeyPair();
        String privateKeyHex = ((ECPrivateKeyParameters) keyPair.getPrivate()).getD().toString(16);
        ECPoint publicKeyPoint = ((ECPublicKeyParameters) keyPair.getPublic()).getQ();
        String publicKeyHex = Hex.toHexString(publicKeyPoint.getEncoded(false));
        return new String[]{publicKeyHex, privateKeyHex};
    }

    /**
     * 测试方法:演示如何使用并验证与在线工具的兼容性
     */
    public static void main(String[] args) throws Exception {
        // ========== 第1步:生成全新的密钥对 ==========
        String[] keys = generateKeys();
        String publicKeyHex = keys[0];
        String privateKeyHex = keys[1];
        System.out.println("【全新生成】公钥: " + publicKeyHex);
        System.out.println("【全新生成】私钥: " + privateKeyHex);
        System.out.println("========================================");

        // ========== 第2步:使用 C1C3C2 模式(国标)加密 ==========
        String plainText = "Test测试123@#"; // 包含中文、英文、数字、符号的测试文本
        int targetMode = CIPHER_MODE_C1C3C2; // 我们的目标是生成在线工具能解的格式

        String cipherTextHex = encrypt(plainText, publicKeyHex, targetMode);
        System.out.println("【加密结果 - C1C3C2模式】");
        System.out.println("明文: " + plainText);
        System.out.println("密文 (Hex): " + cipherTextHex);
        System.out.println("密文长度: " + cipherTextHex.length() + " 个字符 (即 " + cipherTextHex.length()/2 + " 字节)");
        System.out.println("========================================");

        // ========== 第3步:使用本工具类本地解密(验证基础功能) ==========
        try {
            String decryptedText = decrypt(cipherTextHex, privateKeyHex);
            System.out.println("【本地解密验证】");
            System.out.println("结果: " + decryptedText);
            System.out.println("与原明文一致吗? " + plainText.equals(decryptedText));
        } catch (Exception e) {
            System.out.println("【本地解密失败】错误: " + e.getMessage());
            e.printStackTrace();
        }
        System.out.println("========================================");
        System.out.println("私钥 (Private Key): " + privateKeyHex);
        System.out.println("密文 (Ciphertext): " + cipherTextHex);
        System.out.println("预期明文: " + plainText);
    }

}

3.返回结果,代码解密解密成功!

4.网页测试,解密成功!

5.网站测试地址:

SM2在线密解工具 SM2加密工具 国密2解密工具 - The X 在线工具 (the-x.cn)

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐