【烦人的加密算法】国密SM2的使用--Java版本

开箱即用
首先引入包

<dependency>
	<groupId>org.bouncycastle</groupId>
	<artifactId>bcprov-jdk15on</artifactId>
	<version>1.68</version>
</dependency>
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;
    }

    /**
     * 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 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 privateKey = "dbd874c60c8c7432052c7f881ae23f5939d841b12a105bb38ab97129ed02f92d";
        String publicKey = "033e5250957110884657948ce04507833731e7f88a18569f57f16b7e2abe3a79ad";
        System.out.println(encrypt(publicKey, "content"));
        String contentDecrypt = "BP4DukeJwLi9Xfp97HZ39GvfAsJ+u+1Rr8zK5TXd+b95YkwDuZnwFpCtSWkvfxfpXP5DmuIbRBQW0JUgcZ7SXbi+vGM9TDD3LNEVIlvQ1Z5Z8TcotgYsryL6J0eSwtdmoVbhdBEehRw=";
        System.out.println(decrypt(privateKey, contentDecrypt));
    }

}

参考:
https://blog.csdn.net/RisenMyth/article/details/107212156

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
很高兴回答你的问题!以下是一个使用国密算法SM2-SM3)的Java Demo Maven工程,供您参考: 1. 首先,在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>com.huawei.security</groupId> <artifactId>sm</artifactId> <version>2.0.5.300</version> </dependency> ``` 2. 创建SM2密钥对 ```java import com.huawei.security.sm.SM2KeyPair; import com.huawei.security.sm.SM2PrivateKey; import com.huawei.security.sm.SM2PublicKey; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; public class SM2Demo { public static void main(String[] args) throws NoSuchProviderException, NoSuchAlgorithmException { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); SM2KeyPair sm2KeyPair = new SM2KeyPair(); SM2PublicKey publicKey = sm2KeyPair.getPublicKey(); SM2PrivateKey privateKey = sm2KeyPair.getPrivateKey(); System.out.println("publicKey: " + publicKey.getHexString()); System.out.println("privateKey: " + privateKey.getHexString()); } } ``` 3. SM2加密和解密 ```java import com.huawei.security.sm.SM2PrivateKey; import com.huawei.security.sm.SM2PublicKey; import com.huawei.security.sm.SM2Engine; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.KeyPairGenerator; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; public class SM2Demo { public static void main(String[] args) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, NoSuchPaddingException { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); // 创建密钥对 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC"); keyPairGenerator.initialize(256); SM2KeyPair sm2KeyPair = new SM2KeyPair(keyPairGenerator.generateKeyPair()); // 获取公钥和私钥 SM2PublicKey publicKey = sm2KeyPair.getPublicKey(); SM2PrivateKey privateKey = sm2KeyPair.getPrivateKey(); // 加密 SM2Engine sm2Engine = new SM2Engine(); Cipher cipher = Cipher.getInstance(sm2Engine.getAlgorithmName(), "BC"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] plaintext = "Hello, world!".getBytes(); byte[] ciphertext = cipher.doFinal(plaintext); System.out.println("ciphertext: " + new String(ciphertext)); // 解密 cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] decrypted = cipher.doFinal(ciphertext); System.out.println("decrypted: " + new String(decrypted)); } } ``` 4. SM3哈希算法 ```java import com.huawei.security.sm.SM3Digest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; public class SM3Demo { public static void main(String[] args) throws NoSuchProviderException, NoSuchAlgorithmException { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); // 计算哈希值 SM3Digest sm3Digest = new SM3Digest(); byte[] plaintext = "Hello, world!".getBytes(); sm3Digest.update(plaintext, 0, plaintext.length); byte[] hash = new byte[sm3Digest.getDigestSize()]; sm3Digest.doFinal(hash, 0); System.out.println("hash: " + org.bouncycastle.util.encoders.Hex.toHexString(hash)); } } ``` 希望这个Demo工程能够帮助您使用国密算法SM2-SM3)的Java开发。如果您有任何疑问,请随时联系我!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值