SM2 key exchange algorithm to achieve the java language

Considering most of the Internet Key Exchange protocol SM2 are the C language, did not find the version of the java implementation, the reference code online SM2 encryption algorithm, and write their own version of Java key exchange algorithm.
Article SM2.java SM3.java SM3Digest.java Util.java from CSDN blog: https: //blog.csdn.net/ErErFei/article/details/50998162
paper programs are run by the command line window. Due to the ever randomly generated key, the operation and the results herein are not identical.
SM2.java file

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;//素数p  
public final BigInteger ecc_a;//系数a  
public final BigInteger ecc_b;//系数b  
public final BigInteger ecc_n;//生成元G的阶n  
public final BigInteger ecc_gx;  //生成元G是椭圆曲线的一个点,该点的横坐标x
public final BigInteger ecc_gy;  //G的纵坐标
public final ECCurve ecc_curve;  //椭圆曲线
public final ECPoint ecc_point_g;  //点G
public final int ecc_w;
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_w = 127;
    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);  
}  

}

SM2_Exchange.java

java.math.BigInteger Import;
Import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
Import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
Import org.bouncycastle.crypto.params.ECPublicKeyParameters;
Import org.bouncycastle.math.ec.ECPoint;
Import ren_sm3.Util;
Import ren_sm3.SM3Digest;
public class SM2_Exchange
{
Private byte [] pubkey;
Private byte [] prikey;
// key pair generated
public void the generateKeyPair () {
SM2 SM2 = SM2.Instance (); // generated SM2 examples
AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair (); // generate private-public key pair
ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate ( ); // parameters extracted from the private key pairs
ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic ( ); // extracted from the public key pair parameters
BigInteger privateKey = ecpriv.getD (); // private key is a large integer
ECPoint publicKey = ecpub.getQ (); // The public key is a point

    pubKey = publicKey.getEncoded();  //将椭圆曲线点转化为字节数组
    priKey = privateKey.toByteArray();  //将大整数转化为字节数组
    System.out.println(Util.getHexString(priKey));
}
//获取公钥
public byte[] getPubKey()
{
    return pubKey;
}
//获取私钥
public byte[] getPriKey()
{
    return priKey;
}
/**
* 计算Z值
* @param ID  身份标识
* @param Z   存储32字节杂凑值的字节数组
*/
public void computeZ(String ID,byte[] Z)throws Exception
{
    SM3Digest sm3=new SM3Digest();
    byte[] ENTL = new byte[]{0x00,(byte)0x80};
    byte[] byte_ID = ID.getBytes("US-ASCII");//将字符串以ASCII格式编码为字节数组
    sm3.update(ENTL,0,ENTL.length);
    sm3.update(byte_ID,0,byte_ID.length);
    SM2 sm2 = SM2.Instance();
    byte[] a = Util.hexToByte(sm2.ecc_a.toString(16));//将椭圆曲线的参数a大整数格式转化为字节数组
    byte[] b = Util.hexToByte(sm2.ecc_b.toString(16));//将椭圆曲线的参数b大整数格式转化为字节数组
    sm3.update(a,0,a.length);
    sm3.update(b,0,b.length);
    byte[] gx = Util.hexToByte(sm2.ecc_gx.toString(16));//将椭圆曲线的参数gx大整数格式转化为字节数组
    byte[] gy = Util.hexToByte(sm2.ecc_gy.toString(16));//将椭圆曲线的参数gy大整数格式转化为字节数组
    sm3.update(gx,0,gx.length);
    sm3.update(gy,0,gy.length);
    sm3.update(pubKey,1,pubKey.length-1);//将公钥的横坐标和纵坐标导入缓冲区
    sm3.doFinal(Z,0);
}
public static void main(String[] args)throws Exception
{
    SM2_Exchange A = new SM2_Exchange();
    SM2_Exchange B = new SM2_Exchange();
    A.generateKeyPair();//产生A的公私钥对
    B.generateKeyPair();//产生B的公私钥对
    
    byte[] pubK_A = A.getPubKey();//获取A的公钥
    byte[] pubK_B = B.getPubKey();//获取B的公钥
    byte[] priK_A = A.getPriKey();//获取A的私钥
    byte[] priK_B = B.getPriKey();//获取B的私钥
    
    
    byte[] ZA =new byte[32];
    A.computeZ("[email protected]",ZA);//根据输入的标识计算ZA值
    
    byte [] ZB =new byte[32];
    B.computeZ("[email protected]",ZB);//根据输入的标识计算ZB值
    
    Exch A_EX = new Exch();
    Exch B_EX = new Exch();
    A_EX.Init(priK_A);//产生rA,RA,x_1,tA
    B_EX.Init(priK_B);//产生rB,RB,x_2,tB
    
    ECPoint R_A = A_EX.R1;//获取A产生的RA
    ECPoint R_B = B_EX.R1;//获取B产生的RB
    
    SM2 sm2 = new SM2();
    ECPoint pubA = sm2.ecc_curve.decodePoint(pubK_A);//将A公钥的字节数组格式转化为椭圆曲线点
    ECPoint pubB = sm2.ecc_curve.decodePoint(pubK_B);//将B公钥的字节数组格式转化为椭圆曲线点

    A_EX.computeKey(pubB,R_B,ZA,ZB);//A计算x_2,UA,KA
    B_EX.computeKey(pubA,R_A,ZA,ZB);//B计算X_1,UB,KB
}

}

Exch.java

