BouncyCastle之sm2公私匙

本文介绍了如何使用SM2算法创建公私钥对,并提供关键方法如公钥X/Y提取、私钥D操作、SM2签名以及公钥重组。着重于Bouncy Castle库在SM2算法中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

提供公私密匙对,及签名操作,工具类

public class SignUtils {

	private static X9ECParameters x9ECParameters = CustomNamedCurves.getByName("sm2p256v1");
	private static ECParameterSpec ecParameterSpec = new ECParameterSpec(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
	private static BouncyCastleProvider bouncyCastleProvider = new BouncyCastleProvider();
	static{
		Security.addProvider(bouncyCastleProvider);
	}
	/**
	 * 生成公私钥对
	 * 
	 * @return
	 */
	public static KeyPair generateKeyPair() {
		try {
			BouncyCastleProvider prov = new BouncyCastleProvider();
			Security.addProvider(prov);
			KeyPairGenerator gen = KeyPairGenerator.getInstance("ECDSA", prov);
			gen.initialize(ecParameterSpec);
			KeyPair keyPair = gen.generateKeyPair();
			return keyPair;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 取原始公钥中的X,本地持久化存储
	 *
	 * @return
	 */
	public static String getPublicKeyX(KeyPair kp) {
		PublicKey publicKey = kp.getPublic();
		org.bouncycastle.math.ec.ECPoint publickeyECPoint = ((BCECPublicKey)publicKey).getQ();
		String publicKeyX = publickeyECPoint.getXCoord().toString().toUpperCase(Locale.getDefault());
		return publicKeyX;
	}

	/**
	 * 取原始公钥中的Y,本地持久化存储
	 *
	 * @return
	 */
	public static String getPublicKeyY(KeyPair kp) {
		PublicKey publicKey = kp.getPublic();
		org.bouncycastle.math.ec.ECPoint publickeyECPoint = ((BCECPublicKey)publicKey).getQ();
		String publicKeyY = publickeyECPoint.getYCoord().toString().toUpperCase(Locale.getDefault());
		return publicKeyY;
	}

	/**
	 * 取私钥中的D,本地持久化存储,方便后续从D直接转换成真正的私钥对象
	 *
	 * @return
	 */
	public static BigInteger getPrivateD(KeyPair kp){
		BigInteger privateKeySM2D = ((BCECPrivateKey) kp.getPrivate()).getD();
		return privateKeySM2D;
	}

	/**
	 * 通过私钥D得到私钥对象
	 * 
	 * @param d
	 * @return
	 */

	public static BCECPrivateKey getPrivatekeyFromD(BigInteger d) {
		ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(d, ecParameterSpec);
		return new BCECPrivateKey("EC", ecPrivateKeySpec, BouncyCastleProvider.CONFIGURATION);
	}

	/**
	 * 国密算法使用私钥进行签名
	 * 
	 * @param original
	 * 		  SM3摘要
	 * @param pk
	 * 		  私匙
	 * @return
	 */
	public static byte[] signBySM2PK(byte[] original, PrivateKey pk) {
		if (pk == null || original == null || original.length == 0) {
			return null;
		}
		byte[] signed = null;
		try {
			BouncyCastleProvider prov = new BouncyCastleProvider();
			Signature signature = Signature.getInstance("SM3WITHSM2", prov);
			signature.initSign(pk);
			signature.update(original);
			signed = signature.sign();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (SignatureException e) {
			e.printStackTrace();
		}
		return signed;
	}

	/**
	 * 获取公钥,公钥需要将原始公钥中的X以及Y从新组装:04+X+Y
	 * 
	 * @param
	 *
	 * @return
	 */
	public static String getPublicKey() {

		StringBuilder resultData = new StringBuilder();
		//获取本地存储的X
		String publicKeyX = Store.getInstance().get("sm2PublicKeyX");
		resultData.append("04");
		resultData.append(publicKeyX);
		//获取本地存储的X
		String publicKeyY = Store.getInstance().get("sm2PublicKeyY");
		resultData.append(publicKeyY);
		//获取sm2publickey得到的结果
		return resultData.toString();
	}

	/**
	 * 获取本地存储的私钥D
	 * 
	 * @param
	 *
	 * @return
	 */
	public static BigInteger getPrivateKey() {

		//获取本地存储的私匙的D
		String sm2PrivateKeyD = Store.getInstance().get("sm2PrivateKeyD");
		return new BigInteger(sm2PrivateKeyD);
	}


	/**
	 * SM3摘要
	 *
	 * @param data
	 *        原文数据
	 * @return
	 */
	public static byte[] sm3Digest(byte[]  data) throws NoSuchAlgorithmException {
		MessageDigest digest = MessageDigest.getInstance("SM3", bouncyCastleProvider);
		byte[] digestResult = digest.digest(data);
		return digestResult;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值