更新时间:2025-09-08 GMT+08:00
密钥管理服务如何使用SM2进行离线加密数据?
以如下示例进行讲解:
使用SM2主密钥,密钥用途为ENCRYPT_DECRYPT。使用公钥离线加密"HELLO WORLD!":
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.interfaces.ECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
public class SM2offlineEncryption {
private static final String TEST_DATA = "HELLO WORLD!";
// SM2公钥,仅用作示例,实际使用时,需替换实际使用的SM2公钥。SM2公钥可在密钥详情界面获取
private static final String TEST_PUBLIC_KEY
= "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE/AKIN6dVB3lQFuq3Cmhg+0k1QINkp1Ylo6ch1eNHNI0iBRV9m3CgDStox234Kka8mkYGJQDr5ZzrTdCOGAZrpA==";
public static void main(String[] args)
throws InvalidCipherTextException, NoSuchAlgorithmException, InvalidKeySpecException, IOException {
final byte[] plaintext = TEST_DATA.getBytes();
// BASE64解码SM2公钥
final byte[] psm2PublicKeyBytes = Base64.getDecoder().decode(TEST_PUBLIC_KEY);
final byte[] offlineEncryption = sm2PublicOfflineEncryption(psm2PublicKeyBytes, plaintext);
// 仅打印加密结果,可调用KMS接口进行在线解密认证
System.out.println(Base64.getEncoder().encodeToString(offlineEncryption));
}
public static byte[] sm2PublicOfflineEncryption(byte[] publicKeyBytes, byte[] plaintext)
throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidCipherTextException, IOException {
// 解析公钥
final X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
final KeyFactory keyFactory = KeyFactory.getInstance("EC", new BouncyCastleProvider());
final ECPublicKey publicKey = (ECPublicKey) keyFactory.generatePublic(keySpec);
final ECParameterSpec parameterSpec = publicKey.getParameters();
final ECCurve curve = parameterSpec.getCurve();
final ECPoint g = parameterSpec.getG();
final BigInteger n = parameterSpec.getN();
final BigInteger h = parameterSpec.getH();
final ECDomainParameters domainParams = new ECDomainParameters(curve, g, n, h);
final ECPublicKeyParameters publicKeyParams = new ECPublicKeyParameters(publicKey.getQ(), domainParams);
// 初始化SM2加密引擎(使用C1C3C2模式)
final SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
engine.init(true, new ParametersWithRandom(publicKeyParams, new SecureRandom()));
// 执行加密
final byte[] ciphertext = engine.processBlock(plaintext, 0, plaintext.length);
final ECNamedCurveParameterSpec sm2Spec = ECNamedCurveTable.getParameterSpec("sm2p256v1");
final int fieldSize = (sm2Spec.getCurve().getFieldSize() + 7) / 8; // SM2的坐标长度(32字节)
final byte[] x = Arrays.copyOfRange(ciphertext, 1, 1 + fieldSize); // 跳过04前缀
final byte[] y = Arrays.copyOfRange(ciphertext, 1 + fieldSize, 1 + 2 * fieldSize);
final byte[] c3 = Arrays.copyOfRange(ciphertext, 1 + 2 * fieldSize, 1 + 2 * fieldSize + 32);
final byte[] c2 = Arrays.copyOfRange(ciphertext, 1 + 2 * fieldSize + 32, ciphertext.length);
// 组装ASN.1 SEQUENCE: [X, Y, C3, C2]
final ASN1EncodableVector asn1Vector = new ASN1EncodableVector();
asn1Vector.add(new ASN1Integer(new BigInteger(1, x)));
asn1Vector.add(new ASN1Integer(new BigInteger(1, y)));
asn1Vector.add(new DEROctetString(c3));
asn1Vector.add(new DEROctetString(c2));
// 生成DER编码
final DERSequence derSequence = new DERSequence(asn1Vector);
return derSequence.getEncoded();
}
}
父主题: 密钥管理