java sm2加解密

125 阅读1分钟

、 hutools sm2加解密只支持c1c3c2,不支持c1c2c3

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.70</version>
</dependency>
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;

import java.security.Security;

public class SM2Util {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    // 静态常量,初始化 SM2 曲线参数
    private static final X9ECParameters sm2Parameters = GMNamedCurves.getByName("sm2p256v1");
    private static final ECDomainParameters domainParameters = new ECDomainParameters(
            sm2Parameters.getCurve(),
            sm2Parameters.getG(),
            sm2Parameters.getN(),
            sm2Parameters.getH()
    );

    // 加密方法
    public static String encrypt(String publicKeyHex, String plainText, String mode) throws Exception {
        byte[] publicKeyBytes = Hex.decode(publicKeyHex);
        byte[] plainBytes = plainText.getBytes();

        ECPoint ecPublicKeyPoint = sm2Parameters.getCurve().decodePoint(publicKeyBytes);
        ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(ecPublicKeyPoint, domainParameters);

        SM2Engine sm2Engine = getSM2Engine(mode);
        sm2Engine.init(true, publicKeyParameters);
        byte[] cipherText = sm2Engine.processBlock(plainBytes, 0, plainBytes.length);
        return Hex.toHexString(cipherText);
    }

    // 解密方法
    public static String decrypt(String privateKeyHex, String cipherTextHex, String mode) throws Exception {
        byte[] privateKeyBytes = Hex.decode(privateKeyHex);
        byte[] cipherTextBytes = Hex.decode(cipherTextHex);

        ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(new java.math.BigInteger(1, privateKeyBytes), domainParameters);

        SM2Engine sm2Engine = getSM2Engine(mode);
        sm2Engine.init(false, privateKeyParameters);
        byte[] decryptedBytes = sm2Engine.processBlock(cipherTextBytes, 0, cipherTextBytes.length);
        return new String(decryptedBytes);
    }

    // 根据模式获取 SM2 引擎实例
    private static SM2Engine getSM2Engine(String mode) {
        SM2Engine.Mode sm2Mode;
        if ("C1C3C2".equalsIgnoreCase(mode)) {
            sm2Mode = SM2Engine.Mode.C1C3C2;
        } else {
            sm2Mode = SM2Engine.Mode.C1C2C3;
        }
        return new SM2Engine(sm2Mode);
    }
}