全部产品
Search
文档中心

ID Verification:SM2加密说明

更新时间:Oct 23, 2026

ID Verification部分接口服务支持在认证请求中使用SM2加密传输个人信息(姓名、身份证号码)。您可以通过公钥对认证请求中的个人信息参数进行加密。本文介绍如何开启SM2参数加密。

SM2公钥

02cd77e007bdc86eeaf9a479ba7a2c22bc0a517ccb3a6975c3f94b4ac93347dea6

Java语言示例

添加Maven依赖

<dependency>
  <groupId>org.bouncycastle</groupId>
  <artifactId>bcprov-jdk15on</artifactId>
  <version>1.65</version>
</dependency>

示例代码

重要

Cipher 为有状态对象,非线程安全,禁止在多线程间共享同一实例。

import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.util.Base64;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;


public class SM2EncryptUtil {

    private static final String publicKey = "02cd77e007bdc86eeaf9a479ba7a2c22bc0a517ccb3a6975c3f94b4ac93347dea6";

    // 根据实际使用情况调整
    private static final int maxPoolSize = 20;

    private static final BlockingQueue<Cipher> pool = new LinkedBlockingDeque<>(maxPoolSize);

    static {
        try {
            // 初始化池
            for (int i = 0; i < maxPoolSize; i++) {
                Cipher newCipher = createCipher();
                pool.put(newCipher);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * SM2加密
     * @param content2Encrypt 待加密的明文
     * @return Base64编码的密文
     */
    public static String encrypt(String content2Encrypt) {
        Cipher cipher = null;
        try {
            cipher = borrow();
            return Base64.getEncoder().encodeToString(cipher.doFinal(content2Encrypt.getBytes(StandardCharsets.UTF_8)));
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            if (cipher != null) {
                release(cipher);
            }
        }
    }

    private static Cipher createCipher() throws Exception {
        BouncyCastleProvider provider = new BouncyCastleProvider();
        // 获取SM2相关参数
        X9ECParameters parameters = GMNamedCurves.getByName("sm2p256v1");
        // 椭圆曲线参数规格
        ECParameterSpec ecParameterSpec = new ECParameterSpec(parameters.getCurve(), parameters.getG(), parameters.getN(), parameters.getH());
        // 将公钥HEX字符串转换为椭圆曲线对应的点
        ECPoint ecPoint = parameters.getCurve().decodePoint(Hex.decode(publicKey));
        // 获取椭圆曲线KEY生成器
        KeyFactory keyFactory = KeyFactory.getInstance("EC", provider);
        // 将椭圆曲线点转为公钥KEY对象
        BCECPublicKey bcecPublicKey = (BCECPublicKey) keyFactory.generatePublic(new ECPublicKeySpec(ecPoint, ecParameterSpec));
        // 获取SM2加密器
        Cipher cipher = Cipher.getInstance("SM2", provider);
        // 初始化为加密模式
        cipher.init(Cipher.ENCRYPT_MODE, bcecPublicKey);
        return cipher;
    }

    private static Cipher borrow() throws InterruptedException {
        // 线程会阻塞直到有可用的Cipher
        return pool.take();
    }

    private static void release(Cipher cipher) {
        // 避免重复添加
        if (cipher != null && !pool.contains(cipher)) {
            // 将Cipher放回池中
            pool.offer(cipher);
        }
    }

}