国密算法SM2、SM3、SM4详解

本文主要讲解“国密加密算法”SM系列的Java实现方法,不涉及具体的算法剖析,在网络上找到的java实现方法比较少,切在跨语言加密解密上会存在一些问题,所以整理此文志之。

源码下载地址http://download.csdn.net/detail/ererfei/9474502 需要C#实现SM系列算法源码的可以评论留邮箱地址,看到后发送

1.SM2 & SM3

由于SM2算法中需要使用SM3摘要算法,所以把他们放在一起

项目目录结构如下:


首先要下载一个jar包——bcprov-jdk.jar,可以到maven库中下载最新版http://central.maven.org/maven2/org/bouncycastle/并将该jar包引入项目的classpath。实现代码如下(每个工具类都有Main可以运行测试):

a.      SM2主类

【SM2.java】

 

[java]  view plain  copy
  1. package com.mlq.sm;  
  2.   
  3. import java.math.BigInteger;  
  4. import java.security.SecureRandom;  
  5.   
  6. import org.bouncycastle.crypto.generators.ECKeyPairGenerator;  
  7. import org.bouncycastle.crypto.params.ECDomainParameters;  
  8. import org.bouncycastle.crypto.params.ECKeyGenerationParameters;  
  9. import org.bouncycastle.math.ec.ECCurve;  
  10. import org.bouncycastle.math.ec.ECFieldElement;  
  11. import org.bouncycastle.math.ec.ECPoint;  
  12. import org.bouncycastle.math.ec.ECFieldElement.Fp;  
  13.   
  14. public class SM2   
  15. {  
  16.     //测试参数  
  17. //  public static final String[] ecc_param = {  
  18. //      "8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3",   
  19. //      "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498",   
  20. //      "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A",   
  21. //      "8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7",   
  22. //      "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D",   
  23. //      "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2"   
  24. //  };  
  25.       
  26.     //正式参数  
  27.     public static String[] ecc_param = {   
  28.         "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",  
  29.         "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",  
  30.         "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",  
  31.         "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",  
  32.         "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",  
  33.         "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"  
  34.     };  
  35.   
  36.     public static SM2 Instance()   
  37.     {  
  38.         return new SM2();  
  39.     }  
  40.   
  41.     public final BigInteger ecc_p;  
  42.     public final BigInteger ecc_a;  
  43.     public final BigInteger ecc_b;  
  44.     public final BigInteger ecc_n;  
  45.     public final BigInteger ecc_gx;  
  46.     public final BigInteger ecc_gy;  
  47.     public final ECCurve ecc_curve;  
  48.     public final ECPoint ecc_point_g;  
  49.     public final ECDomainParameters ecc_bc_spec;  
  50.     public final ECKeyPairGenerator ecc_key_pair_generator;  
  51.     public final ECFieldElement ecc_gx_fieldelement;  
  52.     public final ECFieldElement ecc_gy_fieldelement;  
  53.   
  54.     public SM2()   
  55.     {  
  56.         this.ecc_p = new BigInteger(ecc_param[0], 16);  
  57.         this.ecc_a = new BigInteger(ecc_param[1], 16);  
  58.         this.ecc_b = new BigInteger(ecc_param[2], 16);  
  59.         this.ecc_n = new BigInteger(ecc_param[3], 16);  
  60.         this.ecc_gx = new BigInteger(ecc_param[4], 16);  
  61.         this.ecc_gy = new BigInteger(ecc_param[5], 16);  
  62.   
  63.         this.ecc_gx_fieldelement = new Fp(this.ecc_p, this.ecc_gx);  
  64.         this.ecc_gy_fieldelement = new Fp(this.ecc_p, this.ecc_gy);  
  65.   
  66.         this.ecc_curve = new ECCurve.Fp(this.ecc_p, this.ecc_a, this.ecc_b);  
  67.         this.ecc_point_g = new ECPoint.Fp(this.ecc_curve, this.ecc_gx_fieldelement, this.ecc_gy_fieldelement);  
  68.   
  69.         this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, this.ecc_n);  
  70.   
  71.         ECKeyGenerationParameters ecc_ecgenparam;  
  72.         ecc_ecgenparam = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom());  
  73.   
  74.         this.ecc_key_pair_generator = new ECKeyPairGenerator();  
  75.         this.ecc_key_pair_generator.init(ecc_ecgenparam);  
  76.     }  
  77. }  

b.      SM2工具类

【SM2Utils.java】

 

[java]  view plain  copy
  1. package com.mlq.sm;  
  2.   
  3. import java.io.IOException;  
  4. import java.math.BigInteger;  
  5. import org.bouncycastle.crypto.AsymmetricCipherKeyPair;  
  6. import org.bouncycastle.crypto.params.ECPrivateKeyParameters;  
  7. import org.bouncycastle.crypto.params.ECPublicKeyParameters;  
  8. import org.bouncycastle.math.ec.ECPoint;  
  9.   
  10. public class SM2Utils   
  11. {  
  12.     //生成随机秘钥对  
  13.     public static void generateKeyPair(){  
  14.         SM2 sm2 = SM2.Instance();  
  15.         AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair();  
  16.         ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();  
  17.         ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();  
  18.         BigInteger privateKey = ecpriv.getD();  
  19.         ECPoint publicKey = ecpub.getQ();  
  20.           
  21.         System.out.println("公钥: " + Util.byteToHex(publicKey.getEncoded()));  
  22.         System.out.println("私钥: " + Util.byteToHex(privateKey.toByteArray()));  
  23.     }  
  24.       
  25.     //数据加密  
  26.     public static String encrypt(byte[] publicKey, byte[] data) throws IOException  
  27.     {  
  28.         if (publicKey == null || publicKey.length == 0)  
  29.         {  
  30.             return null;  
  31.         }  
  32.           
  33.         if (data == null || data.length == 0)  
  34.         {  
  35.             return null;  
  36.         }  
  37.           
  38.         byte[] source = new byte[data.length];  
  39.         System.arraycopy(data, 0, source, 0, data.length);  
  40.           
  41.         Cipher cipher = new Cipher();  
  42.         SM2 sm2 = SM2.Instance();  
  43.         ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);  
  44.           
  45.         ECPoint c1 = cipher.Init_enc(sm2, userKey);  
  46.         cipher.Encrypt(source);  
  47.         byte[] c3 = new byte[32];  
  48.         cipher.Dofinal(c3);  
  49.           
  50. //      System.out.println("C1 " + Util.byteToHex(c1.getEncoded()));  
  51. //      System.out.println("C2 " + Util.byteToHex(source));  
  52. //      System.out.println("C3 " + Util.byteToHex(c3));  
  53.         //C1 C2 C3拼装成加密字串  
  54.         return Util.byteToHex(c1.getEncoded()) + Util.byteToHex(source) + Util.byteToHex(c3);  
  55.           
  56.     }  
  57.       
  58.     //数据解密  
  59.     public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException  
  60.     {  
  61.         if (privateKey == null || privateKey.length == 0)  
  62.         {  
  63.             return null;  
  64.         }  
  65.           
  66.         if (encryptedData == null || encryptedData.length == 0)  
  67.         {  
  68.             return null;  
  69.         }  
  70.         //加密字节数组转换为十六进制的字符串 长度变为encryptedData.length * 2  
  71.         String data = Util.byteToHex(encryptedData);  
  72.         /***分解加密字串 
  73.          * (C1 = C1标志位2位 + C1实体部分128位 = 130) 
  74.          * (C3 = C3实体部分64位  = 64) 
  75.          * (C2 = encryptedData.length * 2 - C1长度  - C2长度) 
  76.          */  
  77.         byte[] c1Bytes = Util.hexToByte(data.substring(0,130));  
  78.         int c2Len = encryptedData.length - 97;  
  79.         byte[] c2 = Util.hexToByte(data.substring(130,130 + 2 * c2Len));  
  80.         byte[] c3 = Util.hexToByte(data.substring(130 + 2 * c2Len,194 + 2 * c2Len));  
  81.           
  82.         SM2 sm2 = SM2.Instance();  
  83.         BigInteger userD = new BigInteger(1, privateKey);  
  84.           
  85.         //通过C1实体字节来生成ECPoint  
  86.         ECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes);  
  87.         Cipher cipher = new Cipher();  
  88.         cipher.Init_dec(userD, c1);  
  89.         cipher.Decrypt(c2);  
  90.         cipher.Dofinal(c3);  
  91.           
  92.         //返回解密结果  
  93.         return c2;  
  94.     }  
  95.       
  96.     public static void main(String[] args) throws Exception   
  97.     {  
  98.         //生成密钥对  
  99.         generateKeyPair();  
  100.           
  101.         String plainText = "ererfeiisgod";  
  102.         byte[] sourceData = plainText.getBytes();  
  103.           
  104.         //下面的秘钥可以使用generateKeyPair()生成的秘钥内容  
  105.         // 国密规范正式私钥  
  106.         String prik = "3690655E33D5EA3D9A4AE1A1ADD766FDEA045CDEAA43A9206FB8C430CEFE0D94";  
  107.         // 国密规范正式公钥  
  108.         String pubk = "04F6E0C3345AE42B51E06BF50B98834988D54EBC7460FE135A48171BC0629EAE205EEDE253A530608178A98F1E19BB737302813BA39ED3FA3C51639D7A20C7391A";  
  109.           
  110.         System.out.println("加密: ");  
  111.         String cipherText = SM2Utils.encrypt(Util.hexToByte(pubk), sourceData);  
  112.         System.out.println(cipherText);  
  113.         System.out.println("解密: ");  
  114.         plainText = new String(SM2Utils.decrypt(Util.hexToByte(prik), Util.hexToByte(cipherText)));  
  115.         System.out.println(plainText);  
  116.           
  117.     }  
  118. }  

