Java国产密码改造

一:介绍

国产密码算法是指国家密码局认定的国产商用密码算法,目前主要使用公开的SM2、SM3、SM4三类算法,分别是非对称算法、哈希算法和对称算法。

      SM2算法:SM2椭圆曲线公钥密码算法是我国自主设计的公钥密码算法,包括SM2-1椭圆曲线数字签名算法,SM2-2椭圆曲线密钥交换协议,SM2-3椭圆曲线公钥加密算法,分别用于实现数字签名密钥协商和数据加密等功能。SM2算法与RSA算法不同的是,SM2算法是基于椭圆曲线上点群离散对数难题,相对于RSA算法,256位的SM2密码强度已经比2048位的RSA密码强度要高。

      SM3算法:SM3杂凑算法是我国自主设计的密码杂凑算法,适用于商用密码应用中的数字签名和验证消息认证码的生成与验证以及随机数的生成,可满足多种密码应用的安全需求。为了保证杂凑算法的安全性,其产生的杂凑值的长度不应太短,例如MD5输出128比特杂凑值,输出长度太短,影响其安全性SHA-1算法的输出长度为160比特,SM3算法的输出长度为256比特,因此SM3算法的安全性要高于MD5算法和SHA-1算法。

     SM4算法:SM4分组密码算法是我国自主设计的分组对称密码算法,用于实现数据的加密/解密运算,以保证数据和信息的机密性。要保证一个对称密码算法的安全性的基本条件是其具备足够的密钥长度,SM4算法与AES算法具有相同的密钥长度分组长度128比特,因此在安全性上高于3DES算法。

二:使用

1.加入jar包

bcprov-jdk15on-147.jar    (不可使用其它更高级版本,否则会报错)

2.Java代码

1.目录结构

2.代码

Cipher.java

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();  
	    }  
}

Util.java

