当前位置:   article > 正文

Java实现SM2算法(国密算法)_java sm2算法

java sm2算法

Java实现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位。

POM依赖:

<!--国密-->
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.56</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

SM2加解密代码:

/**
 * @author SongWei
 * @version 1.0.0
 * @ClassName spring-cloud.com.boot.cloud.encryption.sm.Sm2Utils.java
 * @Description SM2加解密工具类
 * @createTime 2018年10月28日 13:57:00
 */
public class Sm2Utils{
    /**
     * 生成随机秘钥对
     *
     * @Version: 1.0.0
     * @return: Map<String, String>
     * @author: SongWei
     * @date: 2018/10/28 13:57
     */
    public static Map<String, String> generateKeyPair() {
        SM2 sm2 = SM2.Instance();
        AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair();
        ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();
        ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();
        //解密密钥
        BigInteger privateKey = ecpriv.getD(); 
        //加密密钥
        ECPoint publicKey = ecpub.getQ();  
        Map<String, String> resutlMap = new HashMap<String, String>();
        resutlMap.put("privateKey", SecurityUtils.byteToHex(privateKey.toByteArray()));
        resutlMap.put("publicKey", SecurityUtils.byteToHex(publicKey.getEncoded()));
        return resutlMap;
    }

    /**
     * SM2加密
     *
     * @param publicKey <p>公钥</p>
     * @param data      <p>需要加密的数据</p>
     * @Version: 1.0.0
     * @return: String
     * @author: SongWei
     * @date: 2018/10/28 13:57
     */
    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];
        System.arraycopy(data, 0, source, 0, data.length);
        Cipher cipher = new Cipher();
        SM2 sm2 = SM2.Instance();
        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);
        //C1 C2 C3拼装成加密字串
        return SecurityUtils.byteToHex(c1.getEncoded()) + SecurityUtils.byteToHex(source) + SecurityUtils.byteToHex(c3);

    }

    /**
     * 数据解密
     *
     * @param privateKey    <p>私钥</p>
     * @param encryptedData <p>需要解密的内容</p>
     * @Version: 1.0.0
     * @return: byte
     * @author: SongWei
     * @date: 2018/10/18 13:59
     */
    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 = SecurityUtils.byteToHex(encryptedData);
        /**
         *	分解加密字串
         * (C1 = C1标志位2位 + C1实体部分128位 = 130)
         * (C3 = C3实体部分64位  = 64)
         * (C2 = encryptedData.length * 2 - C1长度  - C2长度)
         */
        byte[] c1Bytes = SecurityUtils.hexToByte(data.substring(0, 130));
        int c2Len = encryptedData.length - 97;
        byte[] c2 = SecurityUtils.hexToByte(data.substring(130, 130 + 2 * c2Len));
        byte[] c3 = SecurityUtils.hexToByte(data.substring(130 + 2 * c2Len, 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;
    }

    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 200; i++) {
            //生成密钥对
            Map<String, String> keyMap = generateKeyPair();
            String plainText = "{"id":"123","name":"张三"}";
            加密密钥
            String publicKey = keyMap.get("publicKey");
            //解密蜜月
            String privateKey = keyMap.get("privateKey");
            String encString = SM2Utils.encrypt(SecurityUtils.hexStringToBytes(publicKey), plainText.getBytes());
            System.out.println("密文:" + encString);
            byte[] plainString = SM2Utils.decrypt(SecurityUtils.hexStringToBytes(privateKey), SecurityUtils.hexStringToBytes(encString));
            System.out.println(new String(plainString));
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
/**
 * @author SongWei
 * @version 1.0.0
 * @ClassName spring-cloud.com.boot.cloud.sm.Sm2Tool.java
 * @Description TODO
 * @createTime 2018年10月28日 14:29:00
 */
public class Sm2Tool {

    /**
     * 正式参数
     *
     * @Version: 1.0.0
     * @date: 2018年10月28日 14:29:00
     */
    public static String[] ecc_param = {
            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
            "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",
            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
            "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
            "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"
    };

    public static Sm2Tool Instance() {
        return new Sm2Tool();
    }

    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_fieldsmen;
    public final ECFieldElement ecc_gy_fieldsmen;


    public Sm2Tool() {
        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_fieldsmen = new Fp(this.ecc_p, this.ecc_gx);
        this.ecc_gy_fieldsmen = 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_fieldsmen, this.ecc_gy_fieldsmen);
        this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, this.ecc_n);
        ECKeyGenerationParameters ecc_engender;
        ecc_engender = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom());
        this.ecc_key_pair_generator = new ECKeyPairGenerator();
        this.ecc_key_pair_generator.init(ecc_engender);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

此文章是SM2加解密代码,后续更新SM3和其他工具类(后续更新完整SM2代码)

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号