c.      SM3主类

【SM3.java】

 

[java]  view plain  copy
  1. package com.mlq.sm;  
  2.   
  3. public class SM3   
  4. {  
  5.     public static final byte[] iv = { 0x73, (byte0x800x160x6f0x49,  
  6.         0x14, (byte0xb2, (byte0xb90x170x240x42, (byte0xd7,  
  7.         (byte0xda, (byte0x8a0x060x00, (byte0xa90x6f0x30,  
  8.         (byte0xbc, (byte0x160x310x38, (byte0xaa, (byte0xe3,  
  9.         (byte0x8d, (byte0xee0x4d, (byte0xb0, (byte0xfb0x0e,  
  10.         0x4e };  
  11.       
  12.     public static int[] Tj = new int[64];  
  13.       
  14.     static   
  15.     {  
  16.         for (int i = 0; i < 16; i++)   
  17.         {  
  18.             Tj[i] = 0x79cc4519;  
  19.         }  
  20.       
  21.         for (int i = 16; i < 64; i++)   
  22.         {  
  23.             Tj[i] = 0x7a879d8a;  
  24.         }  
  25.     }  
  26.   
  27.     public static byte[] CF(byte[] V, byte[] B)   
  28.     {  
  29.         int[] v, b;  
  30.         v = convert(V);  
  31.         b = convert(B);  
  32.         return convert(CF(v, b));  
  33.     }  
  34.   
  35.     private static int[] convert(byte[] arr)  
  36.     {  
  37.         int[] out = new int[arr.length / 4];  
  38.         byte[] tmp = new byte[4];  
  39.         for (int i = 0; i < arr.length; i += 4)   
  40.         {  
  41.             System.arraycopy(arr, i, tmp, 04);  
  42.             out[i / 4] = bigEndianByteToInt(tmp);  
  43.         }  
  44.         return out;  
  45.     }  
  46.   
  47.     private static byte[] convert(int[] arr)   
  48.     {  
  49.         byte[] out = new byte[arr.length * 4];  
  50.         byte[] tmp = null;  
  51.         for (int i = 0; i < arr.length; i++)   
  52.         {  
  53.             tmp = bigEndianIntToByte(arr[i]);  
  54.             System.arraycopy(tmp, 0, out, i * 44);  
  55.         }  
  56.         return out;  
  57.     }  
  58.   
  59.     public static int[] CF(int[] V, int[] B)   
  60.     {  
  61.         int a, b, c, d, e, f, g, h;  
  62.         int ss1, ss2, tt1, tt2;  
  63.         a = V[0];  
  64.         b = V[1];  
  65.         c = V[2];  
  66.         d = V[3];  
  67.         e = V[4];  
  68.         f = V[5];  
  69.         g = V[6];  
  70.         h = V[7];  
  71.           
  72.         int[][] arr = expand(B);  
  73.         int[] w = arr[0];  
  74.         int[] w1 = arr[1];  
  75.           
  76.         for (int j = 0; j < 64; j++)  
  77.         {  
  78.             ss1 = (bitCycleLeft(a, 12) + e + bitCycleLeft(Tj[j], j));  
  79.             ss1 = bitCycleLeft(ss1, 7);  
  80.             ss2 = ss1 ^ bitCycleLeft(a, 12);  
  81.             tt1 = FFj(a, b, c, j) + d + ss2 + w1[j];  
  82.             tt2 = GGj(e, f, g, j) + h + ss1 + w[j];  
  83.             d = c;  
  84.             c = bitCycleLeft(b, 9);  
  85.             b = a;  
  86.             a = tt1;  
  87.             h = g;  
  88.             g = bitCycleLeft(f, 19);  
  89.             f = e;  
  90.             e = P0(tt2);  
  91.   
  92.             /*System.out.print(j+" "); 
  93.             System.out.print(Integer.toHexString(a)+" "); 
  94.             System.out.print(Integer.toHexString(b)+" "); 
  95.             System.out.print(Integer.toHexString(c)+" "); 
  96.             System.out.print(Integer.toHexString(d)+" "); 
  97.             System.out.print(Integer.toHexString(e)+" "); 
  98.             System.out.print(Integer.toHexString(f)+" "); 
  99.             System.out.print(Integer.toHexString(g)+" "); 
  100.             System.out.print(Integer.toHexString(h)+" "); 
  101.             System.out.println("");*/  
  102.         }  
  103. //      System.out.println("");  
  104.   
  105.         int[] out = new int[8];  
  106.         out[0] = a ^ V[0];  
  107.         out[1] = b ^ V[1];  
  108.         out[2] = c ^ V[2];  
  109.         out[3] = d ^ V[3];  
  110.         out[4] = e ^ V[4];  
  111.         out[5] = f ^ V[5];  
  112.         out[6] = g ^ V[6];  
  113.         out[7] = h ^ V[7];  
  114.   
  115.         return out;  
  116.     }  
  117.   
  118.     private static int[][] expand(int[] B)   
  119.     {  
  120.         int W[] = new int[68];  
  121.         int W1[] = new int[64];  
  122.         for (int i = 0; i < B.length; i++)  
  123.         {  
  124.             W[i] = B[i];  
  125.         }  
  126.   
  127.         for (int i = 16; i < 68; i++)   
  128.         {  
  129.             W[i] = P1(W[i - 16] ^ W[i - 9] ^ bitCycleLeft(W[i - 3], 15))  
  130.                     ^ bitCycleLeft(W[i - 13], 7) ^ W[i - 6];  
  131.         }  
  132.   
  133.         for (int i = 0; i < 64; i++)   
  134.         {  
  135.             W1[i] = W[i] ^ W[i + 4];  
  136.         }  
  137.   
  138.         int arr[][] = new int[][] { W, W1 };  
  139.         return arr;  
  140.     }  
  141.   
  142.     private static byte[] bigEndianIntToByte(int num)   
  143.     {  
  144.         return back(Util.intToBytes(num));  
  145.     }  
  146.   
  147.     private static int bigEndianByteToInt(byte[] bytes)  
  148.     {  
  149.         return Util.byteToInt(back(bytes));  
  150.     }  
  151.   
  152.     private static int FFj(int X, int Y, int Z, int j)   
  153.     {  
  154.         if (j >= 0 && j <= 15)   
  155.         {  
  156.             return FF1j(X, Y, Z);  
  157.         }  
  158.         else   
  159.         {  
  160.             return FF2j(X, Y, Z);  
  161.         }  
  162.     }  
  163.   
  164.     private static int GGj(int X, int Y, int Z, int j)   
  165.     {  
  166.         if (j >= 0 && j <= 15)   
  167.         {  
  168.             return GG1j(X, Y, Z);  
  169.         }  
  170.         else  
  171.         {  
  172.             return GG2j(X, Y, Z);  
  173.         }  
  174.     }  
  175.   
  176.     // 逻辑位运算函数  
  177.     private static int FF1j(int X, int Y, int Z)  
  178.     {  
  179.         int tmp = X ^ Y ^ Z;  
  180.         return tmp;  
  181.     }  
  182.   
  183.     private static int FF2j(int X, int Y, int Z)  
  184.     {  
  185.         int tmp = ((X & Y) | (X & Z) | (Y & Z));  
  186.         return tmp;  
  187.     }  
  188.   
  189.     private static int GG1j(int X, int Y, int Z)   
  190.     {  
  191.         int tmp = X ^ Y ^ Z;  
  192.         return tmp;  
  193.     }  
  194.   
  195.     private static int GG2j(int X, int Y, int Z)   
  196.     {  
  197.         int tmp = (X & Y) | (~X & Z);  
  198.         return tmp;  
  199.     }  
  200.   
  201.     private static int P0(int X)   
  202.     {  
  203.         int y = rotateLeft(X, 9);  
  204.         y = bitCycleLeft(X, 9);  
  205.         int z = rotateLeft(X, 17);  
  206.         z = bitCycleLeft(X, 17);  
  207.         int t = X ^ y ^ z;  
  208.         return t;  
  209.     }  
  210.   
  211.     private static int P1(int X)   
  212.     {  
  213.         int t = X ^ bitCycleLeft(X, 15) ^ bitCycleLeft(X, 23);  
  214.         return t;  
  215.     }  
  216.   
  217.     /** 
  218.      * 对最后一个分组字节数据padding 
  219.      *  
  220.      * @param in 
  221.      * @param bLen 
  222.      *            分组个数 
  223.      * @return 
  224.      */  
  225.     public static byte[] padding(byte[] in, int bLen)  
  226.     {  
  227.         int k = 448 - (8 * in.length + 1) % 512;  
  228.         if (k < 0)   
  229.         {  
  230.             k = 960 - (8 * in.length + 1) % 512;  
  231.         }  
  232.         k += 1;  
  233.         byte[] padd = new byte[k / 8];  
  234.         padd[0] = (byte0x80;  
  235.         long n = in.length * 8 + bLen * 512;  
  236.         byte[] out = new byte[in.length + k / 8 + 64 / 8];  
  237.         int pos = 0;  
  238.         System.arraycopy(in, 0, out, 0, in.length);  
  239.         pos += in.length;  
  240.         System.arraycopy(padd, 0, out, pos, padd.length);  
  241.         pos += padd.length;  
  242.         byte[] tmp = back(Util.longToBytes(n));  
  243.         System.arraycopy(tmp, 0, out, pos, tmp.length);  
  244.         return out;  
  245.     }  
  246.   
  247.     /** 
  248.      * 字节数组逆序 
  249.      *  
  250.      * @param in 
  251.      * @return 
  252.      */  
  253.     private static byte[] back(byte[] in)   
  254.     {  
  255.         byte[] out = new byte[in.length];  
  256.         for (int i = 0; i < out.length; i++)   
  257.         {  
  258.             out[i] = in[out.length - i - 1];  
  259.         }  
  260.   
  261.         return out;  
  262.     }  
  263.   
  264.     public static int rotateLeft(int x, int n)   
  265.     {  
  266.         return (x << n) | (x >> (32 - n));  
  267.     }  
  268.   
  269.     private static int bitCycleLeft(int n, int bitLen)   
  270.     {  
  271.         bitLen %= 32;  
  272.         byte[] tmp = bigEndianIntToByte(n);  
  273.         int byteLen = bitLen / 8;  
  274.         int len = bitLen % 8;  
  275.         if (byteLen > 0)  
  276.         {  
  277.             tmp = byteCycleLeft(tmp, byteLen);  
  278.         }  
  279.   
  280.         if (len > 0)   
  281.         {  
  282.             tmp = bitSmall8CycleLeft(tmp, len);  
  283.         }  
  284.   
  285.         return bigEndianByteToInt(tmp);  
  286.     }  
  287.   
  288.     private static byte[] bitSmall8CycleLeft(byte[] in, int len)   
  289.     {  
  290.         byte[] tmp = new byte[in.length];  
  291.         int t1, t2, t3;  
  292.         for (int i = 0; i < tmp.length; i++)  
  293.         {  
  294.             t1 = (byte) ((in[i] & 0x000000ff) << len);  
  295.             t2 = (byte) ((in[(i + 1) % tmp.length] & 0x000000ff) >> (8 - len));  
  296.             t3 = (byte) (t1 | t2);  
  297.             tmp[i] = (byte) t3;  
  298.         }  
  299.   
  300.         return tmp;  
  301.     }  
  302.   
  303.     private static byte[] byteCycleLeft(byte[] in, int byteLen)   
  304.     {  
  305.         byte[] tmp = new byte[in.length];  
  306.         System.arraycopy(in, byteLen, tmp, 0, in.length - byteLen);  
  307.         System.arraycopy(in, 0, tmp, in.length - byteLen, byteLen);  
  308.         return tmp;  
  309.     }  
  310. }  

d.      SM3工具类

【SM3Digest.java】

 

[java]  view plain  copy
  1. package com.mlq.sm;  
  2.   
  3. import org.bouncycastle.util.encoders.Hex;  
  4.   
  5. public class SM3Digest  
  6. {  
  7.     /** SM3值的长度 */  
  8.     private static final int BYTE_LENGTH = 32;  
  9.       
  10.     /** SM3分组长度 */  
  11.     private static final int BLOCK_LENGTH = 64;  
  12.       
  13.     /** 缓冲区长度 */  
  14.     private static final int BUFFER_LENGTH = BLOCK_LENGTH * 1;  
  15.       
  16.     /** 缓冲区 */  
  17.     private byte[] xBuf = new byte[BUFFER_LENGTH];  
  18.       
  19.     /** 缓冲区偏移量 */  
  20.     private int xBufOff;  
  21.       
  22.     /** 初始向量 */  
  23.     private byte[] V = SM3.iv.clone();  
  24.       
  25.     private int cntBlock = 0;  
  26.   
  27.     public SM3Digest() {  
  28.     }  
  29.   
  30.     public SM3Digest(SM3Digest t)  
  31.     {  
  32.         System.arraycopy(t.xBuf, 0this.xBuf, 0, t.xBuf.length);  
  33.         this.xBufOff = t.xBufOff;  
  34.         System.arraycopy(t.V, 0this.V, 0, t.V.length);  
  35.     }  
  36.       
  37.     /** 
  38.      * SM3结果输出 
  39.      *  
  40.      * @param out 保存SM3结构的缓冲区 
  41.      * @param outOff 缓冲区偏移量 
  42.      * @return 
  43.      */  
  44.     public int doFinal(byte[] out, int outOff)   
  45.     {  
  46.         byte[] tmp = doFinal();  
  47.         System.arraycopy(tmp, 0, out, 0, tmp.length);  
  48.         return BYTE_LENGTH;  
  49.     }  
  50.   
  51.     public void reset()   
  52.     {  
  53.         xBufOff = 0;  
  54.         cntBlock = 0;  
  55.         V = SM3.iv.clone();  
  56.     }  
  57.   
  58.     /** 
  59.      * 明文输入 
  60.      *  
  61.      * @param in 
  62.      *            明文输入缓冲区 
  63.      * @param inOff 
  64.      *            缓冲区偏移量 
  65.      * @param len 
  66.      *            明文长度 
  67.      */  
  68.     public void update(byte[] in, int inOff, int len)  
  69.     {  
  70.         int partLen = BUFFER_LENGTH - xBufOff;  
  71.         int inputLen = len;  
  72.         int dPos = inOff;  
  73.         if (partLen < inputLen)   
  74.         {  
  75.             System.arraycopy(in, dPos, xBuf, xBufOff, partLen);  
  76.             inputLen -= partLen;  
  77.             dPos += partLen;  
  78.             doUpdate();  
  79.             while (inputLen > BUFFER_LENGTH)   
  80.             {  
  81.                 System.arraycopy(in, dPos, xBuf, 0, BUFFER_LENGTH);  
  82.                 inputLen -= BUFFER_LENGTH;  
  83.                 dPos += BUFFER_LENGTH;  
  84.                 doUpdate();  
  85.             }  
  86.         }  
  87.   
  88.         System.arraycopy(in, dPos, xBuf, xBufOff, inputLen);  
  89.         xBufOff += inputLen;  
  90.     }  
  91.   
  92.     private void doUpdate()   
  93.     {  
  94.         byte[] B = new byte[BLOCK_LENGTH];  
  95.         for (int i = 0; i < BUFFER_LENGTH; i += BLOCK_LENGTH)   
  96.         {  
  97.             System.arraycopy(xBuf, i, B, 0, B.length);  
  98.             doHash(B);  
  99.         }  
  100.         xBufOff = 0;  
  101.     }  
  102.   
  103.     private void doHash(byte[] B)  
  104.     {  
  105.         byte[] tmp = SM3.CF(V, B);  
  106.         System.arraycopy(tmp, 0, V, 0, V.length);  
  107.         cntBlock++;  
  108.     }  
  109.   
  110.     private byte[] doFinal()   
  111.     {  
  112.         byte[] B = new byte[BLOCK_LENGTH];  
  113.         byte[] buffer = new byte[xBufOff];  
  114.         System.arraycopy(xBuf, 0, buffer, 0, buffer.length);  
  115.         byte[] tmp = SM3.padding(buffer, cntBlock);  
  116.         for (int i = 0; i < tmp.length; i += BLOCK_LENGTH)  
  117.         {  
  118.             System.arraycopy(tmp, i, B, 0, B.length);  
  119.             doHash(B);  
  120.         }  
  121.         return V;  
  122.     }  
  123.   
  124.     public void update(byte in)   
  125.     {  
  126.         byte[] buffer = new byte[] { in };  
  127.         update(buffer, 01);  
  128.     }  
  129.       
  130.     public int getDigestSize()   
  131.     {  
  132.         return BYTE_LENGTH;  
  133.     }  
  134.       
  135.     public static void main(String[] args)   
  136.     {  
  137.         byte[] md = new byte[32];  
  138.         byte[] msg1 = "ererfeiisgod".getBytes();  
  139.         SM3Digest sm3 = new SM3Digest();  
  140.         sm3.update(msg1, 0, msg1.length);  
  141.         sm3.doFinal(md, 0);  
  142.         String s = new String(Hex.encode(md));  
  143.         System.out.println(s.toUpperCase());  
  144.     }  
  145. }  

e.      工具类

【Util.java】

[java]  view plain  copy
  1. package com.mlq.sm;  
  2.   
  3. import java.math.BigInteger;  
  4.   
  5. public class Util   
  6. {  
  7.     /** 
  8.      * 整形转换成网络传输的字节流(字节数组)型数据 
  9.      *  
  10.      * @param num 一个整型数据 
  11.      * @return 4个字节的自己数组 
  12.      */  
  13.     public static byte[] intToBytes(int num)  
  14.     {  
  15.         byte[] bytes = new byte[4];  
  16.         bytes[0] = (byte) (0xff & (num >> 0));  
  17.         bytes[1] = (byte) (0xff & (num >> 8));  
  18.         bytes[2] = (byte) (0xff & (num >> 16));  
  19.         bytes[3] = (byte) (0xff & (num >> 24));  
  20.         return bytes;  
  21.     }  
  22.   
  23.     /** 
  24.      * 四个字节的字节数据转换成一个整形数据 
  25.      *  
  26.      * @param bytes 4个字节的字节数组 
  27.      * @return 一个整型数据 
  28.      */  
  29.     public static int byteToInt(byte[] bytes)   
  30.     {  
  31.         int num = 0;  
  32.         int temp;  
  33.         temp = (0x000000ff & (bytes[0])) << 0;  
  34.         num = num | temp;  
  35.         temp = (0x000000ff & (bytes[1])) << 8;  
  36.         num = num | temp;  
  37.         temp = (0x000000ff & (bytes[2])) << 16;  
  38.         num = num | temp;  
  39.         temp = (0x000000ff & (bytes[3])) << 24;  
  40.         num = num | temp;  
  41.         return num;  
  42.     }  
  43.   
  44.     /** 
  45.      * 长整形转换成网络传输的字节流(字节数组)型数据 
  46.      *  
  47.      * @param num 一个长整型数据 
  48.      * @return 4个字节的自己数组 
  49.      */  
  50.     public static byte[] longToBytes(long num)   
  51.     {  
  52.         byte[] bytes = new byte[8];  
  53.         for (int i = 0; i < 8; i++)   
  54.         {  
  55.             bytes[i] = (byte) (0xff & (num >> (i * 8)));  
  56.         }  
  57.   
  58.         return bytes;  
  59.     }  
  60.   
  61.     /** 
  62.      * 大数字转换字节流(字节数组)型数据 
  63.      *  
  64.      * @param n 
  65.      * @return 
  66.      */  
  67.     public static byte[] byteConvert32Bytes(BigInteger n)   
  68.     {  
  69.         byte tmpd[] = (byte[])null;  
  70.         if(n == null)  
  71.         {  
  72.             return null;  
  73.         }  
  74.           
  75.         if(n.toByteArray().length == 33)  
  76.         {  
  77.             tmpd = new byte[32];  
  78.             System.arraycopy(n.toByteArray(), 1, tmpd, 032);  
  79.         }   
  80.         else if(n.toByteArray().length == 32)  
  81.         {  
  82.             tmpd = n.toByteArray();  
  83.         }   
  84.         else  
  85.         {  
  86.             tmpd = new byte[32];  
  87.             for(int i = 0; i < 32 - n.toByteArray().length; i++)  
  88.             {  
  89.                 tmpd[i] = 0;  
  90.             }  
  91.             System.arraycopy(n.toByteArray(), 0, tmpd, 32 - n.toByteArray().length, n.toByteArray().length);  
  92.         }  
  93.         return tmpd;  
  94.     }  
  95.       
  96.     /** 
  97.      * 换字节流(字节数组)型数据转大数字 
  98.      *  
  99.      * @param b 
  100.      * @return 
  101.      */  
  102.     public static BigInteger byteConvertInteger(byte[] b)  
  103.     {  
  104.         if (b[0] < 0)  
  105.         {  
  106.             byte[] temp = new byte[b.length + 1];  
  107.             temp[0] = 0;  
  108.             System.arraycopy(b, 0, temp, 1, b.length);  
  109.             return new BigInteger(temp);  
  110.         }  
  111.         return new BigInteger(b);  
  112.     }  
  113.       
  114.     /** 
  115.      * 根据字节数组获得值(十六进制数字) 
  116.      *  
  117.      * @param bytes 
  118.      * @return 
  119.      */  
  120.     public static String getHexString(byte[] bytes)   
  121.     {  
  122.         return getHexString(bytes, true);  
  123.     }  
  124.       
  125.     /** 
  126.      * 根据字节数组获得值(十六进制数字) 
  127.      *  
  128.      * @param bytes 
  129.      * @param upperCase 
  130.      * @return 
  131.      */  
  132.     public static String getHexString(byte[] bytes, boolean upperCase)   
  133.     {  
  134.         String ret = "";  
  135.         for (int i = 0; i < bytes.length; i++)   
  136.         {  
  137.             ret += Integer.toString((bytes[i] & 0xff) + 0x10016).substring(1);  
  138.         }  
  139.         return upperCase ? ret.toUpperCase() : ret;  
  140.     }  
  141.       
  142.     /** 
  143.      * 打印十六进制字符串 
  144.      *  
  145.      * @param bytes 
  146.      */  
  147.     public static void printHexString(byte[] bytes)   
  148.     {  
  149.         for (int i = 0; i < bytes.length; i++)   
  150.         {  
  151.             String hex = Integer.toHexString(bytes[i] & 0xFF);  
  152.             if (hex.length() == 1)   
  153.             {  
  154.                 hex = '0' + hex;  
  155.             }  
  156.             System.out.print("0x" + hex.toUpperCase() + ",");  
  157.         }  
  158.         System.out.println("");  
  159.     }  
  160.       
  161.     /** 
  162.      * Convert hex string to byte[] 
  163.      *  
  164.      * @param hexString 
  165.      *            the hex string 
  166.      * @return byte[] 
  167.      */  
  168.     public static byte[] hexStringToBytes(String hexString)   
  169.     {  
  170.         if (hexString == null || hexString.equals(""))   
  171.         {  
  172.             return null;  
  173.         }  
  174.           
  175.         hexString = hexString.toUpperCase();  
  176.         int length = hexString.length() / 2;  
  177.         char[] hexChars = hexString.toCharArray();  
  178.         byte[] d = new byte[length];  
  179.         for (int i = 0; i < length; i++)   
  180.         {  
  181.             int pos = i * 2;  
  182.             d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));  
  183.         }  
  184.         return d;  
  185.     }  
  186.       
  187.     /** 
  188.      * Convert char to byte 
  189.      *  
  190.      * @param c 
  191.      *            char 
  192.      * @return byte 
  193.      */  
  194.     public static byte charToByte(char c)   
  195.     {  
  196.         return (byte"0123456789ABCDEF".indexOf(c);  
  197.     }  
  198.       
  199.     /** 
  200.      * 用于建立十六进制字符的输出的小写字符数组 
  201.      */  
  202.     private static final char[] DIGITS_LOWER = {'0''1''2''3''4''5',  
  203.             '6''7''8''9''a''b''c''d''e''f'};  
  204.    
  205.     /** 
  206.      * 用于建立十六进制字符的输出的大写字符数组 
  207.      */  
  208.     private static final char[] DIGITS_UPPER = {'0''1''2''3''4''5',  
  209.             '6''7''8''9''A''B''C''D''E''F'};  
  210.    
  211.     /** 
  212.      * 将字节数组转换为十六进制字符数组 
  213.      * 
  214.      * @param data byte[] 
  215.      * @return 十六进制char[] 
  216.      */  
  217.     public static char[] encodeHex(byte[] data) {  
  218.         return encodeHex(data, true);  
  219.     }  
  220.    
  221.     /** 
  222.      * 将字节数组转换为十六进制字符数组 
  223.      * 
  224.      * @param data        byte[] 
  225.      * @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式 
  226.      * @return 十六进制char[] 
  227.      */  
  228.     public static char[] encodeHex(byte[] data, boolean toLowerCase) {  
  229.         return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);  
  230.     }  
  231.    
  232.     /** 
  233.      * 将字节数组转换为十六进制字符数组 
  234.      * 
  235.      * @param data     byte[] 
  236.      * @param toDigits 用于控制输出的char[] 
  237.      * @return 十六进制char[] 
  238.      */  
  239.     protected static char[] encodeHex(byte[] data, char[] toDigits) {  
  240.         int l = data.length;  
  241.         char[] out = new char[l << 1];  
  242.         // two characters form the hex value.  
  243.         for (int i = 0, j = 0; i < l; i++) {  
  244.             out[j++] = toDigits[(0xF0 & data[i]) >>> 4];  
  245.             out[j++] = toDigits[0x0F & data[i]];  
  246.         }  
  247.         return out;  
  248.     }  
  249.    
  250.     /** 
  251.      * 将字节数组转换为十六进制字符串 
  252.      * 
  253.      * @param data byte[] 
  254.      * @return 十六进制String 
  255.      */  
  256.     public static String encodeHexString(byte[] data) {  
  257.         return encodeHexString(data, true);  
  258.     }  
  259.    
  260.     /** 
  261.      * 将字节数组转换为十六进制字符串 
  262.      * 
  263.      * @param data        byte[] 
  264.      * @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式 
  265.      * @return 十六进制String 
  266.      */  
  267.     public static String encodeHexString(byte[] data, boolean toLowerCase) {  
  268.         return encodeHexString(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);  
  269.     }  
  270.    
  271.     /** 
  272.      * 将字节数组转换为十六进制字符串 
  273.      * 
  274.      * @param data     byte[] 
  275.      * @param toDigits 用于控制输出的char[] 
  276.      * @return 十六进制String 
  277.      */  
  278.     protected static String encodeHexString(byte[] data, char[] toDigits) {  
  279.         return new String(encodeHex(data, toDigits));  
  280.     }  
  281.    
  282.     /** 
  283.      * 将十六进制字符数组转换为字节数组 
  284.      * 
  285.      * @param data 十六进制char[] 
  286.      * @return byte[] 
  287.      * @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常 
  288.      */  
  289.     public static byte[] decodeHex(char[] data) {  
  290.         int len = data.length;  
  291.    
  292.         if ((len & 0x01) != 0) {  
  293.             throw new RuntimeException("Odd number of characters.");  
  294.         }  
  295.    
  296.         byte[] out = new byte[len >> 1];  
  297.    
  298.         // two characters form the hex value.  
  299.         for (int i = 0, j = 0; j < len; i++) {  
  300.             int f = toDigit(data[j], j) << 4;  
  301.             j++;  
  302.             f = f | toDigit(data[j], j);  
  303.             j++;  
  304.             out[i] = (byte) (f & 0xFF);  
  305.         }  
  306.    
  307.         return out;  
  308.     }  
  309.    
  310.     /** 
  311.      * 将十六进制字符转换成一个整数 
  312.      * 
  313.      * @param ch    十六进制char 
  314.      * @param index 十六进制字符在字符数组中的位置 
  315.      * @return 一个整数 
  316.      * @throws RuntimeException 当ch不是一个合法的十六进制字符时,抛出运行时异常 
  317.      */  
  318.     protected static int toDigit(char ch, int index) {  
  319.         int digit = Character.digit(ch, 16);  
  320.         if (digit == -1) {  
  321.             throw new RuntimeException("Illegal hexadecimal character " + ch  
  322.                     + " at index " + index);  
  323.         }  
  324.         return digit;  
  325.     }  
  326.    
  327.     /** 
  328.      * 数字字符串转ASCII码字符串 
  329.      *  
  330.      * @param String 
  331.      *            字符串 
  332.      * @return ASCII字符串 
  333.      */  
  334.     public static String StringToAsciiString(String content) {  
  335.         String result = "";  
  336.         int max = content.length();  
  337.         for (int i = 0; i < max; i++) {  
  338.             char c = content.charAt(i);  
  339.             String b = Integer.toHexString(c);  
  340.             result = result + b;  
  341.         }  
  342.         return result;  
  343.     }  
  344.       
  345.     /** 
  346.      * 十六进制转字符串 
  347.      *  
  348.      * @param hexString 
  349.      *            十六进制字符串 
  350.      * @param encodeType 
  351.      *            编码类型4:Unicode,2:普通编码 
  352.      * @return 字符串 
  353.      */  
  354.     public static String hexStringToString(String hexString, int encodeType) {  
  355.         String result = "";  
  356.         int max = hexString.length() / encodeType;  
  357.         for (int i = 0; i < max; i++) {  
  358.             char c = (char) hexStringToAlgorism(hexString  
  359.                     .substring(i * encodeType, (i + 1) * encodeType));  
  360.             result += c;  
  361.         }  
  362.         return result;  
  363.     }  
  364.       
  365.     /** 
  366.      * 十六进制字符串装十进制 
  367.      *  
  368.      * @param hex 
  369.      *            十六进制字符串 
  370.      * @return 十进制数值 
  371.      */  
  372.     public static int hexStringToAlgorism(String hex) {  
  373.         hex = hex.toUpperCase();  
  374.         int max = hex.length();  
  375.         int result = 0;  
  376.         for (int i = max; i > 0; i--) {  
  377.             char c = hex.charAt(i - 1);  
  378.             int algorism = 0;  
  379.             if (c >= '0' && c <= '9') {  
  380.                 algorism = c - '0';  
  381.             } else {  
  382.                 algorism = c - 55;  
  383.             }  
  384.             result += Math.pow(16, max - i) * algorism;  
  385.         }  
  386.         return result;  
  387.     }  
  388.       
  389.     /** 
  390.      * 十六转二进制 
  391.      *  
  392.      * @param hex 
  393.      *            十六进制字符串 
  394.      * @return 二进制字符串 
  395.      */  
  396.     public static String hexStringToBinary(String hex) {  
  397.         hex = hex.toUpperCase();  
  398.         String result = "";  
  399.         int max = hex.length();  
  400.         for (int i = 0; i < max; i++) {  
  401.             char c = hex.charAt(i);  
  402.             switch (c) {  
  403.             case '0':  
  404.                 result += "0000";  
  405.                 break;  
  406.             case '1':  
  407.                 result += "0001";  
  408.                 break;  
  409.             case '2':  
  410.                 result += "0010";  
  411.                 break;  
  412.             case '3':  
  413.                 result += "0011";  
  414.                 break;  
  415.             case '4':  
  416.                 result += "0100";  
  417.                 break;  
  418.             case '5':  
  419.                 result += "0101";  
  420.                 break;  
  421.             case '6':  
  422.                 result += "0110";  
  423.                 break;  
  424.             case '7':  
  425.                 result += "0111";  
  426.                 break;  
  427.             case '8':  
  428.                 result += "1000";  
  429.                 break;  
  430.             case '9':  
  431.                 result += "1001";  
  432.                 break;  
  433.             case 'A':  
  434.                 result += "1010";  
  435.                 break;  
  436.             case 'B':  
  437.                 result += "1011";  
  438.                 break;  
  439.             case 'C':  
  440.                 result += "1100";  
  441.                 break;  
  442.             case 'D':  
  443.                 result += "1101";  
  444.                 break;  
  445.             case 'E':  
  446.                 result += "1110";  
  447.                 break;  
  448.             case 'F':  
  449.                 result += "1111";  
  450.                 break;  
  451.             }  
  452.         }  
  453.         return result;  
  454.     }  
  455.       
  456.     /** 
  457.      * ASCII码字符串转数字字符串 
  458.      *  
  459.      * @param String 
  460.      *            ASCII字符串 
  461.      * @return 字符串 
  462.      */  
  463.     public static String AsciiStringToString(String content) {  
  464.         String result = "";  
  465.         int length = content.length() / 2;  
  466.         for (int i = 0; i < length; i++) {  
  467.             String c = content.substring(i * 2, i * 2 + 2);  
  468.             int a = hexStringToAlgorism(c);  
  469.             char b = (char) a;  
  470.             String d = String.valueOf(b);  
  471.             result += d;  
  472.         }  
  473.         return result;  
  474.     }  
  475.       
  476.     /** 
  477.      * 将十进制转换为指定长度的十六进制字符串 
  478.      *  
  479.      * @param algorism 
  480.      *            int 十进制数字 
  481.      * @param maxLength 
  482.      *            int 转换后的十六进制字符串长度 
  483.      * @return String 转换后的十六进制字符串 
  484.      */  
  485.     public static String algorismToHexString(int algorism, int maxLength) {  
  486.         String result = "";  
  487.         result = Integer.toHexString(algorism);  
  488.   
  489.         if (result.length() % 2 == 1) {  
  490.             result = "0" + result;  
  491.         }  
  492.         return patchHexString(result.toUpperCase(), maxLength);  
  493.     }  
  494.       
  495.     /** 
  496.      * 字节数组转为普通字符串(ASCII对应的字符) 
  497.      *  
  498.      * @param bytearray 
  499.      *            byte[] 
  500.      * @return String 
  501.      */  
  502.     public static String byteToString(byte[] bytearray) {  
  503.         String result = "";  
  504.         char temp;  
  505.   
  506.         int length = bytearray.length;  
  507.         for (int i = 0; i < length; i++) {  
  508.             temp = (char) bytearray[i];  
  509.             result += temp;  
  510.         }  
  511.         return result;  
  512.     }  
  513.       
  514.     /** 
  515.      * 二进制字符串转十进制 
  516.      *  
  517.      * @param binary 
  518.      *            二进制字符串 
  519.      * @return 十进制数值 
  520.      */  
  521.     public static int binaryToAlgorism(String binary) {  
  522.         int max = binary.length();  
  523.         int result = 0;  
  524.         for (int i = max; i > 0; i--) {  
  525.             char c = binary.charAt(i - 1);  
  526.             int algorism = c - '0';  
  527.             result += Math.pow(2, max - i) * algorism;  
  528.         }  
  529.         return result;  
  530.     }  
  531.   
  532.     /** 
  533.      * 十进制转换为十六进制字符串 
  534.      *  
  535.      * @param algorism 
  536.      *            int 十进制的数字 
  537.      * @return String 对应的十六进制字符串 
  538.      */  
  539.     public static String algorismToHEXString(int algorism) {  
  540.         String result = "";  
  541.         result = Integer.toHexString(algorism);  
  542.   
  543.         if (result.length() % 2 == 1) {  
  544.             result = "0" + result;  
  545.   
  546.         }  
  547.         result = result.toUpperCase();  
  548.   
  549.         return result;  
  550.     }  
  551.       
  552.     /** 
  553.      * HEX字符串前补0,主要用于长度位数不足。 
  554.      *  
  555.      * @param str 
  556.      *            String 需要补充长度的十六进制字符串 
  557.      * @param maxLength 
  558.      *            int 补充后十六进制字符串的长度 
  559.      * @return 补充结果 
  560.      */  
  561.     static public String patchHexString(String str, int maxLength) {  
  562.         String temp = "";  
  563.         for (int i = 0; i < maxLength - str.length(); i++) {  
  564.             temp = "0" + temp;  
  565.         }  
  566.         str = (temp + str).substring(0, maxLength);  
  567.         return str;  
  568.     }  
  569.       
  570.     /** 
  571.      * 将一个字符串转换为int 
  572.      *  
  573.      * @param s 
  574.      *            String 要转换的字符串 
  575.      * @param defaultInt 
  576.      *            int 如果出现异常,默认返回的数字 
  577.      * @param radix 
  578.      *            int 要转换的字符串是什么进制的,如16 8 10. 
  579.      * @return int 转换后的数字 
  580.      */  
  581.     public static int parseToInt(String s, int defaultInt, int radix) {  
  582.         int i = 0;  
  583.         try {  
  584.             i = Integer.parseInt(s, radix);  
  585.         } catch (NumberFormatException ex) {  
  586.             i = defaultInt;  
  587.         }  
  588.         return i;  
  589.     }  
  590.       
  591.     /** 
  592.      * 将一个十进制形式的数字字符串转换为int 
  593.      *  
  594.      * @param s 
  595.      *            String 要转换的字符串 
  596.      * @param defaultInt 
  597.      *            int 如果出现异常,默认返回的数字 
  598.      * @return int 转换后的数字 
  599.      */  
  600.     public static int parseToInt(String s, int defaultInt) {  
  601.         int i = 0;  
  602.         try {  
  603.             i = Integer.parseInt(s);  
  604.         } catch (NumberFormatException ex) {  
  605.             i = defaultInt;  
  606.         }  
  607.         return i;  
  608.     }  
  609.       
  610.     /** 
  611.      * 十六进制串转化为byte数组 
  612.      *  
  613.      * @return the array of byte 
  614.      */  
  615.     public static byte[] hexToByte(String hex)  
  616.             throws IllegalArgumentException {  
  617.         if (hex.length() % 2 != 0) {  
  618.             throw new IllegalArgumentException();  
  619.         }  
  620.         char[] arr = hex.toCharArray();  
  621.         byte[] b = new byte[hex.length() / 2];  
  622.         for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {  
  623.             String swap = "" + arr[i++] + arr[i];  
  624.             int byteint = Integer.parseInt(swap, 16) & 0xFF;  
  625.             b[j] = new Integer(byteint).byteValue();  
  626.         }  
  627.         return b;  
  628.     }  
  629.       
  630.     /** 
  631.      * 字节数组转换为十六进制字符串 
  632.      *  
  633.      * @param b 
  634.      *            byte[] 需要转换的字节数组 
  635.      * @return String 十六进制字符串 
  636.      */  
  637.     public static String byteToHex(byte b[]) {  
  638.         if (b == null) {  
  639.             throw new IllegalArgumentException(  
  640.                     "Argument b ( byte array ) is null! ");  
  641.         }  
  642.         String hs = "";  
  643.         String stmp = "";  
  644.         for (int n = 0; n < b.length; n++) {  
  645.             stmp = Integer.toHexString(b[n] & 0xff);  
  646.             if (stmp.length() == 1) {  
  647.                 hs = hs + "0" + stmp;  
  648.             } else {  
  649.                 hs = hs + stmp;  
  650.             }  
  651.         }  
  652.         return hs.toUpperCase();  
  653.     }  
  654.       
  655.     public static byte[] subByte(byte[] input, int startIndex, int length) {  
  656.         byte[] bt = new byte[length];  
  657.         for (int i = 0; i < length; i++) {  
  658.             bt[i] = input[i + startIndex];  
  659.         }  
  660.         return bt;  
  661.     }  
  662. }  

f.     Chiper类

[java]  view plain  copy
  1. package com.mlq.sm;  
  2.   
  3. import java.math.BigInteger;  
  4. import org.bouncycastle.crypto.AsymmetricCipherKeyPair;  
  5. import org.bouncycastle.crypto.params.ECPrivateKeyParameters;  
  6. import org.bouncycastle.crypto.params.ECPublicKeyParameters;  
  7. import org.bouncycastle.math.ec.ECPoint;  
  8.   
  9. public class Cipher   
  10. {  
  11.     private int ct;  
  12.     private ECPoint p2;  
  13.     private SM3Digest sm3keybase;  
  14.     private SM3Digest sm3c3;  
  15.     private byte key[];  
  16.     private byte keyOff;  
  17.   
  18.     public Cipher()   
  19.     {  
  20.         this.ct = 1;  
  21.         this.key = new byte[32];  
  22.         this.keyOff = 0;  
  23.     }  
  24.   
  25.     private void Reset()   
  26.     {  
  27.         this.sm3keybase = new SM3Digest();  
  28.         this.sm3c3 = new SM3Digest();  
  29.           
  30.         byte p[] = Util.byteConvert32Bytes(p2.getX().toBigInteger());  
  31.         this.sm3keybase.update(p, 0, p.length);  
  32.         this.sm3c3.update(p, 0, p.length);  
  33.           
  34.         p = Util.byteConvert32Bytes(p2.getY().toBigInteger());  
  35.         this.sm3keybase.update(p, 0, p.length);  
  36.         this.ct = 1;  
  37.         NextKey();  
  38.     }  
  39.   
  40.     private void NextKey()   
  41.     {  
  42.         SM3Digest sm3keycur = new SM3Digest(this.sm3keybase);  
  43.         sm3keycur.update((byte) (ct >> 24 & 0xff));  
  44.         sm3keycur.update((byte) (ct >> 16 & 0xff));  
  45.         sm3keycur.update((byte) (ct >> 8 & 0xff));  
  46.         sm3keycur.update((byte) (ct & 0xff));  
  47.         sm3keycur.doFinal(key, 0);  
  48.         this.keyOff = 0;  
  49.         this.ct++;  
  50.     }  
  51.   
  52.     public ECPoint Init_enc(SM2 sm2, ECPoint userKey)   
  53.     {  
  54.         AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair();  
  55.         ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();  
  56.         ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();  
  57.         BigInteger k = ecpriv.getD();  
  58.         ECPoint c1 = ecpub.getQ();  
  59.         this.p2 = userKey.multiply(k);  
  60.         Reset();  
  61.         return c1;  
  62.     }  
  63.   
  64.     public void Encrypt(byte data[])   
  65.     {  
  66.         this.sm3c3.update(data, 0, data.length);  
  67.         for (int i = 0; i < data.length; i++)   
  68.         {  
  69.             if (keyOff == key.length)  
  70.             {  
  71.                 NextKey();  
  72.             }  
  73.             data[i] ^= key[keyOff++];  
  74.         }  
  75.     }  
  76.   
  77.     public void Init_dec(BigInteger userD, ECPoint c1)  
  78.     {  
  79.         this.p2 = c1.multiply(userD);  
  80.         Reset();  
  81.     }  
  82.   
  83.     public void Decrypt(byte data[])   
  84.     {  
  85.         for (int i = 0; i < data.length; i++)  
  86.         {  
  87.             if (keyOff == key.length)  
  88.             {  
  89.                 NextKey();  
  90.             }  
  91.             data[i] ^= key[keyOff++];  
  92.         }  
  93.   
  94.         this.sm3c3.update(data, 0, data.length);  
  95.     }  
  96.   
  97.     public void Dofinal(byte c3[])   
  98.     {  
  99.         byte p[] = Util.byteConvert32Bytes(p2.getY().toBigInteger());  
  100.         this.sm3c3.update(p, 0, p.length);  
  101.         this.sm3c3.doFinal(c3, 0);  
  102.         Reset();  
  103.     }  
  104. }  

2.SM4

直接上代码:

a.      SM4主类

【SM4.java】

 

[java]  view plain  copy
  1. package com.mlq.sm;  
  2.   
  3. import java.io.ByteArrayInputStream;  
  4. import java.io.ByteArrayOutputStream;  
  5.   
  6. public class SM4   
  7. {  
  8.     public static final int SM4_ENCRYPT = 1;  
  9.       
  10.     public static final int SM4_DECRYPT = 0;  
  11.   
  12.     private long GET_ULONG_BE(byte[] b, int i)   
  13.     {  
  14.         long n = (long)(b[i] & 0xff) << 24 | (long)((b[i + 1] & 0xff) << 16) | (long)((b[i + 2] & 0xff) << 8) | (long)(b[i + 3] & 0xff) & 0xffffffffL;  
  15.         return n;  
  16.     }  
  17.   
  18.     private void PUT_ULONG_BE(long n, byte[] b, int i)   
  19.     {  
  20.         b[i] = (byte)(int)(0xFF & n >> 24);  
  21.         b[i + 1] = (byte)(int)(0xFF & n >> 16);  
  22.         b[i + 2] = (byte)(int)(0xFF & n >> 8);  
  23.         b[i + 3] = (byte)(int)(0xFF & n);  
  24.     }  
  25.   
  26.     private long SHL(long x, int n)   
  27.     {  
  28.         return (x & 0xFFFFFFFF) << n;  
  29.     }  
  30.       
  31.     private long ROTL(long x, int n)   
  32.     {  
  33.         return SHL(x, n) | x >> (32 - n);  
  34.     }  
  35.       
  36.     private void SWAP(long[] sk, int i)  
  37.     {  
  38.         long t = sk[i];  
  39.         sk[i] = sk[(31 - i)];  
  40.         sk[(31 - i)] = t;  
  41.     }  
  42.       
  43.     public static final byte[] SboxTable = { (byte0xd6, (byte0x90, (byte0xe9, (byte0xfe,  
  44.         (byte0xcc, (byte0xe10x3d, (byte0xb70x16, (byte0xb6,  
  45.         0x14, (byte0xc20x28, (byte0xfb0x2c0x050x2b0x67,  
  46.         (byte0x9a0x760x2a, (byte0xbe0x04, (byte0xc3,  
  47.         (byte0xaa0x440x130x260x49, (byte0x860x06,  
  48.         (byte0x99, (byte0x9c0x420x50, (byte0xf4, (byte0x91,  
  49.         (byte0xef, (byte0x980x7a0x330x540x0b0x43,  
  50.         (byte0xed, (byte0xcf, (byte0xac0x62, (byte0xe4,  
  51.         (byte0xb30x1c, (byte0xa9, (byte0xc90x08, (byte0xe8,  
  52.         (byte0x95, (byte0x80, (byte0xdf, (byte0x94, (byte0xfa,  
  53.         0x75, (byte0x8f0x3f, (byte0xa60x470x07, (byte0xa7,  
  54.         (byte0xfc, (byte0xf30x730x17, (byte0xba, (byte0x83,  
  55.         0x590x3c0x19, (byte0xe6, (byte0x850x4f, (byte0xa8,  
  56.         0x680x6b, (byte0x81, (byte0xb20x710x64, (byte0xda,  
  57.         (byte0x8b, (byte0xf8, (byte0xeb0x0f0x4b0x700x56,  
  58.         (byte0x9d0x350x1e0x240x0e0x5e0x630x58, (byte0xd1,  
  59.         (byte0xa20x250x220x7c0x3b0x010x210x78, (byte0x87,  
  60.         (byte0xd40x000x460x57, (byte0x9f, (byte0xd30x27,  
  61.         0x520x4c0x360x02, (byte0xe7, (byte0xa0, (byte0xc4,  
  62.         (byte0xc8, (byte0x9e, (byte0xea, (byte0xbf, (byte0x8a,  
  63.         (byte0xd20x40, (byte0xc70x38, (byte0xb5, (byte0xa3,  
  64.         (byte0xf7, (byte0xf2, (byte0xce, (byte0xf90x610x15,  
  65.         (byte0xa1, (byte0xe0, (byte0xae0x5d, (byte0xa4,  
  66.         (byte0x9b0x340x1a0x55, (byte0xad, (byte0x930x32,  
  67.         0x30, (byte0xf5, (byte0x8c, (byte0xb1, (byte0xe30x1d,  
  68.         (byte0xf6, (byte0xe20x2e, (byte0x820x66, (byte0xca,  
  69.         0x60, (byte0xc00x290x23, (byte0xab0x0d0x530x4e0x6f,  
  70.         (byte0xd5, (byte0xdb0x370x45, (byte0xde, (byte0xfd,  
  71.         (byte0x8e0x2f0x03, (byte0xff0x6a0x720x6d0x6c0x5b,  
  72.         0x51, (byte0x8d0x1b, (byte0xaf, (byte0x92, (byte0xbb,  
  73.         (byte0xdd, (byte0xbc0x7f0x11, (byte0xd90x5c0x41,  
  74.         0x1f0x100x5a, (byte0xd80x0a, (byte0xc10x31,  
  75.         (byte0x88, (byte0xa5, (byte0xcd0x7b, (byte0xbd0x2d,  
  76.         0x74, (byte0xd00x12, (byte0xb8, (byte0xe5, (byte0xb4,  
  77.         (byte0xb0, (byte0x890x69, (byte0x970x4a0x0c,  
  78.         (byte0x960x770x7e0x65, (byte0xb9, (byte0xf10x09,  
  79.         (byte0xc50x6e, (byte0xc6, (byte0x840x18, (byte0xf0,  
  80.         0x7d, (byte0xec0x3a, (byte0xdc0x4d0x200x79,  
  81.         (byte0xee0x5f0x3e, (byte0xd7, (byte0xcb0x390x48 };  
  82.       
  83.     public static final int[] FK = { 0xa3b1bac60x56aa33500x677d91970xb27022dc };  
  84.       
  85.     public static final int[] CK = { 0x00070e15,0x1c232a31,0x383f464d,0x545b6269,  
  86.         0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,  
  87.         0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,  
  88.         0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,  
  89.         0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,  
  90.         0x30373e45,0x4c535a61,0x686f767d,0x848b9299,  
  91.         0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,  
  92.         0x10171e25,0x2c333a41,0x484f565d,0x646b7279 };  
  93.   
  94.     private byte sm4Sbox(byte inch)  
  95.     {  
  96.         int i = inch & 0xFF;  
  97.         byte retVal = SboxTable[i];  
  98.         return retVal;  
  99.     }  
  100.   
  101.     private long sm4Lt(long ka)   
  102.     {  
  103.         long bb = 0L;  
  104.         long c = 0L;  
  105.         byte[] a = new byte[4];  
  106.         byte[] b = new byte[4];  
  107.         PUT_ULONG_BE(ka, a, 0);  
  108.         b[0] = sm4Sbox(a[0]);  
  109.         b[1] = sm4Sbox(a[1]);  
  110.         b[2] = sm4Sbox(a[2]);  
  111.         b[3] = sm4Sbox(a[3]);  
  112.         bb = GET_ULONG_BE(b, 0);  
  113.         c = bb ^ ROTL(bb, 2) ^ ROTL(bb, 10) ^ ROTL(bb, 18) ^ ROTL(bb, 24);  
  114.         return c;  
  115.     }  
  116.   
  117.     private long sm4F(long x0, long x1, long x2, long x3, long rk)  
  118.     {  
  119.         return x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk);  
  120.     }  
  121.   
  122.     private long sm4CalciRK(long ka)   
  123.     {  
  124.         long bb = 0L;  
  125.         long rk = 0L;  
  126.         byte[] a = new byte[4];  
  127.         byte[] b = new byte[4];  
  128.         PUT_ULONG_BE(ka, a, 0);  
  129.         b[0] = sm4Sbox(a[0]);  
  130.         b[1] = sm4Sbox(a[1]);  
  131.         b[2] = sm4Sbox(a[2]);  
  132.         b[3] = sm4Sbox(a[3]);  
  133.         bb = GET_ULONG_BE(b, 0);  
  134.         rk = bb ^ ROTL(bb, 13) ^ ROTL(bb, 23);  
  135.         return rk;  
  136.     }  
  137.   
  138.     private void sm4_setkey(long[] SK, byte[] key)   
  139.     {  
  140.         long[] MK = new long[4];  
  141.         long[] k = new long[36];  
  142.         int i = 0;  
  143.         MK[0] = GET_ULONG_BE(key, 0);  
  144.         MK[1] = GET_ULONG_BE(key, 4);  
  145.         MK[2] = GET_ULONG_BE(key, 8);  
  146.         MK[3] = GET_ULONG_BE(key, 12);  
  147.         k[0] = MK[0] ^ (long) FK[0];  
  148.         k[1] = MK[1] ^ (long) FK[1];  
  149.         k[2] = MK[2] ^ (long) FK[2];  
  150.         k[3] = MK[3] ^ (long) FK[3];  
  151.         for (; i < 32; i++)   
  152.         {  
  153.             k[(i + 4)] = (k[i] ^ sm4CalciRK(k[(i + 1)] ^ k[(i + 2)] ^ k[(i + 3)] ^ (long) CK[i]));  
  154.             SK[i] = k[(i + 4)];  
  155.         }  
  156.     }  
  157.   
  158.     private void sm4_one_round(long[] sk, byte[] input, byte[] output)   
  159.     {  
  160.         int i = 0;  
  161.         long[] ulbuf = new long[36];  
  162.         ulbuf[0] = GET_ULONG_BE(input, 0);  
  163.         ulbuf[1] = GET_ULONG_BE(input, 4);  
  164.         ulbuf[2] = GET_ULONG_BE(input, 8);  
  165.         ulbuf[3] = GET_ULONG_BE(input, 12);  
  166.         while (i < 32)  
  167.         {  
  168.             ulbuf[(i + 4)] = sm4F(ulbuf[i], ulbuf[(i + 1)], ulbuf[(i + 2)], ulbuf[(i + 3)], sk[i]);  
  169.             i++;  
  170.         }  
  171.         PUT_ULONG_BE(ulbuf[35], output, 0);  
  172.         PUT_ULONG_BE(ulbuf[34], output, 4);  
  173.         PUT_ULONG_BE(ulbuf[33], output, 8);  
  174.         PUT_ULONG_BE(ulbuf[32], output, 12);  
  175.     }  
  176.   
  177.     private byte[] padding(byte[] input, int mode)  
  178.     {  
  179.         if (input == null)   
  180.         {  
  181.             return null;  
  182.         }  
  183.           
  184.         byte[] ret = (byte[]) null;  
  185.         if (mode == SM4_ENCRYPT)   
  186.         {  
  187.             int p = 16 - input.length % 16;  
  188.             ret = new byte[input.length + p];  
  189.             System.arraycopy(input, 0, ret, 0, input.length);  
  190.             for (int i = 0; i < p; i++)   
  191.             {  
  192.                 ret[input.length + i] = (byte) p;  
  193.             }  
  194.         }   
  195.         else   
  196.         {  
  197.             int p = input[input.length - 1];  
  198.             ret = new byte[input.length - p];  
  199.             System.arraycopy(input, 0, ret, 0, input.length - p);  
  200.         }  
  201.         return ret;  
  202.     }  
  203.   
  204.     public void sm4_setkey_enc(SM4_Context ctx, byte[] key) throws Exception  
  205.     {  
  206.         if (ctx == null)   
  207.         {  
  208.             throw new Exception("ctx is null!");  
  209.         }  
  210.           
  211.         if (key == null || key.length != 16)   
  212.         {  
  213.             throw new Exception("key error!");  
  214.         }  
  215.           
  216.         ctx.mode = SM4_ENCRYPT;  
  217.         sm4_setkey(ctx.sk, key);  
  218.     }  
  219.   
  220.     public void sm4_setkey_dec(SM4_Context ctx, byte[] key) throws Exception  
  221.     {  
  222.         if (ctx == null)   
  223.         {  
  224.             throw new Exception("ctx is null!");  
  225.         }  
  226.           
  227.         if (key == null || key.length != 16)   
  228.         {  
  229.             throw new Exception("key error!");  
  230.         }  
  231.           
  232.         int i = 0;  
  233.         ctx.mode = SM4_DECRYPT;  
  234.         sm4_setkey(ctx.sk, key);  
  235.         for (i = 0; i < 16; i++)   
  236.         {  
  237.             SWAP(ctx.sk, i);  
  238.         }  
  239.     }  
  240.   
  241.     public byte[] sm4_crypt_ecb(SM4_Context ctx, byte[] input) throws Exception   
  242.     {  
  243.         if (input == null)   
  244.         {  
  245.             throw new Exception("input is null!");  
  246.         }  
  247.       
  248.         if ((ctx.isPadding) && (ctx.mode == SM4_ENCRYPT))   
  249.         {  
  250.             input = padding(input, SM4_ENCRYPT);  
  251.         }  
  252.           
  253.         int length = input.length;  
  254.         ByteArrayInputStream bins = new ByteArrayInputStream(input);  
  255.         ByteArrayOutputStream bous = new ByteArrayOutputStream();  
  256.         for(; length > 0; length -= 16)  
  257.         {  
  258.             byte[] in = new byte[16];  
  259.             byte[] out = new byte[16];  
  260.             bins.read(in);  
  261.             sm4_one_round(ctx.sk, in, out);  
  262.             bous.write(out);  
  263.         }  
  264.           
  265.         byte[] output = bous.toByteArray();  
  266.         if (ctx.isPadding && ctx.mode == SM4_DECRYPT)   
  267.         {  
  268.             output = padding(output, SM4_DECRYPT);  
  269.         }  
  270.         bins.close();  
  271.         bous.close();  
  272.         return output;  
  273.     }  
  274.   
  275.     public byte[] sm4_crypt_cbc(SM4_Context ctx, byte[] iv, byte[] input) throws Exception  
  276.     {  
  277.         if (iv == null || iv.length != 16)  
  278.         {  
  279.             throw new Exception("iv error!");  
  280.         }  
  281.           
  282.         if (input == null)   
  283.         {  
  284.             throw new Exception("input is null!");  
  285.         }  
  286.           
  287.         if (ctx.isPadding && ctx.mode == SM4_ENCRYPT)   
  288.         {  
  289.             input = padding(input, SM4_ENCRYPT);  
  290.         }  
  291.           
  292.         int i = 0;  
  293.         int length = input.length;  
  294.         ByteArrayInputStream bins = new ByteArrayInputStream(input);  
  295.         ByteArrayOutputStream bous = new ByteArrayOutputStream();  
  296.         if (ctx.mode == SM4_ENCRYPT)   
  297.         {  
  298.             for(; length > 0; length -= 16)  
  299.             {  
  300.                 byte[] in = new byte[16];  
  301.                 byte[] out = new byte[16];  
  302.                 byte[] out1 = new byte[16];  
  303.                   
  304.                 bins.read(in);  
  305.                 for (i = 0; i < 16; i++)   
  306.                 {  
  307.                     out[i] = ((byte) (in[i] ^ iv[i]));  
  308.                 }  
  309.                 sm4_one_round(ctx.sk, out, out1);  
  310.                 System.arraycopy(out1, 0, iv, 016);  
  311.                 bous.write(out1);  
  312.             }  
  313.         }   
  314.         else   
  315.         {  
  316.             byte[] temp = new byte[16];  
  317.             for(; length > 0; length -= 16)  
  318.             {  
  319.                 byte[] in = new byte[16];  
  320.                 byte[] out = new byte[16];  
  321.                 byte[] out1 = new byte[16];  
  322.                   
  323.                 bins.read(in);  
  324.                 System.arraycopy(in, 0, temp, 016);  
  325.                 sm4_one_round(ctx.sk, in, out);  
  326.                 for (i = 0; i < 16; i++)   
  327.                 {  
  328.                     out1[i] = ((byte) (out[i] ^ iv[i]));  
  329.                 }  
  330.                 System.arraycopy(temp, 0, iv, 016);  
  331.                 bous.write(out1);  
  332.             }  
  333.         }  
  334.           
  335.         byte[] output = bous.toByteArray();  
  336.         if (ctx.isPadding && ctx.mode == SM4_DECRYPT)   
  337.         {  
  338.             output = padding(output, SM4_DECRYPT);  
  339.         }  
  340.         bins.close();  
  341.         bous.close();  
  342.         return output;  
  343.     }  
  344. }  

b.      SM4实体类

【SM4_Context.java】

 

[java]  view plain  copy
  1. package com.mlq.sm;  
  2.   
  3. public class SM4_Context  
  4. {  
  5.     public int mode;  
  6.       
  7.     public long[] sk;  
  8.       
  9.     public boolean isPadding;  
  10.   
  11.     public SM4_Context()   
  12.     {  
  13.         this.mode = 1;  
  14.         this.isPadding = true;  
  15.         this.sk = new long[32];  
  16.     }  
  17. }  

c.      SM4工具类(这里的PaddingMode采用的是PKCS7)

【SM4Utils.java】

 

[java]  view plain  copy
  1. package com.mlq.sm;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.regex.Matcher;  
  5. import java.util.regex.Pattern;  
  6.   
  7. import sun.misc.BASE64Decoder;  
  8. import sun.misc.BASE64Encoder;  
  9.   
  10. public class SM4Utils  
  11. {  
  12.     private String secretKey = "";  
  13.     private String iv = "";  
  14.     private boolean hexString = false;  
  15.       
  16.     public SM4Utils()  
  17.     {  
  18.     }  
  19.       
  20.     public String encryptData_ECB(String plainText)  
  21.     {  
  22.         try   
  23.         {  
  24.             SM4_Context ctx = new SM4_Context();  
  25.             ctx.isPadding = true;  
  26.             ctx.mode = SM4.SM4_ENCRYPT;  
  27.               
  28.             byte[] keyBytes;  
  29.             if (hexString)  
  30.             {  
  31.                 keyBytes = Util.hexStringToBytes(secretKey);  
  32.             }  
  33.             else  
  34.             {  
  35.                 keyBytes = secretKey.getBytes();  
  36.             }  
  37.               
  38.             SM4 sm4 = new SM4();  
  39.             sm4.sm4_setkey_enc(ctx, keyBytes);  
  40.             byte[] encrypted = sm4.sm4_crypt_ecb(ctx, plainText.getBytes("GBK"));  
  41.             String cipherText = new BASE64Encoder().encode(encrypted);  
  42.             if (cipherText != null && cipherText.trim().length() > 0)  
  43.             {  
  44.                 Pattern p = Pattern.compile("\\s*|\t|\r|\n");  
  45.                 Matcher m = p.matcher(cipherText);  
  46.                 cipherText = m.replaceAll("");  
  47.             }  
  48.             return cipherText;  
  49.         }   
  50.         catch (Exception e)   
  51.         {  
  52.             e.printStackTrace();  
  53.             return null;  
  54.         }  
  55.     }  
  56.       
  57.     public String decryptData_ECB(String cipherText)  
  58.     {  
  59.         try   
  60.         {  
  61.             SM4_Context ctx = new SM4_Context();  
  62.             ctx.isPadding = true;  
  63.             ctx.mode = SM4.SM4_DECRYPT;  
  64.               
  65.             byte[] keyBytes;  
  66.             if (hexString)  
  67.             {  
  68.                 keyBytes = Util.hexStringToBytes(secretKey);  
  69.             }  
  70.             else  
  71.             {  
  72.                 keyBytes = secretKey.getBytes();  
  73.             }  
  74.               
  75.             SM4 sm4 = new SM4();  
  76.             sm4.sm4_setkey_dec(ctx, keyBytes);  
  77.             byte[] decrypted = sm4.sm4_crypt_ecb(ctx, new BASE64Decoder().decodeBuffer(cipherText));  
  78.             return new String(decrypted, "GBK");  
  79.         }   
  80.         catch (Exception e)   
  81.         {  
  82.             e.printStackTrace();  
  83.             return null;  
  84.         }  
  85.     }  
  86.       
  87.     public String encryptData_CBC(String plainText)  
  88.     {  
  89.         try   
  90.         {  
  91.             SM4_Context ctx = new SM4_Context();  
  92.             ctx.isPadding = true;  
  93.             ctx.mode = SM4.SM4_ENCRYPT;  
  94.               
  95.             byte[] keyBytes;  
  96.             byte[] ivBytes;  
  97.             if (hexString)  
  98.             {  
  99.                 keyBytes = Util.hexStringToBytes(secretKey);  
  100.                 ivBytes = Util.hexStringToBytes(iv);  
  101.             }  
  102.             else  
  103.             {  
  104.                 keyBytes = secretKey.getBytes();  
  105.                 ivBytes = iv.getBytes();  
  106.             }  
  107.               
  108.             SM4 sm4 = new SM4();  
  109.             sm4.sm4_setkey_enc(ctx, keyBytes);  
  110.             byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, plainText.getBytes("GBK"));  
  111.             String cipherText = new BASE64Encoder().encode(encrypted);  
  112.             if (cipherText != null && cipherText.trim().length() > 0)  
  113.             {  
  114.                 Pattern p = Pattern.compile("\\s*|\t|\r|\n");  
  115.                 Matcher m = p.matcher(cipherText);  
  116.                 cipherText = m.replaceAll("");  
  117.             }  
  118.             return cipherText;  
  119.         }   
  120.         catch (Exception e)   
  121.         {  
  122.             e.printStackTrace();  
  123.             return null;  
  124.         }  
  125.     }  
  126.       
  127.     public String decryptData_CBC(String cipherText)  
  128.     {  
  129.         try   
  130.         {  
  131.             SM4_Context ctx = new SM4_Context();  
  132.             ctx.isPadding = true;  
  133.             ctx.mode = SM4.SM4_DECRYPT;  
  134.               
  135.             byte[] keyBytes;  
  136.             byte[] ivBytes;  
  137.             if (hexString)  
  138.             {  
  139.                 keyBytes = Util.hexStringToBytes(secretKey);  
  140.                 ivBytes = Util.hexStringToBytes(iv);  
  141.             }  
  142.             else  
  143.             {  
  144.                 keyBytes = secretKey.getBytes();  
  145.                 ivBytes = iv.getBytes();  
  146.             }  
  147.               
  148.             SM4 sm4 = new SM4();  
  149.             sm4.sm4_setkey_dec(ctx, keyBytes);  
  150.             byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, new BASE64Decoder().decodeBuffer(cipherText));  
  151.             return new String(decrypted, "GBK");  
  152.         }   
  153.         catch (Exception e)  
  154.         {  
  155.             e.printStackTrace();  
  156.             return null;  
  157.         }  
  158.     }  
  159.       
  160.     public static void main(String[] args) throws IOException   
  161.     {  
  162.         String plainText = "ererfeiisgod";  
  163.           
  164.         SM4Utils sm4 = new SM4Utils();  
  165.         sm4.secretKey = "JeF8U9wHFOMfs2Y8";  
  166.         sm4.hexString = false;  
  167.           
  168.         System.out.println("ECB模式");  
  169.         String cipherText = sm4.encryptData_ECB(plainText);  
  170.         System.out.println("密文: " + cipherText);  
  171.         System.out.println("");  
  172.           
  173.         plainText = sm4.decryptData_ECB(cipherText);  
  174.         System.out.println("明文: " + plainText);  
  175.         System.out.println("");  
  176.           
  177.         System.out.println("CBC模式");  
  178.         sm4.iv = "UISwD9fW6cFh9SNS";  
  179.         cipherText = sm4.encryptData_CBC(plainText);  
  180.         System.out.println("密文: " + cipherText);  
  181.         System.out.println("");  
  182.           
  183.         plainText = sm4.decryptData_CBC(cipherText);  
  184.         System.out.println("明文: " + plainText);  
  185.     }  
  • 3
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值