SM2加密实现之JAVA方式

package com.xxx.tax.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
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.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;

import javax.crypto.Cipher;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.ECGenParameterSpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * SM2加密
 *
 * @author hcf
 * @date 2021/9/1 14:31
 */
@Slf4j
public class Sm2Utils {

    /**
     * SM2 生成公私钥
     *
     * @return 公私钥
     */
    public static Map<String, String> generateKeyPair() {
        Map<String, String> resultMap = new HashMap<>(2);
        try {
            BouncyCastleProvider provider = new BouncyCastleProvider();

            // 获取椭圆曲线相关生成参数规格
            ECGenParameterSpec genParameterSpec = new ECGenParameterSpec("sm2p256v1");
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", provider);

            // 使用SM2的算法区域初始化密钥生成器
            keyPairGenerator.initialize(genParameterSpec, new SecureRandom());

            // 生成密钥对
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            BCECPrivateKey exPrivateKey = (BCECPrivateKey) keyPair.getPrivate();
            BCECPublicKey ecPublicKey = (BCECPublicKey) keyPair.getPublic();

            // 解密密钥
            BigInteger privateKey = exPrivateKey.getD();
            // 加密密钥
            ECPoint publicKey = ecPublicKey.getQ();

            resultMap.put("privateKey", privateKey.toString(16));
            resultMap.put("publicKey", new String(Hex.encode(publicKey.getEncoded(true))));
        } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
            log.info("NoSuchAlgorithmException | InvalidAlgorithmParameterException {}", e.getMessage(), e);
        }
        return resultMap;
    }
    
	public static String printHexString(byte[] b) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                builder.append('0'+hex);
                hex = '0' + hex;
            }else {
            	 builder.append(hex);
            }
            //System.out.print(hex.toLowerCase());
           
        }
        System.out.println(builder.toString());
        return builder.toString();
    }

    /**
     * sm2 加密
     *
     * @param publicKey 公钥
     * @param content   内容
     * @return 密文
     */
    public static String encrypt(String publicKey, String content) {
        String contentEncrypt = StringUtils.EMPTY;
        try {
            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);
            // 加密并编码为base64格式
            contentEncrypt = Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes()));

        } catch (Exception e) {
            log.info("SM2Utils.encrypt(java.lang.String, java.lang.String) error {}", e.getMessage(), e);
        }
        
        return printHexString(contentEncrypt.getBytes());
        //return contentEncrypt;
    }

    /**
     * sm2 加密
     *
     * @param publicKey 公钥
     * @param content   内容
     * @return 密文
     */
    public static String encrypt(String publicKey, byte[] content) {
        return encrypt(publicKey, new String(content));
    }

    /**
     * sm2 加密
     *
     * @param privateKey     私钥
     * @param contentDecrypt 密文
     * @return 明文
     */
    public static String decrypt(String privateKey, String contentDecrypt) {
        String content = StringUtils.EMPTY;
        try {
            BouncyCastleProvider provider = new BouncyCastleProvider();
            // 获取SM2相关参数
            X9ECParameters parameters = GMNamedCurves.getByName("sm2p256v1");
            // 椭圆曲线参数规格
            ECParameterSpec ecParameterSpec = new ECParameterSpec(parameters.getCurve(), parameters.getG(), parameters.getN(), parameters.getH());
            // 将私钥HEX字符串转换为X值
            BigInteger bigInteger = new BigInteger(privateKey, 16);
            // 获取椭圆曲线KEY生成器
            KeyFactory keyFactory = KeyFactory.getInstance("EC", provider);
            // 将X值转为私钥KEY对象
            BCECPrivateKey bcecPrivateKey = (BCECPrivateKey) keyFactory.generatePrivate(new ECPrivateKeySpec(bigInteger, ecParameterSpec));

            // 获取SM2加密器
            Cipher cipher = Cipher.getInstance("SM2", provider);
            // 初始化为加密模式
            cipher.init(Cipher.DECRYPT_MODE, bcecPrivateKey);
            // 解密
            content = new String(cipher.doFinal(Base64.getDecoder().decode(contentDecrypt)));

        } catch (Exception e) {
            log.info("SM2Utils.encrypt(java.lang.String, java.lang.String) error {}", e.getMessage(), e);
        }
        return content;
    }

    /**
     * sm2 加密
     *
     * @param privateKey     私钥
     * @param contentDecrypt 密文
     * @return 明文
     */
    public static String decrypt(String privateKey, byte[] contentDecrypt) {
        return decrypt(privateKey, new String(contentDecrypt));
    }


    public static void main(String[] args) {
    	
    	String publicKey = "043048E9968B72DDF70983B8E305217D94C1E02A5BD4875B625ACC3B13512641A7AD7DF0A1A39F453675EB4B085D8B9E05433E91DBE716E80A7219C2485F28B01F";
        System.out.println(encrypt(publicKey, "8F6190402EC4F423"));
    }

}

如有问题,请私信。

xObP8s/gudi/zrPMoaJKU7K5u7e+s7/Os8yhokpBVkHP4LnYv86zzMjn0OjSqtKyv8nS1MGqz7VRUaGjDQoNCtf31d8gUVEgNDA0NTQwMjI5

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
要在Java实现SM2加密解密,您可以使用bcprov库。在使用之前,您需要确保已经导入了bcprov-ext-jdk15on-151.jar和bcprov-jdk15on-151.jar这两个包。 首先,您需要生成SM2的密钥对。可以使用以下代码生成密钥对: ```java import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Hex; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.Security; public class SM2Example { public static void main(String[] args) throws Exception { Security.addProvider(new BouncyCastleProvider()); KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("SM2", "BC"); KeyPair keyPair = keyPairGenerator.generateKeyPair(); byte[] publicKey = keyPair.getPublic().getEncoded(); byte[] privateKey = keyPair.getPrivate().getEncoded(); System.out.println("公钥: " + Hex.toHexString(publicKey)); System.out.println("私钥: " + Hex.toHexString(privateKey)); } } ``` 然后,您可以使用以下代码进行SM2加密和解密: ```java import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.crypto.engines.SM2Engine; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.util.PrivateKeyInfoFactory; import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Hex; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Security; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; public class SM2Example { public static void main(String[] args) throws Exception { Security.addProvider(new BouncyCastleProvider()); // 加载公钥和私钥 byte[] publicKeyBytes = Hex.decode("公钥"); byte[] privateKeyBytes = Hex.decode("私钥"); KeyFactory keyFactory = KeyFactory.getInstance("SM2", "BC"); X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes); PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes); PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec); // 加密 SM2Engine engine = new SM2Engine(); engine.init(true, new ECPublicKeyParameters((ECPublicKey) publicKey, SM2Util.DOMAIN_PARAMETERS)); byte[] plaintext = "要加密的数据".getBytes(); byte[] encrypted = engine.processBlock(plaintext, 0, plaintext.length); System.out.println("加密结果: " + Hex.toHexString(encrypted)); // 解密 engine.init(false, new ECPrivateKeyParameters((ECPrivateKey) privateKey, SM2Util.DOMAIN_PARAMETERS)); byte[] decrypted = engine.processBlock(encrypted, 0, encrypted.length); System.out.println("解密结果: " + new String(decrypted)); } } ``` 请注意,这只是一个基础的示例,您可能需要根据您的具体需求进行修改和完善。另外,您还可以通过了解更多关于bcprov库的文档和示例来深入学习和使用SM2加密解密。<span class="em">1</span> #### 引用[.reference_title] - *1* [SM2加密解密JAVA版本.zip](https://download.csdn.net/download/kill_bugs/13500151)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liberty888

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值