我的编程空间,编程开发者的网络收藏夹
学习永远不晚

国密:生成SM2秘钥、加解密及加验签

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

国密:生成SM2秘钥、加解密及加验签

国密改造已经持续了很长时间了,相信很多从事金融科技类的程序猿都遇到过这个需求。这篇文章就为大家带来笔者对于国密改造的一些经验,主要是代码层面,有兴趣的同学可以研究下国密的算法模型!

注:本文所用到的工具类并非笔者所写!

目录

一、国密简述

二、依赖准备

三、SM2算法应用

1、生成SM2公私钥

工具类

测试Demo

 2、数据加解密


一、国密简述

国密——国家密码局制定的国家密码算法。主要包含SM1、SM2、SM3、SM4几种方式。

SM1:对称加密,且算法不公开,使用硬件加密,本文不做叙述;

SM2:非对称加密,签名以及生成秘钥速度优于RSA,基于ECC算法,运算效率更高,且更安全;

SM3:摘要,国产杂凑算法,生成长度为256比特,优于MD5以及SHA-1算法;

SM4: 无线局域网标准的分组数据算法。对称加密,密钥长度和分组长度均为128位;

注意

生成SM2 公钥是130 位 前面多了04两个标识符,注意区分!

二、依赖准备

国密主要用到下面的包

                    org.bouncycastle            bcpkix-jdk15on            1.57        

一定注意版本。实际项目中笔者发现项目其他子工程用到1.56版本的包,所以选择了低版本。

三、SM2算法应用

1、生成SM2公私钥

工具类