public class Util {
	 /** 
     * 整形转换成网络传输的字节流(字节数组)型数据 
     *  
     * @param num 一个整型数据 
     * @return 4个字节的自己数组 
     */  
    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;  
    }  
  
    /** 
     * 四个字节的字节数据转换成一个整形数据 
     *  
     * @param bytes 4个字节的字节数组 
     * @return 一个整型数据 
     */  
    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;  
    }  
  
    /** 
     * 长整形转换成网络传输的字节流(字节数组)型数据 
     *  
     * @param num 一个长整型数据 
     * @return 4个字节的自己数组 
     */  
    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;  
    }  
  
    /** 
     * 大数字转换字节流(字节数组)型数据 
     *  
     * @param n 
     * @return 
     */  
    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;  
    }  
      
    /** 
     * 换字节流(字节数组)型数据转大数字 
     *  
     * @param b 
     * @return 
     */  
    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);  
    }  
      
    /** 
     * 根据字节数组获得值(十六进制数字) 
     *  
     * @param bytes 
     * @return 
     */  
    public static String getHexString(byte[] bytes)   
    {  
        return getHexString(bytes, true);  
    }  
      
    /** 
     * 根据字节数组获得值(十六进制数字) 
     *  
     * @param bytes 
     * @param upperCase 
     * @return 
     */  
    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;  
    }  
      
    /** 
     * 打印十六进制字符串 
     *  
     * @param bytes 
     */  
    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("");  
    }  
      
    /** 
     * Convert hex string to byte[] 
     *  
     * @param hexString 
     *            the hex string 
     * @return byte[] 
     */  
    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;  
    }  
      
    /** 
     * Convert char to byte 
     *  
     * @param c 
     *            char 
     * @return byte 
     */  
    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'};  
   
    /** 
     * 将字节数组转换为十六进制字符数组 
     * 
     * @param data byte[] 
     * @return 十六进制char[] 
     */  
    public static char[] encodeHex(byte[] data) {  
        return encodeHex(data, true);  
    }  
   
    /** 
     * 将字节数组转换为十六进制字符数组 
     * 
     * @param data        byte[] 
     * @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式 
     * @return 十六进制char[] 
     */  
    public static char[] encodeHex(byte[] data, boolean toLowerCase) {  
        return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);  
    }  
   
    /** 
     * 将字节数组转换为十六进制字符数组 
     * 
     * @param data     byte[] 
     * @param toDigits 用于控制输出的char[] 
     * @return 十六进制char[] 
     */  
    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;  
    }  
   
    /** 
     * 将字节数组转换为十六进制字符串 
     * 
     * @param data byte[] 
     * @return 十六进制String 
     */  
    public static String encodeHexString(byte[] data) {  
        return encodeHexString(data, true);  
    }  
   
    /** 
     * 将字节数组转换为十六进制字符串 
     * 
     * @param data        byte[] 
     * @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式 
     * @return 十六进制String 
     */  
    public static String encodeHexString(byte[] data, boolean toLowerCase) {  
        return encodeHexString(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);  
    }  
   
    /** 
     * 将字节数组转换为十六进制字符串 
     * 
     * @param data     byte[] 
     * @param toDigits 用于控制输出的char[] 
     * @return 十六进制String 
     */  
    protected static String encodeHexString(byte[] data, char[] toDigits) {  
        return new String(encodeHex(data, toDigits));  
    }  
   
    /** 
     * 将十六进制字符数组转换为字节数组 
     * 
     * @param data 十六进制char[] 
     * @return byte[] 
     * @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常 
     */  
    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;  
    }  
   
    /** 
     * 将十六进制字符转换成一个整数 
     * 
     * @param ch    十六进制char 
     * @param index 十六进制字符在字符数组中的位置 
     * @return 一个整数 
     * @throws RuntimeException 当ch不是一个合法的十六进制字符时,抛出运行时异常 
     */  
    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;  
    }  
   
    /** 
     * 数字字符串转ASCII码字符串 
     *  
     * @param String 
     *            字符串 
     * @return ASCII字符串 
     */  
    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;  
    }  
      
    /** 
     * 十六进制转字符串 
     *  
     * @param hexString 
     *            十六进制字符串 
     * @param encodeType 
     *            编码类型4:Unicode,2:普通编码 
     * @return 字符串 
     */  
    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;  
    }  
      
    /** 
     * 十六进制字符串装十进制 
     *  
     * @param hex 
     *            十六进制字符串 
     * @return 十进制数值 
     */  
    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;  
    }  
      
    /** 
     * 十六转二进制 
     *  
     * @param hex 
     *            十六进制字符串 
     * @return 二进制字符串 
     */  
    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;  
    }  
      
    /** 
     * ASCII码字符串转数字字符串 
     *  
     * @param String 
     *            ASCII字符串 
     * @return 字符串 
     */  
    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;  
    }  
      
    /** 
     * 将十进制转换为指定长度的十六进制字符串 
     *  
     * @param algorism 
     *            int 十进制数字 
     * @param maxLength 
     *            int 转换后的十六进制字符串长度 
     * @return String 转换后的十六进制字符串 
     */  
    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);  
    }  
      
    /** 
     * 字节数组转为普通字符串(ASCII对应的字符) 
     *  
     * @param bytearray 
     *            byte[] 
     * @return String 
     */  
    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;  
    }  
      
    /** 
     * 二进制字符串转十进制 
     *  
     * @param binary 
     *            二进制字符串 
     * @return 十进制数值 
     */  
    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;  
    }  
  
    /** 
     * 十进制转换为十六进制字符串 
     *  
     * @param algorism 
     *            int 十进制的数字 
     * @return String 对应的十六进制字符串 
     */  
    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;  
    }  
      
    /** 
     * HEX字符串前补0,主要用于长度位数不足。 
     *  
     * @param str 
     *            String 需要补充长度的十六进制字符串 
     * @param maxLength 
     *            int 补充后十六进制字符串的长度 
     * @return 补充结果 
     */  
    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;  
    }  
      
    /** 
     * 将一个字符串转换为int 
     *  
     * @param s 
     *            String 要转换的字符串 
     * @param defaultInt 
     *            int 如果出现异常,默认返回的数字 
     * @param radix 
     *            int 要转换的字符串是什么进制的,如16 8 10. 
     * @return int 转换后的数字 
     */  
    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;  
    }  
      
    /** 
     * 将一个十进制形式的数字字符串转换为int 
     *  
     * @param s 
     *            String 要转换的字符串 
     * @param defaultInt 
     *            int 如果出现异常,默认返回的数字 
     * @return int 转换后的数字 
     */  
    public static int parseToInt(String s, int defaultInt) {  
        int i = 0;  
        try {  
            i = Integer.parseInt(s);  
        } catch (NumberFormatException ex) {  
            i = defaultInt;  
        }  
        return i;  
    }  
      
    /** 
     * 十六进制串转化为byte数组 
     *  
     * @return the array of byte 
     */  
    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;  
    }  
      
    /** 
     * 字节数组转换为十六进制字符串 
     *  
     * @param b 
     *            byte[] 需要转换的字节数组 
     * @return String 十六进制字符串 
     */  
    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.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;  
    }  
}

