• SM2加解密


    SM2算法(国密算法)

    国密即国家密码局认定的国产密码算法。主要有SM1,SM2,SM3,SM4。密钥长度和分组长度均为128位
    一、SM1 为对称加密。其加密强度与AES相当。该算法不公开,调用该算法时,需要通过加密芯片的接口进行调用。
    二、SM2为非对称加密,基于ECC。该算法已公开。由于该算法基于ECC,故其签名速度与秘钥生成速度都快于RSA。ECC 256位(SM2采用的就是ECC 256位的一种)安全强度比RSA 2048位高,但运算速度快于RSA。
    三、SM3 消息摘要。可以用MD5作为对比理解。该算法已公开。校验结果为256位。
    四、SM4 无线局域网标准的分组数据算法。对称加密,密钥长度和分组长度均为128位。

    import org.bouncycastle.asn1.gm.GMNamedCurves;
    import org.bouncycastle.asn1.x9.X9ECParameters;
    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.jce.spec.ECParameterSpec;
    import org.bouncycastle.jce.spec.ECPrivateKeySpec;
    import org.bouncycastle.util.encoders.Hex;
    
    import java.math.BigInteger;
    import java.nio.charset.StandardCharsets;
    import java.security.*;
    import java.security.spec.ECGenParameterSpec;
    
    
    public class SM2Demo {
        private static String mStr="zym55mmyz";
    
        public static void main(String[] args) {
            try {
                final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
                // 获取一个椭圆曲线类型的密钥对生成器
                final KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
                // 使用SM2参数初始化生成器
                kpg.initialize(sm2Spec);
                // 获取密钥对
                KeyPair keyPair = kpg.generateKeyPair();
                PublicKey publicKey = keyPair.getPublic();
                PrivateKey privateKey = keyPair.getPrivate();
                String data = encrypt(publicKey,mStr);
                System.out.println("SM2加密:" + data);
                String text = decrypt(privateKey, data);
                System.out.println("SM2解密:" + text);
                byte[] privateKeyEncoded = privateKey.getEncoded();
                /*// 进行Base64编码
                String privateKeyString = Base64.getEncoder().encodeToString(privateKeyEncoded);
    
                //Base64.encode(privateKeyEncoded);*/
                String privateKeyStr = "";
                if (privateKey instanceof BCECPrivateKey){
                    privateKeyStr = ((BCECPrivateKey)privateKey).getD().toString(16);
                }
                String ret = sm2Decrypt(privateKeyStr, data);
                System.out.println("SM2解密2:" + ret);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * SM2加密算法
         * @param publicKey     公钥
         * @param data          明文数据
         * @return
         **/
        public static String encrypt(PublicKey publicKey, String data) {
            ECPublicKeyParameters ecPublicKeyParameters = null;
            if (publicKey instanceof BCECPublicKey) {
                BCECPublicKey bcecPublicKey = (BCECPublicKey) publicKey;
                ECParameterSpec ecParameterSpec = bcecPublicKey.getParameters();
                ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
                        ecParameterSpec.getG(), ecParameterSpec.getN());
                ecPublicKeyParameters = new ECPublicKeyParameters(bcecPublicKey.getQ(),ecDomainParameters);
            }
            SM2Engine sm2Engine = new SM2Engine();
            sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters, new SecureRandom()));
    
            byte[] arrayOfBytes = null;
            try {
                byte[] in = data.getBytes(StandardCharsets.UTF_8);
                arrayOfBytes = sm2Engine.processBlock(in,0, in.length);
            }
            catch (Exception e) {
                System.out.println("SM2加密时出现异常:");
            }
            return Hex.toHexString(arrayOfBytes);
        }
    
        /**
         * SM2解密算法
         * @param privateKey        私钥
         * @param cipherData        密文数据
         * @return
         **/
        public static String decrypt(PrivateKey privateKey, String cipherData) {
            byte[] cipherDataByte = Hex.decode(cipherData);
            BCECPrivateKey bcecPrivateKey = (BCECPrivateKey) privateKey;
            ECParameterSpec ecParameterSpec = bcecPrivateKey.getParameters();
            ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
                    ecParameterSpec.getG(), ecParameterSpec.getN());
            ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(bcecPrivateKey.getD(),
                    ecDomainParameters);
            SM2Engine sm2Engine = new SM2Engine();
            sm2Engine.init(false, ecPrivateKeyParameters);
            String result = null;
            try {
                byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);
                return new String(arrayOfBytes, StandardCharsets.UTF_8);
            }
            catch (Exception e) {
                System.out.println("SM2解密时出现异常");
            }
            return result;
        }
    
        /**
         * SM2解密算法
         * @param key 私钥
         * @param cipherData 密文数据
         * @return
         */
        public static String sm2Decrypt(String key, String cipherData){
            String result = null;
            try {
                // 加密算法
                String algorithm = "EC";
                //私钥Hex,还原私钥
                BigInteger privateKeyD = new BigInteger(key, 16);
                //使用标准名称创建EC参数生成的参数规范
                X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
                //获取私钥的基本域参数
                ECParameterSpec ecParameterSpec = new ECParameterSpec(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());
                ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(privateKeyD,ecParameterSpec);
                //获取私钥对象
                BCECPrivateKey bcecPrivateKey = new BCECPrivateKey(algorithm,ecPrivateKeySpec, BouncyCastleProvider.CONFIGURATION);
    
                byte[] cipherDataByte = Hex.decode(cipherData);
                ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
                        ecParameterSpec.getG(), ecParameterSpec.getN());
                //通过私钥值和私钥基本参数创建私钥参数对象
                ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(bcecPrivateKey.getD(),
                        ecDomainParameters);
                //通过解密模式创建解密引擎并初始化
                SM2Engine sm2Engine = new SM2Engine();
                sm2Engine.init(false, ecPrivateKeyParameters);
                try {
                    byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);
                    return new String(arrayOfBytes, StandardCharsets.UTF_8);
                }
                catch (Exception e) {
                }
            } catch (Exception e) {
            }
            return result;
        }
    }
  • 相关阅读:
    判断当前时间为星期几
    springboot+mysql数据源切换
    表单上传图片
    po,vo,bo,dto,dao解释
    生成电脑的SSH key
    单例模式
    事物的特性和隔离级别
    springAOP自定义注解讲解
    Spring依赖注入(DI)的三种方式
    redis持久化
  • 原文地址:https://www.cnblogs.com/lijianda/p/16173893.html
Copyright © 2020-2023  润新知