package cn.test.encrypt.utils.sm2;import cn.test.encrypt.utils.Util;import org.bouncycastle.crypto.AsymmetricCipherKeyPair;import org.bouncycastle.crypto.digests.SM3Digest;import org.bouncycastle.crypto.params.ECPrivateKeyParameters;import org.bouncycastle.crypto.params.ECPublicKeyParameters;import org.bouncycastle.math.ec.ECPoint;import java.math.BigInteger;public class Cipher {    private int ct;    private ECPoint p2;    private SM3Digest sm3keybase;    private SM3Digest sm3c3;    private byte key[];    private byte keyOff;    public Cipher()    {        this.ct = 1;        this.key = new byte[32];        this.keyOff = 0;    }    private void Reset()    {        this.sm3keybase = new SM3Digest();        this.sm3c3 = new SM3Digest();        byte p[] = Util.byteConvert32Bytes(p2.getX().toBigInteger());        this.sm3keybase.update(p, 0, p.length);        this.sm3c3.update(p, 0, p.length);        p = Util.byteConvert32Bytes(p2.getY().toBigInteger());        this.sm3keybase.update(p, 0, p.length);        this.ct = 1;        NextKey();    }    private void NextKey()    {        SM3Digest sm3keycur = new SM3Digest(this.sm3keybase);        sm3keycur.update((byte) (ct >> 24 & 0xff));        sm3keycur.update((byte) (ct >> 16 & 0xff));        sm3keycur.update((byte) (ct >> 8 & 0xff));        sm3keycur.update((byte) (ct & 0xff));        sm3keycur.doFinal(key, 0);        this.keyOff = 0;        this.ct++;    }    public ECPoint Init_enc(SM2 sm2, ECPoint userKey)    {        AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair();        ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();        ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();        BigInteger k = ecpriv.getD();        ECPoint c1 = ecpub.getQ();        this.p2 = userKey.multiply(k);        Reset();        return c1;    }    public void Encrypt(byte data[])    {        this.sm3c3.update(data, 0, data.length);        for (int i = 0; i < data.length; i++)        {            if (keyOff == key.length)            {                NextKey();            }            data[i] ^= key[keyOff++];        }    }    public void Init_dec(BigInteger userD, ECPoint c1)    {        this.p2 = c1.multiply(userD);        Reset();    }    public void Decrypt(byte data[])    {        for (int i = 0; i < data.length; i++)        {            if (keyOff == key.length)            {                NextKey();            }            data[i] ^= key[keyOff++];        }        this.sm3c3.update(data, 0, data.length);    }    public void Dofinal(byte c3[])    {        byte p[] = Util.byteConvert32Bytes(p2.getY().toBigInteger());        this.sm3c3.update(p, 0, p.length);        this.sm3c3.doFinal(c3, 0);        Reset();    }}
package cn.test.encrypt.utils.sm2;import org.bouncycastle.crypto.generators.ECKeyPairGenerator;import org.bouncycastle.crypto.params.ECDomainParameters;import org.bouncycastle.crypto.params.ECKeyGenerationParameters;import org.bouncycastle.math.ec.ECCurve;import org.bouncycastle.math.ec.ECFieldElement;import org.bouncycastle.math.ec.ECFieldElement.Fp;import org.bouncycastle.math.ec.ECPoint;import java.math.BigInteger;import java.security.SecureRandom;public class SM2 {    //国密参数    public static String[] ecc_param = {            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",            "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",            "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",            "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"    };    public static SM2 Instance()    {        return new SM2();    }    public final BigInteger ecc_p;    public final BigInteger ecc_a;    public final BigInteger ecc_b;    public final BigInteger ecc_n;    public final BigInteger ecc_gx;    public final BigInteger ecc_gy;    public final ECCurve ecc_curve;    public final ECPoint ecc_point_g;    public final ECDomainParameters ecc_bc_spec;    public final ECKeyPairGenerator ecc_key_pair_generator;    public final ECFieldElement ecc_gx_fieldelement;    public final ECFieldElement ecc_gy_fieldelement;    public SM2()    {        this.ecc_p = new BigInteger(ecc_param[0], 16);        this.ecc_a = new BigInteger(ecc_param[1], 16);        this.ecc_b = new BigInteger(ecc_param[2], 16);        this.ecc_n = new BigInteger(ecc_param[3], 16);        this.ecc_gx = new BigInteger(ecc_param[4], 16);        this.ecc_gy = new BigInteger(ecc_param[5], 16);        this.ecc_gx_fieldelement = new Fp(this.ecc_p, this.ecc_gx);        this.ecc_gy_fieldelement = new Fp(this.ecc_p, this.ecc_gy);        this.ecc_curve = new ECCurve.Fp(this.ecc_p, this.ecc_a, this.ecc_b);        this.ecc_point_g = new ECPoint.Fp(this.ecc_curve, this.ecc_gx_fieldelement, this.ecc_gy_fieldelement);        this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, this.ecc_n);        ECKeyGenerationParameters ecc_ecgenparam;        ecc_ecgenparam = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom());        this.ecc_key_pair_generator = new ECKeyPairGenerator();        this.ecc_key_pair_generator.init(ecc_ecgenparam);    }}

生成随机秘钥工具类

package cn.test.encrypt.utils.sm2;import cn.test.encrypt.utils.Util;import org.bouncycastle.crypto.AsymmetricCipherKeyPair;import org.bouncycastle.crypto.params.ECPrivateKeyParameters;import org.bouncycastle.crypto.params.ECPublicKeyParameters;import org.bouncycastle.math.ec.ECPoint;import java.io.IOException;import java.math.BigInteger;public class SM2EncDecUtils {    //生成随机秘钥对    public static SM2KeyVO generateKeyPair(){        SM2 sm2 = SM2.Instance();        AsymmetricCipherKeyPair key = null;        while (true){            key=sm2.ecc_key_pair_generator.generateKeyPair();            if(((ECPrivateKeyParameters) key.getPrivate()).getD().toByteArray().length==32){                break;            }        }        ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();        ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();        BigInteger privateKey = ecpriv.getD();        ECPoint publicKey = ecpub.getQ();        SM2KeyVO sm2KeyVO = new SM2KeyVO();        sm2KeyVO.setPublicKey(publicKey);        sm2KeyVO.setPrivateKey(privateKey);        //System.out.println("公钥: " + Util.byteToHex(publicKey.getEncoded()));        //System.out.println("私钥: " + Util.byteToHex(privateKey.toByteArray()));        return sm2KeyVO;    }    //数据加密    public static String encrypt(byte[] publicKey, byte[] data) throws IOException    {        if (publicKey == null || publicKey.length == 0)        {            return null;        }        if (data == null || data.length == 0)        {            return null;        }        byte[] source = new byte[data.length];        //将数组data复制到source        System.arraycopy(data, 0, source, 0, data.length);        Cipher cipher = new Cipher();        SM2 sm2 = SM2.Instance();//new自建类,, SM2 sm2 = new SM2();        ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);        ECPoint c1 = cipher.Init_enc(sm2, userKey);        cipher.Encrypt(source);        byte[] c3 = new byte[32];        cipher.Dofinal(c3);     // System.out.println("C1 " + Util.byteToHex(c1.getEncoded()));     // System.out.println("C2 " + Util.byteToHex(source));     //System.out.println("C3 " + Util.byteToHex(c3));        //C1 C2 C3拼装成加密字串        // C1 | C2 | C3        //return Util.byteToHex(c1.getEncoded()) + Util.byteToHex(source) + Util.byteToHex(c3);        // C1 | C3 | C2        return Util.byteToHex(c1.getEncoded()) + Util.byteToHex(c3) + Util.byteToHex(source);    }    //数据解密    public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException    {        if (privateKey == null || privateKey.length == 0)        {            return null;        }        if (encryptedData == null || encryptedData.length == 0)        {            return null;        }        //加密字节数组转换为十六进制的字符串 长度变为encryptedData.length * 2        String data = Util.byteToHex(encryptedData);                        byte[] c1Bytes = Util.hexToByte(data.substring(0,130));        int c2Len = encryptedData.length - 97;        byte[] c3 = Util.hexToByte(data.substring(130,130 + 64));        byte[] c2 = Util.hexToByte(data.substring(194,194 + 2 * c2Len));        SM2 sm2 = SM2.Instance();        BigInteger userD = new BigInteger(1, privateKey);        //通过C1实体字节来生成ECPoint        ECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes);        Cipher cipher = new Cipher();        cipher.Init_dec(userD, c1);        cipher.Decrypt(c2);        cipher.Dofinal(c3);        //返回解密结果        return c2;    }}

SM2曲线算法工具类

package cn.test.encrypt.utils.sm2;import cn.test.encrypt.utils.Util;import org.bouncycastle.crypto.AsymmetricCipherKeyPair;import org.bouncycastle.crypto.digests.SM3Digest;import org.bouncycastle.crypto.generators.ECKeyPairGenerator;import org.bouncycastle.crypto.params.ECDomainParameters;import org.bouncycastle.crypto.params.ECKeyGenerationParameters;import org.bouncycastle.crypto.params.ECPrivateKeyParameters;import org.bouncycastle.crypto.params.ECPublicKeyParameters;import org.bouncycastle.math.ec.ECCurve;import org.bouncycastle.math.ec.ECFieldElement;import org.bouncycastle.math.ec.ECFieldElement.Fp;import org.bouncycastle.math.ec.ECPoint;import java.math.BigInteger;import java.security.SecureRandom;public class SM2Factory {//A 第一系数private static final BigInteger a  = new BigInteger("fffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc",16);//B 第二系数private static final BigInteger b  = new BigInteger("28e9fa9e9d9f5e344d5a9e4bcf6509a7f39789f515ab8f92ddbcbd414d940e93",16);//曲线X系数private static final BigInteger gx = new BigInteger("32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",16);//曲线Y系数private static final BigInteger gy = new BigInteger("bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0",16);//生产者顺序系数private static final BigInteger n  = new BigInteger("fffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123",16);//素数private static final BigInteger p  = new BigInteger("fffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff",16);//因子系数 1private static final int h  = 1;//一些必要类public final ECFieldElement ecc_gx_fieldelement;public final ECFieldElement ecc_gy_fieldelement;public final ECCurve ecc_curve;public final ECPoint ecc_point_g;public final ECDomainParameters ecc_bc_spec;public final ECKeyPairGenerator ecc_key_pair_generator;public static SM2Factory getInstance(){return new SM2Factory();}public SM2Factory() {this.ecc_gx_fieldelement = new Fp(this.p,this.gx);this.ecc_gy_fieldelement = new Fp(this.p, this.gy);this.ecc_curve = new ECCurve.Fp(this.p, this.a, this.b);this.ecc_point_g = new ECPoint.Fp(this.ecc_curve, this.ecc_gx_fieldelement,this.ecc_gy_fieldelement);this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, this.n);ECKeyGenerationParameters ecc_ecgenparam;ecc_ecgenparam = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom());this.ecc_key_pair_generator = new ECKeyPairGenerator();this.ecc_key_pair_generator.init(ecc_ecgenparam);}public  byte[] sm2GetZ(byte[] userId, ECPoint userKey){SM3Digest sm3 = new SM3Digest();int len = userId.length * 8;sm3.update((byte) (len >> 8 & 0xFF));sm3.update((byte) (len & 0xFF));sm3.update(userId, 0, userId.length);byte[] p = Util.byteConvert32Bytes(this.a);sm3.update(p, 0, p.length);p = Util.byteConvert32Bytes(this.b);sm3.update(p, 0, p.length);p = Util.byteConvert32Bytes(this.gx);sm3.update(p, 0, p.length);p = Util.byteConvert32Bytes(this.gy);sm3.update(p, 0, p.length);p = Util.byteConvert32Bytes(userKey.normalize().getXCoord().toBigInteger());sm3.update(p, 0, p.length);p = Util.byteConvert32Bytes(userKey.normalize().getYCoord().toBigInteger());sm3.update(p, 0, p.length);byte[] md = new byte[sm3.getDigestSize()];sm3.doFinal(md, 0);return md;}public void sm2Sign(byte[] md, BigInteger userD, ECPoint userKey, SM2Result sm2Result) {BigInteger e = new BigInteger(1, md);BigInteger k = null;ECPoint kp = null;BigInteger r = null;BigInteger s = null;do {do {// 正式环境AsymmetricCipherKeyPair keypair = ecc_key_pair_generator.generateKeyPair();ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) keypair.getPrivate();ECPublicKeyParameters ecpub = (ECPublicKeyParameters) keypair.getPublic();k = ecpriv.getD();kp = ecpub.getQ();//System.out.println("BigInteger:" + k + "\nECPoint:" + kp);//System.out.println("计算曲线点X1: "+ kp.getXCoord().toBigInteger().toString(16));//System.out.println("计算曲线点Y1: "+ kp.getYCoord().toBigInteger().toString(16));//System.out.println("");// rr = e.add(kp.getXCoord().toBigInteger());r = r.mod(this.n);} while (r.equals(BigInteger.ZERO) || r.add(k).equals(this.n)||r.toString(16).length()!=64);// (1 + dA)~-1BigInteger da_1 = userD.add(BigInteger.ONE);da_1 = da_1.modInverse(this.n);// ss = r.multiply(userD);s = k.subtract(s).mod(this.n);s = da_1.multiply(s).mod(this.n);} while (s.equals(BigInteger.ZERO)||(s.toString(16).length()!=64));sm2Result.r = r;sm2Result.s = s;}public void sm2Verify(byte md[], ECPoint userKey, BigInteger r,                          BigInteger s, SM2Result sm2Result) {sm2Result.R = null;BigInteger e = new BigInteger(1, md);BigInteger t = r.add(s).mod(this.n);if (t.equals(BigInteger.ZERO)) {return;} else {ECPoint x1y1 = ecc_point_g.multiply(sm2Result.s);//System.out.println("计算曲线点X0: "+ x1y1.normalize().getXCoord().toBigInteger().toString(16));//System.out.println("计算曲线点Y0: "+ x1y1.normalize().getYCoord().toBigInteger().toString(16));//System.out.println("");x1y1 = x1y1.add(userKey.multiply(t));//System.out.println("计算曲线点X1: "+ x1y1.normalize().getXCoord().toBigInteger().toString(16));//System.out.println("计算曲线点Y1: "+ x1y1.normalize().getYCoord().toBigInteger().toString(16));//System.out.println("");sm2Result.R = e.add(x1y1.normalize().getXCoord().toBigInteger()).mod(this.n);//System.out.println("R: " + sm2Result.R.toString(16));return;}}}

工具类

package cn.test.encrypt.utils;import java.math.BigInteger;public class Util {        public static byte[] intToBytes(int num) {        byte[] bytes = new byte[4];        bytes[0] = (byte) (0xff & (num >> 0));        bytes[1] = (byte) (0xff & (num >> 8));        bytes[2] = (byte) (0xff & (num >> 16));        bytes[3] = (byte) (0xff & (num >> 24));        return bytes;    }        public static int byteToInt(byte[] bytes) {        int num = 0;        int temp;        temp = (0x000000ff & (bytes[0])) << 0;        num = num | temp;        temp = (0x000000ff & (bytes[1])) << 8;        num = num | temp;        temp = (0x000000ff & (bytes[2])) << 16;        num = num | temp;        temp = (0x000000ff & (bytes[3])) << 24;        num = num | temp;        return num;    }        public static byte[] longToBytes(long num) {        byte[] bytes = new byte[8];        for (int i = 0; i < 8; i++) {            bytes[i] = (byte) (0xff & (num >> (i * 8)));        }        return bytes;    }        public static byte[] byteConvert32Bytes(BigInteger n) {        byte tmpd[] = (byte[]) null;        if (n == null) {            return null;        }        if (n.toByteArray().length == 33) {            tmpd = new byte[32];            System.arraycopy(n.toByteArray(), 1, tmpd, 0, 32);        } else if (n.toByteArray().length == 32) {            tmpd = n.toByteArray();        } else {            tmpd = new byte[32];            for (int i = 0; i < 32 - n.toByteArray().length; i++) {                tmpd[i] = 0;            }            System.arraycopy(n.toByteArray(), 0, tmpd, 32 - n.toByteArray().length, n.toByteArray().length);        }        return tmpd;    }        public static BigInteger byteConvertInteger(byte[] b) {        if (b[0] < 0) {            byte[] temp = new byte[b.length + 1];            temp[0] = 0;            System.arraycopy(b, 0, temp, 1, b.length);            return new BigInteger(temp);        }        return new BigInteger(b);    }        public static String getHexString(byte[] bytes) {        return getHexString(bytes, true);    }        public static String getHexString(byte[] bytes, boolean upperCase) {        String ret = "";        for (int i = 0; i < bytes.length; i++) {            ret += Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1);        }        return upperCase ? ret.toUpperCase() : ret;    }        public static void printHexString(byte[] bytes) {        for (int i = 0; i < bytes.length; i++) {            String hex = Integer.toHexString(bytes[i] & 0xFF);            if (hex.length() == 1) {                hex = '0' + hex;            }            System.out.print("0x" + hex.toUpperCase() + ",");        }        System.out.println("");    }        public static byte[] hexStringToBytes(String hexString) {        if (hexString == null || hexString.equals("")) {            return null;        }        hexString = hexString.toUpperCase();        int length = hexString.length() / 2;        char[] hexChars = hexString.toCharArray();        byte[] d = new byte[length];        for (int i = 0; i < length; i++) {            int pos = i * 2;            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));        }        return d;    }        public static byte charToByte(char c) {        return (byte) "0123456789ABCDEF".indexOf(c);    }        private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5',            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};        private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5',            '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};        public static char[] encodeHex(byte[] data) {        return encodeHex(data, true);    }        public static char[] encodeHex(byte[] data, boolean toLowerCase) {        return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);    }        protected static char[] encodeHex(byte[] data, char[] toDigits) {        int l = data.length;        char[] out = new char[l << 1];        // two characters form the hex value.        for (int i = 0, j = 0; i < l; i++) {            out[j++] = toDigits[(0xF0 & data[i]) >>> 4];            out[j++] = toDigits[0x0F & data[i]];        }        return out;    }        public static String encodeHexString(byte[] data) {        return encodeHexString(data, true);    }        public static String encodeHexString(byte[] data, boolean toLowerCase) {        return encodeHexString(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);    }        protected static String encodeHexString(byte[] data, char[] toDigits) {        return new String(encodeHex(data, toDigits));    }        public static byte[] decodeHex(char[] data) {        int len = data.length;        if ((len & 0x01) != 0) {            throw new RuntimeException("Odd number of characters.");        }        byte[] out = new byte[len >> 1];        // two characters form the hex value.        for (int i = 0, j = 0; j < len; i++) {            int f = toDigit(data[j], j) << 4;            j++;            f = f | toDigit(data[j], j);            j++;            out[i] = (byte) (f & 0xFF);        }        return out;    }        protected static int toDigit(char ch, int index) {        int digit = Character.digit(ch, 16);        if (digit == -1) {            throw new RuntimeException("Illegal hexadecimal character " + ch                    + " at index " + index);        }        return digit;    }        public static String StringToAsciiString(String content) {        String result = "";        int max = content.length();        for (int i = 0; i < max; i++) {            char c = content.charAt(i);            String b = Integer.toHexString(c);            result = result + b;        }        return result;    }        public static String hexStringToString(String hexString, int encodeType) {        String result = "";        int max = hexString.length() / encodeType;        for (int i = 0; i < max; i++) {            char c = (char) hexStringToAlgorism(hexString                    .substring(i * encodeType, (i + 1) * encodeType));            result += c;        }        return result;    }        public static int hexStringToAlgorism(String hex) {        hex = hex.toUpperCase();        int max = hex.length();        int result = 0;        for (int i = max; i > 0; i--) {            char c = hex.charAt(i - 1);            int algorism = 0;            if (c >= '0' && c <= '9') {                algorism = c - '0';            } else {                algorism = c - 55;            }            result += Math.pow(16, max - i) * algorism;        }        return result;    }        public static String hexStringToBinary(String hex) {        hex = hex.toUpperCase();        String result = "";        int max = hex.length();        for (int i = 0; i < max; i++) {            char c = hex.charAt(i);            switch (c) {                case '0':                    result += "0000";                    break;                case '1':                    result += "0001";                    break;                case '2':                    result += "0010";                    break;                case '3':                    result += "0011";                    break;                case '4':                    result += "0100";                    break;                case '5':                    result += "0101";                    break;                case '6':                    result += "0110";                    break;                case '7':                    result += "0111";                    break;                case '8':                    result += "1000";                    break;                case '9':                    result += "1001";                    break;                case 'A':                    result += "1010";                    break;                case 'B':                    result += "1011";                    break;                case 'C':                    result += "1100";                    break;                case 'D':                    result += "1101";                    break;                case 'E':                    result += "1110";                    break;                case 'F':                    result += "1111";                    break;            }        }        return result;    }        public static String AsciiStringToString(String content) {        String result = "";        int length = content.length() / 2;        for (int i = 0; i < length; i++) {            String c = content.substring(i * 2, i * 2 + 2);            int a = hexStringToAlgorism(c);            char b = (char) a;            String d = String.valueOf(b);            result += d;        }        return result;    }        public static String algorismToHexString(int algorism, int maxLength) {        String result = "";        result = Integer.toHexString(algorism);        if (result.length() % 2 == 1) {            result = "0" + result;        }        return patchHexString(result.toUpperCase(), maxLength);    }        public static String byteToString(byte[] bytearray) {        String result = "";        char temp;        int length = bytearray.length;        for (int i = 0; i < length; i++) {            temp = (char) bytearray[i];            result += temp;        }        return result;    }        public static int binaryToAlgorism(String binary) {        int max = binary.length();        int result = 0;        for (int i = max; i > 0; i--) {            char c = binary.charAt(i - 1);            int algorism = c - '0';            result += Math.pow(2, max - i) * algorism;        }        return result;    }        public static String algorismToHEXString(int algorism) {        String result = "";        result = Integer.toHexString(algorism);        if (result.length() % 2 == 1) {            result = "0" + result;        }        result = result.toUpperCase();        return result;    }        static public String patchHexString(String str, int maxLength) {        String temp = "";        for (int i = 0; i < maxLength - str.length(); i++) {            temp = "0" + temp;        }        str = (temp + str).substring(0, maxLength);        return str;    }        public static int parseToInt(String s, int defaultInt, int radix) {        int i = 0;        try {            i = Integer.parseInt(s, radix);        } catch (NumberFormatException ex) {            i = defaultInt;        }        return i;    }        public static int parseToInt(String s, int defaultInt) {        int i = 0;        try {            i = Integer.parseInt(s);        } catch (NumberFormatException ex) {            i = defaultInt;        }        return i;    }        public static byte[] hexToByte(String hex)            throws IllegalArgumentException {        if (hex.length() % 2 != 0) {            throw new IllegalArgumentException();        }        char[] arr = hex.toCharArray();        byte[] b = new byte[hex.length() / 2];        for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {            String swap = "" + arr[i++] + arr[i];            int byteint = Integer.parseInt(swap, 16) & 0xFF;            b[j] = new Integer(byteint).byteValue();        }        return b;    }        public static String byteToHex(byte b[]) {        if (b == null) {            throw new IllegalArgumentException(                    "Argument b ( byte array ) is null! ");        }        String hs = "";        String stmp = "";        for (int n = 0; n < b.length; n++) {            stmp = Integer.toHexString(b[n] & 0xff);            if (stmp.length() == 1) {                hs = hs + "0" + stmp;            } else {                hs = hs + stmp;            }        }        return hs.toLowerCase();        //return hs.toUpperCase();    }    public static byte[] subByte(byte[] input, int startIndex, int length) {        byte[] bt = new byte[length];        for (int i = 0; i < length; i++) {            bt[i] = input[i + startIndex];        }        return bt;    }}

SM2对象

package cn.test.encrypt.utils.sm2;import cn.test.encrypt.utils.Util;import cn.test.encrypt.test.SecurityTestAll;import org.bouncycastle.math.ec.ECPoint;import java.math.BigInteger;public class SM2KeyVO {    BigInteger privateKey ;    ECPoint publicKey ;    public BigInteger getPrivateKey() {        return privateKey;    }    public void setPrivateKey(BigInteger privateKey) {        this.privateKey = privateKey;    }    public ECPoint getPublicKey() {        return publicKey;    }    public void setPublicKey(ECPoint publicKey) {        this.publicKey = publicKey;    }    //HardPubKey:3059301306072A8648CE3D020106082A811CCF5501822D03420004+X+Y    //SoftPubKey:04+X+Y    public String getPubHexInSoft(){        return Util.byteToHex(publicKey.getEncoded(true));        //System.out.println("公钥: " + );    }    public String getPubHexInHard(){        return SecurityTestAll.SM2PubHardKeyHead +Util.byteToHex(publicKey.getEncoded(true));    }    public String getPriHexInSoft(){        return Util.byteToHex(privateKey.toByteArray());    }}

测试Demo

 public static void main(String[] args) {        SM2KeyVO initKeyVO = SM2EncDecUtils.generateKeyPair();        System.out.println("初始公钥为: "+initKeyVO.getPubHexInSoft());        System.out.println("初始私钥为: "+initKeyVO.getPriHexInSoft());    }

输出结果:

 2、数据加解密

简单业务描述:使用初始公钥加密工作公钥,使用初始私钥解密加密后公钥;

Demo

    public static void main(String[] args) throws IOException {        //生成初始秘钥        SM2KeyVO initKeyVO = SM2EncDecUtils.generateKeyPair();        String initPubKey = initKeyVO.getPubHexInSoft();        String initPriKey = initKeyVO.getPriHexInSoft();        System.out.println("初始公钥为: " + initPubKey);        System.out.println("初始私钥为: " + initPriKey);        //生成工作秘钥        SM2KeyVO serverKey = SM2EncDecUtils.generateKeyPair();        String serverPubKey = serverKey.getPubHexInSoft();        String serverPriKey = serverKey.getPriHexInSoft();        System.out.println("服务端公钥为: " + serverPubKey);        System.out.println("服务端私钥为: " + serverPriKey);        //使用初始公钥加密服务端公钥 注意格式字节数组        String encryptServerPubKey = SM2EncDecUtils.encrypt(Convert.hexToBytes(initPubKey), serverPubKey.getBytes());        System.out.println("加密后公钥:"+encryptServerPubKey);        //使用初始私钥解密服务端公钥 注意格式        byte[] decrypt = SM2EncDecUtils.decrypt(Convert.hexToBytes(initPriKey), Convert.hexToBytes(encryptServerPubKey));        System.out.println("解密后服务端公钥:"+new String(decrypt));        if (serverPubKey.equals(new String(decrypt)))            System.out.println("——————————解密成功——————————");    }

结果:

 至此,SM2的公私钥生成以及加解密就完成了,下一期内容为生成Sign以及验证。

来源地址:https://blog.csdn.net/Su7148/article/details/127872997

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

国密:生成SM2秘钥、加解密及加验签

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录