更新时间: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(); } }
父主题: 密钥管理