SM3Digest.java

public class SM3Digest {
	 /** SM3值的长度 */  
    private static final int BYTE_LENGTH = 32;  
      
    /** SM3分组长度 */  
    private static final int BLOCK_LENGTH = 64;  
      
    /** 缓冲区长度 */  
    private static final int BUFFER_LENGTH = BLOCK_LENGTH * 1;  
      
    /** 缓冲区 */  
    private byte[] xBuf = new byte[BUFFER_LENGTH];  
      
    /** 缓冲区偏移量 */  
    private int xBufOff;  
      
    /** 初始向量 */  
    private byte[] V = SM3.iv.clone();  
      
    private int cntBlock = 0;  
  
    public SM3Digest() {  
    }  
  
    public SM3Digest(SM3Digest t)  
    {  
        System.arraycopy(t.xBuf, 0, this.xBuf, 0, t.xBuf.length);  
        this.xBufOff = t.xBufOff;  
        System.arraycopy(t.V, 0, this.V, 0, t.V.length);  
    }  
      
    /** 
     * SM3结果输出 
     *  
     * @param out 保存SM3结构的缓冲区 
     * @param outOff 缓冲区偏移量 
     * @return 
     */  
    public int doFinal(byte[] out, int outOff)   
    {  
        byte[] tmp = doFinal();  
        System.arraycopy(tmp, 0, out, 0, tmp.length);  
        return BYTE_LENGTH;  
    }  
  
    public void reset()   
    {  
        xBufOff = 0;  
        cntBlock = 0;  
        V = SM3.iv.clone();  
    }  
  
    /** 
     * 明文输入 
     *  
     * @param in 
     *            明文输入缓冲区 
     * @param inOff 
     *            缓冲区偏移量 
     * @param len 
     *            明文长度 
     */  
    public void update(byte[] in, int inOff, int len)  
    {  
        int partLen = BUFFER_LENGTH - xBufOff;  
        int inputLen = len;  
        int dPos = inOff;  
        if (partLen < inputLen)   
        {  
            System.arraycopy(in, dPos, xBuf, xBufOff, partLen);  
            inputLen -= partLen;  
            dPos += partLen;  
            doUpdate();  
            while (inputLen > BUFFER_LENGTH)   
            {  
                System.arraycopy(in, dPos, xBuf, 0, BUFFER_LENGTH);  
                inputLen -= BUFFER_LENGTH;  
                dPos += BUFFER_LENGTH;  
                doUpdate();  
            }  
        }  
  
        System.arraycopy(in, dPos, xBuf, xBufOff, inputLen);  
        xBufOff += inputLen;  
    }  
  
    private void doUpdate()   
    {  
        byte[] B = new byte[BLOCK_LENGTH];  
        for (int i = 0; i < BUFFER_LENGTH; i += BLOCK_LENGTH)   
        {  
            System.arraycopy(xBuf, i, B, 0, B.length);  
            doHash(B);  
        }  
        xBufOff = 0;  
    }  
  
    private void doHash(byte[] B)  
    {  
        byte[] tmp = SM3.CF(V, B);  
        System.arraycopy(tmp, 0, V, 0, V.length);  
        cntBlock++;  
    }  
  
    private byte[] doFinal()   
    {  
        byte[] B = new byte[BLOCK_LENGTH];  
        byte[] buffer = new byte[xBufOff];  
        System.arraycopy(xBuf, 0, buffer, 0, buffer.length);  
        byte[] tmp = SM3.padding(buffer, cntBlock);  
        for (int i = 0; i < tmp.length; i += BLOCK_LENGTH)  
        {  
            System.arraycopy(tmp, i, B, 0, B.length);  
            doHash(B);  
        }  
        return V;  
    }  
  
    public void update(byte in)   
    {  
        byte[] buffer = new byte[] { in };  
        update(buffer, 0, 1);  
    }  
      
    public int getDigestSize()   
    {  
        return BYTE_LENGTH;  
    }  
      
    public static void main(String[] args)   
    {  
        byte[] md = new byte[32];  
        byte[] msg1 = "ererfeiisgod".getBytes();  
        SM3Digest sm3 = new SM3Digest();  
        sm3.update(msg1, 0, msg1.length);  
        sm3.doFinal(md, 0);  
        String s = new String(Hex.encode(md));  
        System.out.println(s.toUpperCase());  
    }  
}

