SM2加解密

需要使用SM2进行加解密,百度查询的都是自己生成密钥对,然后进行加解密。现在密钥对已给,需要构造加解密公私钥对象进行加解密操作。最后找到hutool工具包直接可以根据公私钥进行构造一SM2对象。查看源码研究了下翻译一下使用bouncycastle包进行实现大致如下这样

添加依赖包

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

根据现有公私钥信息进行加密解密

import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SM3Digest;
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.crypto.params.ParametersWithRandom;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.BigIntegers;
import org.bouncycastle.util.encoders.Hex;

public class SM2Test {
	static String SM2_CURVE_NAME = "sm2p256v1";
	
    
	public static void main(String[] args) throws Exception {
		//私钥
	    String prvKey = "23be18173850ac04c5255984759e15bf60a8eb0f54880b01a9bc24e20e82df48";
	    //公钥坐标
	    String x = "741192ca3ee1a2ba9a50ccab30dd069b29437e2f38fcba709bf84f8a3e732584";
	    String y = "a47f526415387d5eeb48257fa6e4a5603c7b2ba729ede7c61dfe109d89bd02b1";
	    
        String info = "中国";
        byte[] data = info.getBytes();
        
        SM2Test sm2 = new SM2Test();
        
        //KeyPair keyPair = sm2.genKeyPair();
       
        ECDomainParameters domain = sm2.getDomain();
        SM2Engine engine = sm2.getSM2Engine();
		//公钥加密
		CipherParameters pubKeyParameters = sm2.getPubKey(x, y, domain);
		engine.init(true, pubKeyParameters);
		byte[] encData = engine.processBlock(data, 0, data.length);
		System.out.println("加密后内容:"+Hex.toHexString(encData));
		//私钥解密
		CipherParameters PrivateKey = sm2.getPrvKey(prvKey,domain);
		engine.init(false, PrivateKey);
		byte[] decData = engine.processBlock(encData, 0, encData.length);
		System.out.println("解密后内容:"+new String(decData));
		
	}
	
	/**
	 * 构造私钥对象
	 * @param prvKey
	 * @return
	 */
	public CipherParameters getPrvKey(String prvKey,ECDomainParameters domain) {
		BigInteger prvKeyData = BigIntegers.fromUnsignedByteArray(Hex.decode(prvKey));
		ECPrivateKeyParameters PrivateKey = new ECPrivateKeyParameters(prvKeyData, domain);
		return PrivateKey;
	}
	
	/**
	 * 构造公钥对象
	 * @param x
	 * @param y
	 * @param domain
	 * @return
	 */
	public CipherParameters getPubKey(String x,String y,ECDomainParameters domain) {
		ECCurve curve = domain.getCurve();
		ECPoint point = curve.createPoint(BigIntegers.fromUnsignedByteArray(Hex.decode(x)), BigIntegers.fromUnsignedByteArray(Hex.decode(y)));
		ECPublicKeyParameters PublicKey = new ECPublicKeyParameters(point, domain);
		CipherParameters pubKeyParameters = new ParametersWithRandom(PublicKey);
		return pubKeyParameters;
	}
	
	public SM2Engine getSM2Engine() {
		Digest digest = new SM3Digest();
		SM2Engine engine =  new SM2Engine(digest,SM2Engine.Mode.C1C3C2);
		return engine;
	}
	
	public ECDomainParameters getDomain() {
		X9ECParameters x9ECParameters= GMNamedCurves.getByName(SM2_CURVE_NAME);
		ECDomainParameters domain  = new ECDomainParameters(
				x9ECParameters.getCurve(),
				x9ECParameters.getG(),
				x9ECParameters.getN(),
				x9ECParameters.getH()
		);
		return domain;
	}
	
	/**
	 * 生成密钥对
	 * @return
	 * @throws Exception
	 */
	public KeyPair genKeyPair() throws Exception {
		final ECGenParameterSpec sm2Spec = new ECGenParameterSpec(SM2_CURVE_NAME);
        // 获取一个椭圆曲线类型的密钥对生成器
        final KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
        SecureRandom random = new SecureRandom();
        // 使用SM2的算法区域初始化密钥生成器
        kpg.initialize(sm2Spec, random);
        // 获取密钥对
        KeyPair keyPair = kpg.generateKeyPair();
        
        BCECPublicKey pubk = (BCECPublicKey) keyPair.getPublic();
        BCECPrivateKey privK = (BCECPrivateKey) keyPair.getPrivate();
        byte[] privData = BigIntegers.asUnsignedByteArray(32,privK.getD());
        byte[] pubx = BigIntegers.asUnsignedByteArray(32, pubk.getQ().getRawXCoord().toBigInteger());
        byte[] puby = BigIntegers.asUnsignedByteArray(32, pubk.getQ().getRawYCoord().toBigInteger());
        System.out.println("Private Key:"+Hex.toHexString(privData));
        System.out.println("PUB X:"+Hex.toHexString(pubx));
        System.out.println("PUB Y:"+Hex.toHexString(puby));
        return keyPair;
	}
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,我可以为您提供一些关于 JavaScript 和 Java 中 SM2 加解密的基本信息。 JavaScript 中的 SM2 加解密可以使用 jsrsasign 库进行实现。以下是一个简单的示例代码: ```javascript // 密钥对生成 var ec = new KJUR.crypto.ECDSA({'curve': 'sm2'}); var keypair = ec.generateKeyPairHex(); // 加密 var pubKey = keypair.ecpubhex; var plainText = 'hello world'; var cipher = KJUR.crypto.Cipher.encrypt(pubKey, plainText, 'SM2'); // 解密 var privKey = keypair.ecprvhex; var decrypted = KJUR.crypto.Cipher.decrypt(privKey, cipher, 'SM2'); console.log(decrypted); ``` Java 中的 SM2 加解密可以使用 Bouncy Castle 库进行实现。以下是一个简单的示例代码: ```java // 密钥对生成 ECNamedCurveParameterSpec sm2Spec = ECNamedCurveTable.getParameterSpec("sm2p256v1"); KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider()); kpg.initialize(sm2Spec, new SecureRandom()); KeyPair keyPair = kpg.generateKeyPair(); // 加密 Cipher cipher = Cipher.getInstance("SM2", new BouncyCastleProvider()); cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic()); byte[] plainText = "hello world".getBytes(); byte[] cipherText = cipher.doFinal(plainText); // 解密 cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate()); byte[] decrypted = cipher.doFinal(cipherText); System.out.println(new String(decrypted)); ``` 需要注意的是,JavaScript 和 Java 中的 SM2 加解密算法的实现细节可能有所不同,需要根据具体需求进行调整。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值