SM2加密解密工具

非原創,網上找的資源,具體地址忘了,請見諒

Cipher類
package com.zjxt.test_post_demo.sm2utils;

import java.math.BigInteger;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;  
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;  
import org.bouncycastle.crypto.params.ECPublicKeyParameters;  
import org.bouncycastle.math.ec.ECPoint; 
 
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();  
	    }  
}

SM2

package com.zjxt.test_post_demo.sm2utils;

import java.math.BigInteger;
import java.security.SecureRandom;  
  
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;  
import org.bouncycastle.crypto.params.ECDomainParameters;  
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;  
import org.bouncycastle.math.ec.ECCurve;  
import org.bouncycastle.math.ec.ECFieldElement;  
import org.bouncycastle.math.ec.ECPoint;  
import org.bouncycastle.math.ec.ECFieldElement.Fp;  
 
public class SM2 {
	 //測試參數  
//  public static final String[] ecc_param = {  
//      "8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3",   
//      "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498",   
//      "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A",   
//      "8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7",   
//      "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D",   
//      "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2"   
//  };  
      
    //正式參數  
    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);  
    }  
}
SM2KeyPair 公私鑰對
package com.zjxt.test_post_demo.sm2utils;


public class SM2KeyPair {
	
	/** 公鑰 */
	private  String publicKey;
	
	/** 私鑰 */
	private String privateKey;
 
	SM2KeyPair(String publicKey, String privateKey) {
		this.publicKey = publicKey;
		this.privateKey = privateKey;
	}
 
	public String getPublicKey() {
		return publicKey;
	}
 
	public String getPrivateKey() {
		return privateKey;
	}
	
}
SM2Utils SM2工具類,生成公私鑰對,加密解密等方法
package com.zjxt.test_post_demo.sm2utils;

import java.io.IOException;
import java.math.BigInteger;  
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;  
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;  
import org.bouncycastle.crypto.params.ECPublicKeyParameters;  
import org.bouncycastle.math.ec.ECPoint; 
 
public class SM2Utils {
	  //生成隨機祕鑰對  
    public static SM2KeyPair 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()));
        return  new SM2KeyPair(Util.byteToHex(publicKey.getEncoded(false)),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(false)) + 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;  
    }  
       
}

SM3

package com.zjxt.test_post_demo.sm2utils;

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;  
		    }  
}
SM3Digest
package com.zjxt.test_post_demo.sm2utils;

import org.bouncycastle.util.encoders.Hex;
 
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());  
    }  
}
Util 工具類
package com.zjxt.test_post_demo.sm2utils;

import java.math.BigInteger;
 
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 content
     *            字符串 
     * @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 content
     *            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;  
    }  
}
SM2Test1 測試類
package com.zjxt.test_post_demo.sm2utils;

import java.io.IOException;

public class SM2Test1 {
    public static void main(String[] args) throws IOException {

        // 獲取公鑰私鑰對
        SM2KeyPair sm2KeyPair = SM2Utils.generateKeyPair();

        // 獲取公鑰和私鑰
        String publickey=sm2KeyPair.getPublicKey();
        String privatekey=sm2KeyPair.getPrivateKey();

        // 需要加密的信息
        String info="哈哈哈,嘿嘿嘿";
        // 將信息加密,公鑰的字節碼需要使用util裏的hexToByte方法
        String encrypt = SM2Utils.encrypt(Util.hexToByte(publickey), info.getBytes("utf-8"));

        System.out.println("加密後信息:"+encrypt);

        // 將加密後的信息解密,私鑰和加密後的數據的字節碼對象需要用util裏的hexToByte方法
        byte[] decrypt = SM2Utils.decrypt(Util.hexToByte(privatekey), Util.hexToByte(encrypt));
        // 將字節數組轉爲字符串
        String newInfo=new String(decrypt,"utf-8");
        System.out.println("解密後信息:"+newInfo);


    }

}

其中有些方法已過時,暫時未找到對應的替代方法,

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章