SM3.java

public class SM3 {
	 public static final byte[] iv = { 0x73, (byte) 0x80, 0x16, 0x6f, 0x49,  
		        0x14, (byte) 0xb2, (byte) 0xb9, 0x17, 0x24, 0x42, (byte) 0xd7,  
		        (byte) 0xda, (byte) 0x8a, 0x06, 0x00, (byte) 0xa9, 0x6f, 0x30,  
		        (byte) 0xbc, (byte) 0x16, 0x31, 0x38, (byte) 0xaa, (byte) 0xe3,  
		        (byte) 0x8d, (byte) 0xee, 0x4d, (byte) 0xb0, (byte) 0xfb, 0x0e,  
		        0x4e };  
		      
		    public static int[] Tj = new int[64];  
		      
		    static   
		    {  
		        for (int i = 0; i < 16; i++)   
		        {  
		            Tj[i] = 0x79cc4519;  
		        }  
		      
		        for (int i = 16; i < 64; i++)   
		        {  
		            Tj[i] = 0x7a879d8a;  
		        }  
		    }  
		  
		    public static byte[] CF(byte[] V, byte[] B)   
		    {  
		        int[] v, b;  
		        v = convert(V);  
		        b = convert(B);  
		        return convert(CF(v, b));  
		    }  
		  
		    private static int[] convert(byte[] arr)  
		    {  
		        int[] out = new int[arr.length / 4];  
		        byte[] tmp = new byte[4];  
		        for (int i = 0; i < arr.length; i += 4)   
		        {  
		            System.arraycopy(arr, i, tmp, 0, 4);  
		            out[i / 4] = bigEndianByteToInt(tmp);  
		        }  
		        return out;  
		    }  
		  
		    private static byte[] convert(int[] arr)   
		    {  
		        byte[] out = new byte[arr.length * 4];  
		        byte[] tmp = null;  
		        for (int i = 0; i < arr.length; i++)   
		        {  
		            tmp = bigEndianIntToByte(arr[i]);  
		            System.arraycopy(tmp, 0, out, i * 4, 4);  
		        }  
		        return out;  
		    }  
		  
		    public static int[] CF(int[] V, int[] B)   
		    {  
		        int a, b, c, d, e, f, g, h;  
		        int ss1, ss2, tt1, tt2;  
		        a = V[0];  
		        b = V[1];  
		        c = V[2];  
		        d = V[3];  
		        e = V[4];  
		        f = V[5];  
		        g = V[6];  
		        h = V[7];  
		          
		        int[][] arr = expand(B);  
		        int[] w = arr[0];  
		        int[] w1 = arr[1];  
		          
		        for (int j = 0; j < 64; j++)  
		        {  
		            ss1 = (bitCycleLeft(a, 12) + e + bitCycleLeft(Tj[j], j));  
		            ss1 = bitCycleLeft(ss1, 7);  
		            ss2 = ss1 ^ bitCycleLeft(a, 12);  
		            tt1 = FFj(a, b, c, j) + d + ss2 + w1[j];  
		            tt2 = GGj(e, f, g, j) + h + ss1 + w[j];  
		            d = c;  
		            c = bitCycleLeft(b, 9);  
		            b = a;  
		            a = tt1;  
		            h = g;  
		            g = bitCycleLeft(f, 19);  
		            f = e;  
		            e = P0(tt2);  
		  
		            /*System.out.print(j+" "); 
		            System.out.print(Integer.toHexString(a)+" "); 
		            System.out.print(Integer.toHexString(b)+" "); 
		            System.out.print(Integer.toHexString(c)+" "); 
		            System.out.print(Integer.toHexString(d)+" "); 
		            System.out.print(Integer.toHexString(e)+" "); 
		            System.out.print(Integer.toHexString(f)+" "); 
		            System.out.print(Integer.toHexString(g)+" "); 
		            System.out.print(Integer.toHexString(h)+" "); 
		            System.out.println("");*/  
		        }  
//		      System.out.println("");  
		  
		        int[] out = new int[8];  
		        out[0] = a ^ V[0];  
		        out[1] = b ^ V[1];  
		        out[2] = c ^ V[2];  
		        out[3] = d ^ V[3];  
		        out[4] = e ^ V[4];  
		        out[5] = f ^ V[5];  
		        out[6] = g ^ V[6];  
		        out[7] = h ^ V[7];  
		  
		        return out;  
		    }  
		  