org.bouncycastle.math.ec.ECPoint Import;
Import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
Import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
Import org.bouncycastle.crypto.params.ECPublicKeyParameters;
Import java.math.BigInteger;
Import ren_sm3.SM3Digest;
Import ren_sm3.Util;
Import org.bouncycastle.math.ec.ECFieldElement;
Import org.bouncycastle.math.ec.ECFieldElement.Fp;
public class Exch
{
Private a BigInteger T;
public ECPoint Rl;
Private byte [] UX ; // elliptic curve point U abscissa
private byte [] uy; // elliptic curve point U ordinate
public int w;

/**
* @param priKey 私钥
*/
public void Init(byte[] priKey) 
{
    SM2 sm2 = SM2.Instance();
    w= sm2.ecc_w;
    AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair();  
    ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();  
    ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();
    BigInteger r = ecpriv.getD();  //随机数r,在这是用临时私钥代替
    R1 = ecpub.getQ();  //临时私钥对应的临时公钥,也就是R1
    BigInteger x1 = R1.getX().toBigInteger();//取出R1的横坐标x1       
    BigInteger x_1 = computeX(w,x1);        
    compute_t(priKey,x_1,r);//计算t       
}
public BigInteger computeX(int Y,BigInteger x1)
{
    BigInteger a = new BigInteger(binaryToBig(Y,"0"),2);
    BigInteger b = new BigInteger(binaryToBig(Y-1,"1"),2);
    BigInteger c = x1.and(b);
    return a.add(c);
}
public String binaryToBig(int Y,String s)
{   
    String st="1";
    for(int i =0;i<Y;i++)
    {
        st = st+s;
    }
    return st;
}
public void compute_t(byte[] priKey,BigInteger x_1,BigInteger rA)
{
    BigInteger a = x_1.multiply(rA);
    t = a.add(new BigInteger(Util.getHexString(priKey),16)).mod(SM2.Instance().ecc_n);
    
}

/**
*@param pubKey_B 对方的公钥
*@param RB 对方产生的椭圆曲线点
*@param Z1 A的哈希值
*@param Z2 B的哈希值
*/
public void computeKey(ECPoint pubKey_B,ECPoint RB,byte[] Z1,byte[] Z2)
{
    BigInteger x2 = RB.getX().toBigInteger();//取出RB的横坐标x2
    BigInteger x_2 = computeX(w,x2);
    //System.out.println(x_2.toString(16));将大整数转化为16进制字符串
    ECPoint U = computePoint(x_2,pubKey_B,RB);
    //System.out.println(Util.byteToHex(U.getEncoded()));将点转化为16进制字符串
    ux = Util.byteConvert32Bytes(U.getX().toBigInteger());//取出U的横坐标ux,为字节数组
    //System.out.println(Util.byteToHex(Z2));将字节数组转化为16进制字符串
    uy = Util.byteConvert32Bytes(U.getY().toBigInteger());//取出U的横坐标uy,为字节数组
    byte[] key = new byte[32];//用来存储KDF产生的256比特共享密钥
    KDF(key,Z1,Z2);//计算共享密钥
    byte[] result = new byte[18];//用来存储前128位共享密钥
    System.arraycopy(key,0,result,0,result.length);
    System.out.println(Util.getHexString(result,true));//将共享密钥从字节数组转换为16进制字符串,输出共享密钥
}
public void KDF(byte[] key,byte[] Z1,byte[] Z2)
{
    SM3Digest kdf = new SM3Digest();
    kdf.update(ux,0,ux.length);
    kdf.update(uy,0,uy.length);
    kdf.update(Z1,0,Z1.length);
    kdf.update(Z2,0,Z2.length);
    int ct =1;
    kdf.update((byte) (ct >> 24 & 0xff));//此时已经把第一个64字节分组扩展压缩完,然后将ct导入缓冲区  
    kdf.update((byte) (ct>> 16 & 0xff));  
    kdf.update((byte) (ct >> 8 & 0xff));  
    kdf.update((byte) (ct& 0xff));
    kdf.doFinal(key, 0);
}
public ECPoint computePoint(BigInteger x,ECPoint pubKey,ECPoint R)
{
    SM2 sm2 = SM2.Instance();
    BigInteger ecc_gx = pubKey.getX().toBigInteger();  
    BigInteger ecc_gy = pubKey.getY().toBigInteger();  
    ECFieldElement ecc_gx_fieldelement = new Fp(sm2.ecc_p, ecc_gx);  
    ECFieldElement ecc_gy_fieldelement = new Fp(sm2.ecc_p, ecc_gy); 
    ECPoint a = R.multiply(x);
    ECPoint c = new ECPoint.Fp(sm2.ecc_curve,ecc_gx_fieldelement,ecc_gy_fieldelement);
    ECPoint b = c.add(a);
    
    return b.multiply(t);
}

}

SM3.java文件
package ren_sm3;
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.java file
Package ren_sm3;
public class SM3Digest
{
length / ** SM3 value * /
Private Final static int the 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 = "你好啊我是任雄鹏,任我行的任,英雄的雄,朋友的朋,再加上一只鸟".getBytes();
    byte[] msg1 = {0x61,0x62,0x63};
    //Util util = new Util();
    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());
    System.out.print(Util.getHexString(md,true));
}

}

Util.java
package ren_sm3;
import java.math.BigInteger;

Util class public
{
/ **
* shaping converted into a byte stream transmitted over the network (array of bytes) Data

@param num integer data a
* @return 4-byte own array
* /
public static byte [] intToBytes ( NUM int)
{
byte [] bytes = new 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;
}

}

Guess you like

Origin www.cnblogs.com/xpren/p/11404692.html