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>

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
     * @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 

公钥

* @param data

需要加密的数据

* @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

私钥

* @param encryptedData

需要解密的内容

* @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)); } } }
/**
 * @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);
    }
}

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

你可能感兴趣的:(Java,后端,SM2,java,加密解密,SM2)