		    private static int[][] expand(int[] B)   
		    {  
		        int W[] = new int[68];  
		        int W1[] = new int[64];  
		        for (int i = 0; i < B.length; i++)  
		        {  
		            W[i] = B[i];  
		        }  
		  
		        for (int i = 16; i < 68; i++)   
		        {  
		            W[i] = P1(W[i - 16] ^ W[i - 9] ^ bitCycleLeft(W[i - 3], 15))  
		                    ^ bitCycleLeft(W[i - 13], 7) ^ W[i - 6];  
		        }  
		  
		        for (int i = 0; i < 64; i++)   
		        {  
		            W1[i] = W[i] ^ W[i + 4];  
		        }  
		  
		        int arr[][] = new int[][] { W, W1 };  
		        return arr;  
		    }  
		  
		    private static byte[] bigEndianIntToByte(int num)   
		    {  
		        return back(Util.intToBytes(num));  
		    }  
		  
		    private static int bigEndianByteToInt(byte[] bytes)  
		    {  
		        return Util.byteToInt(back(bytes));  
		    }  
		  
		    private static int FFj(int X, int Y, int Z, int j)   
		    {  
		        if (j >= 0 && j <= 15)   
		        {  
		            return FF1j(X, Y, Z);  
		        }  
		        else   
		        {  
		            return FF2j(X, Y, Z);  
		        }  
		    }  
		  
		    private static int GGj(int X, int Y, int Z, int j)   
		    {  
		        if (j >= 0 && j <= 15)   
		        {  
		            return GG1j(X, Y, Z);  
		        }  
		        else  
		        {  
		            return GG2j(X, Y, Z);  
		        }  
		    }  
		  
		    // 逻辑位运算函数  
		    private static int FF1j(int X, int Y, int Z)  
		    {  
		        int tmp = X ^ Y ^ Z;  
		        return tmp;  
		    }  
		  
		    private static int FF2j(int X, int Y, int Z)  
		    {  
		        int tmp = ((X & Y) | (X & Z) | (Y & Z));  
		        return tmp;  
		    }  
		  
		    private static int GG1j(int X, int Y, int Z)   
		    {  
		        int tmp = X ^ Y ^ Z;  
		        return tmp;  
		    }  
		  
		    private static int GG2j(int X, int Y, int Z)   
		    {  
		        int tmp = (X & Y) | (~X & Z);  
		        return tmp;  
		    }  
		  
		    private static int P0(int X)   
		    {  
		        int y = rotateLeft(X, 9);  
		        y = bitCycleLeft(X, 9);  
		        int z = rotateLeft(X, 17);  
		        z = bitCycleLeft(X, 17);  
		        int t = X ^ y ^ z;  
		        return t;  
		    }  
		  
		    private static int P1(int X)   
		    {  
		        int t = X ^ bitCycleLeft(X, 15) ^ bitCycleLeft(X, 23);  
		        return t;  
		    }  
		  
		    /** 
		     * 对最后一个分组字节数据padding 
		     *  
		     * @param in 
		     * @param bLen 
		     *            分组个数 
		     * @return 
		     */  
		    public static byte[] padding(byte[] in, int bLen)  
		    {  
		        int k = 448 - (8 * in.length + 1) % 512;  
		        if (k < 0)   
		        {  
		            k = 960 - (8 * in.length + 1) % 512;  
		        }  
		        k += 1;  
		        byte[] padd = new byte[k / 8];  
		        padd[0] = (byte) 0x80;  
		        long n = in.length * 8 + bLen * 512;  
		        byte[] out = new byte[in.length + k / 8 + 64 / 8];  
		        int pos = 0;  
		        System.arraycopy(in, 0, out, 0, in.length);  
		        pos += in.length;  
		        System.arraycopy(padd, 0, out, pos, padd.length);  
		        pos += padd.length;  
		        byte[] tmp = back(Util.longToBytes(n));  
		        System.arraycopy(tmp, 0, out, pos, tmp.length);  
		        return out;  
		    }  
		  
		    /** 
		     * 字节数组逆序 
		     *  
		     * @param in 
		     * @return 
		     */  
		    private static byte[] back(byte[] in)   
		    {  
		        byte[] out = new byte[in.length];  
		        for (int i = 0; i < out.length; i++)   
		        {  
		            out[i] = in[out.length - i - 1];  
		        }  
		  
		        return out;  
		    }  
		  
		    public static int rotateLeft(int x, int n)   
		    {  
		        return (x << n) | (x >> (32 - n));  
		    }  
		  
		    private static int bitCycleLeft(int n, int bitLen)   
		    {  
		        bitLen %= 32;  
		        byte[] tmp = bigEndianIntToByte(n);  
		        int byteLen = bitLen / 8;  
		        int len = bitLen % 8;  
		        if (byteLen > 0)  
		        {  
		            tmp = byteCycleLeft(tmp, byteLen);  
		        }  
		  
		        if (len > 0)   
		        {  
		            tmp = bitSmall8CycleLeft(tmp, len);  
		        }  
		  
		        return bigEndianByteToInt(tmp);  
		    }  
		  
		    private static byte[] bitSmall8CycleLeft(byte[] in, int len)   
		    {  
		        byte[] tmp = new byte[in.length];  
		        int t1, t2, t3;  
		        for (int i = 0; i < tmp.length; i++)  
		        {  
		            t1 = (byte) ((in[i] & 0x000000ff) << len);  
		            t2 = (byte) ((in[(i + 1) % tmp.length] & 0x000000ff) >> (8 - len));  
		            t3 = (byte) (t1 | t2);  
		            tmp[i] = (byte) t3;  
		        }  
		  
		        return tmp;  
		    }  
		  
		    private static byte[] byteCycleLeft(byte[] in, int byteLen)   
		    {  
		        byte[] tmp = new byte[in.length];  
		        System.arraycopy(in, byteLen, tmp, 0, in.length - byteLen);  
		        System.arraycopy(in, 0, tmp, in.length - byteLen, byteLen);  
		        return tmp;  
		    }  
}

SM2.java

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);  
    }  
}

SM2Utils.java

public class SM2Utils {
	  //生成随机秘钥对  
    public static void 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();  
          
        System.out.println("公钥: " + Util.byteToHex(publicKey.getEncoded()));  
        System.out.println("私钥: " + Util.byteToHex(privateKey.toByteArray()));  
    }  
      
    //数据加密  
    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);  
          
//      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拼装成加密字串  
        return Util.byteToHex(c1.getEncoded()) + Util.byteToHex(source) + Util.byteToHex(c3);  
          
    }  
      
    //数据解密  
    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);  
        /***分解加密字串 
         * (C1 = C1标志位2位 + C1实体部分128位 = 130) 
         * (C3 = C3实体部分64位  = 64) 
         * (C2 = encryptedData.length * 2 - C1长度  - C2长度) 
         */  
        byte[] c1Bytes = Util.hexToByte(data.substring(0,130));  
        int c2Len = encryptedData.length - 97;  
        byte[] c2 = Util.hexToByte(data.substring(130,130 + 2 * c2Len));  
        byte[] c3 = Util.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   
    {  
        //生成密钥对  秘钥内容  
        generateKeyPair();  
          
        String plainText = Md5.encode("888888")+"000BA2DAC3E4107863740E2REDQ10D6C";  
        byte[] sourceData = plainText.getBytes();  
                
        System.out.println("加密: ");  
        String cipherText = SM2Utils.encrypt(Util.hexToByte(Constants.publicKey), sourceData);  
        System.out.println(cipherText);  
        System.out.println("解密: ");  
        
        plainText = new String(SM2Utils.decrypt(Util.hexToByte(Constants.privateKey), Util.hexToByte(cipherText )));  
        System.out.println(plainText);  
          
    }  
}

SM2Utils.java 中generateKeyPair();

 String plainText = "加密内容";  
        byte[] sourceData = plainText.getBytes();  
                
        System.out.println("加密: ");  
        String cipherText = SM2Utils.encrypt(Util.hexToByte(Constants.publicKey), sourceData);    //Constants.publicKey 为加密密钥,从generateKeyPair()中获取;
        System.out.println(cipherText);  
        System.out.println("解密: ");  
        
        plainText = new String(SM2Utils.decrypt(Util.hexToByte(Constants.privateKey), Util.hexToByte("")));    //Constants.privateKey 为解密密钥,从generateKeyPair()中获取;
        System.out.println(plainText); 

 

        由于密码服务是信息化安全建设的基础服务,密码的国产化改造和推广就成为我们重要的历史使命。对于国产的产品,加快国产算法模块的改造和应用,真正让国产算法为信息系统的安全自主可控;对于从业者来说,就要不断对用户灌输使用国产密码算法以及尽快升级到国产算法的思想。只有从以上这两个方面入手并且持之以恒,相信国家提出的信息安全领域的自主可控战略最终就会实现。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值