国密即国家密码局认定的国产密码算法。主要有SM1,SM2,SM3,SM4。密钥长度和分组长度均为128位。

SM1 为对称加密。其加密强度与AES相当。该算法不公开,调用该算法时,需要通过加密芯片的接口进行调用。

SM2为非对称加密,基于ECC。该算法已公开。由于该算法基于ECC,故其签名速度与秘钥生成速度都快于RSA。ECC 256位(SM2采用的就是ECC 256位的一种)安全强度比RSA 2048位高,但运算速度快于RSA。

SM3 消息摘要。可以用MD5作为对比理解。该算法已公开。校验结果为256位。

SM4 无线局域网标准的分组数据算法。对称加密,密钥长度和分组长度均为128位。

由于SM1、SM4加解密的分组大小为128bit,故对消息进行加解密时,若消息长度过长,需要进行分组,要消息长度不足,则要进行填充。

java代码下载

pom需添加

<!--国密-->

<dependency>

<groupId>org.bouncycastle</groupId>

<artifactId>bcprov-jdk15on</artifactId>

<version>1.56</version>

</dependency>

sm2:

public class SM2 {

private static BigInteger n = new BigInteger(

"FFFFFFFE" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "7203DF6B" + "21C6052B" + "53BBF409" + "39D54123", 16);

private static BigInteger p = new BigInteger(

"FFFFFFFE" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "00000000" + "FFFFFFFF" + "FFFFFFFF", 16);

private static BigInteger a = new BigInteger(

"FFFFFFFE" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "00000000" + "FFFFFFFF" + "FFFFFFFC", 16);

private static BigInteger b = new BigInteger(

"28E9FA9E" + "9D9F5E34" + "4D5A9E4B" + "CF6509A7" + "F39789F5" + "15AB8F92" + "DDBCBD41" + "4D940E93", 16);

private static BigInteger gx = new BigInteger(

"32C4AE2C" + "1F198119" + "5F990446" + "6A39C994" + "8FE30BBF" + "F2660BE1" + "715A4589" + "334C74C7", 16);

private static BigInteger gy = new BigInteger(

"BC3736A2" + "F4F6779C" + "59BDCEE3" + "6B692153" + "D0A9877C" + "C62A4740" + "02DF32E5" + "2139F0A0", 16);

private static ECDomainParameters ecc_bc_spec;

private static int w = (int) Math.ceil(n.bitLength() * 1.0 / 2) - 1;

private static BigInteger _2w = new BigInteger("2").pow(w);

private static final int DIGEST_LENGTH = 32;


private static SecureRandom random = new SecureRandom();

private static ECCurve.Fp curve;

private static ECPoint G;

private boolean debug = false;


public boolean isDebug() {

return debug;

}


public void setDebug(boolean debug) {

this.debug = debug;

}


/**

* 以16进制打印字节数组

*

* @param b

*/

public static void printHexString(byte[] b) {

for (int i = 0; i < b.length; i++) {

String hex = Integer.toHexString(b[i] & 0xFF);

if (hex.length() == 1) {

hex = '0' + hex;

}

System.out.print(hex.toUpperCase());

}

System.out.println();

}


/**

* 随机数生成器

*

* @param max

* @return

*/

private static BigInteger random(BigInteger max) {


BigInteger r = new BigInteger(256, random);

// int count = 1;


while (r.compareTo(max) >= 0) {

r = new BigInteger(128, random);

// count++;

}


// System.out.println("count: " + count);

return r;

}


/**

* 判断字节数组是否全0

*

* @param buffer

* @return

*/

private boolean allZero(byte[] buffer) {

for (int i = 0; i < buffer.length; i++) {

if (buffer[i] != 0)

return false;

}

return true;

}


/**

* 公钥加密

*

* @param input

* 加密原文

* @param publicKey

* 公钥

* @return

*/

public byte[] encrypt(String input, ECPoint publicKey) {


byte[] inputBuffer = input.getBytes();

if (debug)

printHexString(inputBuffer);


byte[] C1Buffer;

ECPoint kpb;

byte[] t;

do {

/* 1 产生随机数k,k属于[1, n-1] */

BigInteger k = random(n);

if (debug) {

System.out.print("k: ");

printHexString(k.toByteArray());

}


/* 2 计算椭圆曲线点C1 = [k]G = (x1, y1) */

ECPoint C1 = G.multiply(k);

C1Buffer = C1.getEncoded(false);

if (debug) {

System.out.print("C1: ");

printHexString(C1Buffer);

}


/*

* 3 计算椭圆曲线点 S = [h]Pb

*/

BigInteger h = ecc_bc_spec.getH();

if (h != null) {

ECPoint S = publicKey.multiply(h);

if (S.isInfinity())

throw new IllegalStateException();

}


/* 4 计算 [k]PB = (x2, y2) */

kpb = publicKey.multiply(k).normalize();


/* 5 计算 t = KDF(x2||y2, klen) */

byte[] kpbBytes = kpb.getEncoded(false);

t = KDF(kpbBytes, inputBuffer.length);

// DerivationFunction kdf = new KDF1BytesGenerator(new

// ShortenedDigest(new SHA256Digest(), DIGEST_LENGTH));

//

// t = new byte[inputBuffer.length];

// kdf.init(new ISO18033KDFParameters(kpbBytes));

// kdf.generateBytes(t, 0, t.length);

} while (allZero(t));


/* 6 计算C2=M^t */

byte[] C2 = new byte[inputBuffer.length];

for (int i = 0; i < inputBuffer.length; i++) {

C2[i] = (byte) (inputBuffer[i] ^ t[i]);

}


/* 7 计算C3 = Hash(x2 || M || y2) */

byte[] C3 = sm3hash(kpb.getXCoord().toBigInteger().toByteArray(), inputBuffer,

kpb.getYCoord().toBigInteger().toByteArray());


/* 8 输出密文 C=C1 || C2 || C3 */


byte[] encryptResult = new byte[C1Buffer.length + C2.length + C3.length];


System.arraycopy(C1Buffer, 0, encryptResult, 0, C1Buffer.length);

System.arraycopy(C2, 0, encryptResult, C1Buffer.length, C2.length);

System.arraycopy(C3, 0, encryptResult, C1Buffer.length + C2.length, C3.length);


if (debug) {

System.out.print("密文: ");

printHexString(encryptResult);

}


return encryptResult;

}


/**

* 私钥解密

*

* @param encryptData

* 密文数据字节数组

* @param privateKey

* 解密私钥

* @return

*/

public String decrypt(byte[] encryptData, BigInteger privateKey) {


if (debug)

System.out.println("encryptData length: " + encryptData.length);


byte[] C1Byte = new byte[65];

System.arraycopy(encryptData, 0, C1Byte, 0, C1Byte.length);


ECPoint C1 = curve.decodePoint(C1Byte).normalize();


/*

* 计算椭圆曲线点 S = [h]C1 是否为无穷点

*/

BigInteger h = ecc_bc_spec.getH();

if (h != null) {

ECPoint S = C1.multiply(h);

if (S.isInfinity())

throw new IllegalStateException();

}

/* 计算[dB]C1 = (x2, y2) */

ECPoint dBC1 = C1.multiply(privateKey).normalize();


/* 计算t = KDF(x2 || y2, klen) */

byte[] dBC1Bytes = dBC1.getEncoded(false);

int klen = encryptData.length - 65 - DIGEST_LENGTH;

byte[] t = KDF(dBC1Bytes, klen);

// DerivationFunction kdf = new KDF1BytesGenerator(new

// ShortenedDigest(new SHA256Digest(), DIGEST_LENGTH));

// if (debug)

// System.out.println("klen = " + klen);

// kdf.init(new ISO18033KDFParameters(dBC1Bytes));

// kdf.generateBytes(t, 0, t.length);


if (allZero(t)) {

System.err.println("all zero");

throw new IllegalStateException();

}


/* 5 计算M'=C2^t */

byte[] M = new byte[klen];

for (int i = 0; i < M.length; i++) {

M[i] = (byte) (encryptData[C1Byte.length + i] ^ t[i]);

}

if (debug)

printHexString(M);


/* 6 计算 u = Hash(x2 || M' || y2) 判断 u == C3是否成立 */

byte[] C3 = new byte[DIGEST_LENGTH];


if (debug)

try {

System.out.println("M = " + new String(M, "UTF8"));

} catch (UnsupportedEncodingException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}


System.arraycopy(encryptData, encryptData.length - DIGEST_LENGTH, C3, 0, DIGEST_LENGTH);

byte[] u = sm3hash(dBC1.getXCoord().toBigInteger().toByteArray(), M,

dBC1.getYCoord().toBigInteger().toByteArray());

if (Arrays.equals(u, C3)) {

if (debug)

System.out.println("解密成功");

try {

return new String(M, "UTF8");

} catch (UnsupportedEncodingException e) {

e.printStackTrace();

}

return null;

} else {

if (debug) {

System.out.print("u = ");

printHexString(u);

System.out.print("C3 = ");

printHexString(C3);

System.err.println("解密验证失败");

}

return null;

}


}


// /**

// * SHA摘要

// * @param x2

// * @param M

// * @param y2

// * @return

// */

// private byte[] calculateHash(BigInteger x2, byte[] M, BigInteger y2) {

// ShortenedDigest digest = new ShortenedDigest(new SHA256Digest(),

// DIGEST_LENGTH);

// byte[] buf = x2.toByteArray();

// digest.update(buf, 0, buf.length);

// digest.update(M, 0, M.length);

// buf = y2.toByteArray();

// digest.update(buf, 0, buf.length);

//

// buf = new byte[DIGEST_LENGTH];

// digest.doFinal(buf, 0);

//

// return buf;

// }


/**

* 判断是否在范围内

*

* @param param

* @param min

* @param max

* @return

*/

private boolean between(BigInteger param, BigInteger min, BigInteger max) {

if (param.compareTo(min) >= 0 && param.compareTo(max) < 0) {

return true;

} else {

return false;

}

}


/**

* 判断生成的公钥是否合法

*

* @param publicKey

* @return

*/

private boolean checkPublicKey(ECPoint publicKey) {


if (!publicKey.isInfinity()) {


BigInteger x = publicKey.getXCoord().toBigInteger();

BigInteger y = publicKey.getYCoord().toBigInteger();


if (between(x, new BigInteger("0"), p) && between(y, new BigInteger("0"), p)) {


BigInteger xResult = x.pow(3).add(a.multiply(x)).add(b).mod(p);


if (debug)

System.out.println("xResult: " + xResult.toString());


BigInteger yResult = y.pow(2).mod(p);


if (debug)

System.out.println("yResult: " + yResult.toString());


if (yResult.equals(xResult) && publicKey.multiply(n).isInfinity()) {

return true;

}

}

}

return false;

}


/**

* 生成密钥对

*

* @return

*/

public SM2KeyPair generateKeyPair() {


BigInteger d = random(n.subtract(new BigInteger("1")));


SM2KeyPair keyPair = new SM2KeyPair(G.multiply(d).normalize(), d);


if (checkPublicKey(keyPair.getPublicKey())) {

if (debug)

System.out.println("generate key successfully");

return keyPair;

} else {

if (debug)

System.err.println("generate key failed");

return null;

}

}


public SM2() {

curve = new ECCurve.Fp(p, // q

a, // a

b); // b

G = curve.createPoint(gx, gy);

ecc_bc_spec = new ECDomainParameters(curve, G, n);

}


public SM2(boolean debug) {

this();

this.debug = debug;

}


/**

* 导出公钥到本地

*

* @param publicKey

* @param path

*/

public void exportPublicKey(ECPoint publicKey, String path) {

File file = new File(path);

try {

if (!file.exists())

file.createNewFile();

byte buffer[] = publicKey.getEncoded(false);

FileOutputStream fos = new FileOutputStream(file);

fos.write(buffer);

fos.close();

} catch (IOException e) {

e.printStackTrace();

}

}


/**

* 从本地导入公钥

*

* @param path

* @return

*/

public ECPoint importPublicKey(String path) {

File file = new File(path);

try {

if (!file.exists())

return null;

FileInputStream fis = new FileInputStream(file);

ByteArrayOutputStream baos = new ByteArrayOutputStream();


byte buffer[] = new byte[16];

int size;

while ((size = fis.read(buffer)) != -1) {

baos.write(buffer, 0, size);

}

fis.close();

return curve.decodePoint(baos.toByteArray());

} catch (IOException e) {

e.printStackTrace();

}

return null;

}


/**

* 导出私钥到本地

*

* @param privateKey

* @param path

*/

public void exportPrivateKey(BigInteger privateKey, String path) {

File file = new File(path);

try {

if (!file.exists())

file.createNewFile();

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));

oos.writeObject(privateKey);

oos.close();

} catch (IOException e) {

e.printStackTrace();

}

}


/**

* 从本地导入私钥

*

* @param path

* @return

*/

public BigInteger importPrivateKey(String path) {

File file = new File(path);

try {

if (!file.exists())

return null;

FileInputStream fis = new FileInputStream(file);

ObjectInputStream ois = new ObjectInputStream(fis);

BigInteger res = (BigInteger) (ois.readObject());

ois.close();

fis.close();

return res;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}


/**

* 字节数组拼接

*

* @param params

* @return

*/

private static byte[] join(byte[]... params) {

ByteArrayOutputStream baos = new ByteArrayOutputStream();

byte[] res = null;

try {

for (int i = 0; i < params.length; i++) {

baos.write(params[i]);

}

res = baos.toByteArray();

} catch (IOException e) {

e.printStackTrace();

}

return res;

}


/**

* sm3摘要

*

* @param params

* @return

*/

private static byte[] sm3hash(byte[]... params) {

byte[] res = null;

try {

res = SM3.hash(join(params));

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return res;

}


/**

* 取得用户标识字节数组

*

* @param IDA

* @param aPublicKey

* @return

*/

private static byte[] ZA(String IDA, ECPoint aPublicKey) {

byte[] idaBytes = IDA.getBytes();

int entlenA = idaBytes.length * 8;

byte[] ENTLA = new byte[] { (byte) (entlenA & 0xFF00), (byte) (entlenA & 0x00FF) };

byte[] ZA = sm3hash(ENTLA, idaBytes, a.toByteArray(), b.toByteArray(), gx.toByteArray(), gy.toByteArray(),

aPublicKey.getXCoord().toBigInteger().toByteArray(),

aPublicKey.getYCoord().toBigInteger().toByteArray());

return ZA;

}


/**

* 签名

*

* @param M

* 签名信息

* @param IDA

* 签名方唯一标识

* @param keyPair

* 签名方密钥对

* @return 签名

*/

public Signature sign(String M, String IDA, SM2KeyPair keyPair) {

byte[] ZA = ZA(IDA, keyPair.getPublicKey());

byte[] M_ = join(ZA, M.getBytes());

BigInteger e = new BigInteger(1, sm3hash(M_));

// BigInteger k = new BigInteger(

// "6CB28D99 385C175C 94F94E93 4817663F C176D925 DD72B727 260DBAAE

// 1FB2F96F".replace(" ", ""), 16);

BigInteger k;

BigInteger r;

do {

k = random(n);

ECPoint p1 = G.multiply(k).normalize();

BigInteger x1 = p1.getXCoord().toBigInteger();

r = e.add(x1);

r = r.mod(n);

} while (r.equals(BigInteger.ZERO) || r.add(k).equals(n));


BigInteger s = ((keyPair.getPrivateKey().add(BigInteger.ONE).modInverse(n))

.multiply((k.subtract(r.multiply(keyPair.getPrivateKey()))).mod(n))).mod(n);


return new Signature(r, s);

}


/**

* 验签

*

* @param M

* 签名信息

* @param signature

* 签名

* @param IDA

* 签名方唯一标识

* @param aPublicKey

* 签名方公钥

* @return true or false

*/

public boolean verify(String M, Signature signature, String IDA, ECPoint aPublicKey) {

if (!between(signature.r, BigInteger.ONE, n))

return false;

if (!between(signature.s, BigInteger.ONE, n))

return false;


byte[] M_ = join(ZA(IDA, aPublicKey), M.getBytes());

BigInteger e = new BigInteger(1, sm3hash(M_));

BigInteger t = signature.r.add(signature.s).mod(n);


if (t.equals(BigInteger.ZERO))

return false;


ECPoint p1 = G.multiply(signature.s).normalize();

ECPoint p2 = aPublicKey.multiply(t).normalize();

BigInteger x1 = p1.add(p2).normalize().getXCoord().toBigInteger();

BigInteger R = e.add(x1).mod(n);

if (R.equals(signature.r))

return true;

return false;

}


/**

* 密钥派生函数

*

* @param Z

* @param klen

* 生成klen字节数长度的密钥

* @return

*/

private static byte[] KDF(byte[] Z, int klen) {

int ct = 1;

int end = (int) Math.ceil(klen * 1.0 / 32);

ByteArrayOutputStream baos = new ByteArrayOutputStream();

try {

for (int i = 1; i < end; i++) {

baos.write(sm3hash(Z, SM3.toByteArray(ct)));

ct++;

}

byte[] last = sm3hash(Z, SM3.toByteArray(ct));

if (klen % 32 == 0) {

baos.write(last);

} else

baos.write(last, 0, klen % 32);

return baos.toByteArray();

} catch (Exception e) {

e.printStackTrace();

}

return null;

}


/**

* 传输实体类

*

* @author Potato

*

*/

private static class TransportEntity implements Serializable {

final byte[] R; //R点

final byte[] S; //验证S

final byte[] Z; //用户标识

final byte[] K; //公钥


public TransportEntity(byte[] r, byte[] s,byte[] z,ECPoint pKey) {

R = r;

S = s;

Z=z;

K=pKey.getEncoded(false);

}

}


/**

* 密钥协商辅助类

*

* @author Potato

*

*/

public static class KeyExchange {

BigInteger rA;

ECPoint RA;

ECPoint V;

byte[] Z;

byte[] key;


String ID;

SM2KeyPair keyPair;


public KeyExchange(String ID,SM2KeyPair keyPair) {

this.ID=ID;

this.keyPair = keyPair;

this.Z=ZA(ID, keyPair.getPublicKey());

}


/**

* 密钥协商发起第一步

*

* @return

*/

public TransportEntity keyExchange_1() {

rA = random(n);

// rA=new BigInteger("83A2C9C8 B96E5AF7 0BD480B4 72409A9A 327257F1

// EBB73F5B 073354B2 48668563".replace(" ", ""),16);

RA = G.multiply(rA).normalize();

return new TransportEntity(RA.getEncoded(false), null,Z,keyPair.getPublicKey());

}


/**

* 密钥协商响应方

*

* @param entity 传输实体

* @return

*/

public TransportEntity keyExchange_2(TransportEntity entity) {

BigInteger rB = random(n);

// BigInteger rB=new BigInteger("33FE2194 0342161C 55619C4A 0C060293

// D543C80A F19748CE 176D8347 7DE71C80".replace(" ", ""),16);

ECPoint RB = G.multiply(rB).normalize();


this.rA=rB;

this.RA=RB;


BigInteger x2 = RB.getXCoord().toBigInteger();

x2 = _2w.add(x2.and(_2w.subtract(BigInteger.ONE)));


BigInteger tB = keyPair.getPrivateKey().add(x2.multiply(rB)).mod(n);

ECPoint RA = curve.decodePoint(entity.R).normalize();


BigInteger x1 = RA.getXCoord().toBigInteger();

x1 = _2w.add(x1.and(_2w.subtract(BigInteger.ONE)));


ECPoint aPublicKey=curve.decodePoint(entity.K).normalize();

ECPoint temp = aPublicKey.add(RA.multiply(x1).normalize()).normalize();

ECPoint V = temp.multiply(ecc_bc_spec.getH().multiply(tB)).normalize();

if (V.isInfinity())

throw new IllegalStateException();

this.V=V;


byte[] xV = V.getXCoord().toBigInteger().toByteArray();

byte[] yV = V.getYCoord().toBigInteger().toByteArray();

byte[] KB = KDF(join(xV, yV, entity.Z, this.Z), 16);

key = KB;

System.out.print("协商得B密钥:");

printHexString(KB);

byte[] sB = sm3hash(new byte[] { 0x02 }, yV,

sm3hash(xV, entity.Z, this.Z, RA.getXCoord().toBigInteger().toByteArray(),

RA.getYCoord().toBigInteger().toByteArray(), RB.getXCoord().toBigInteger().toByteArray(),

RB.getYCoord().toBigInteger().toByteArray()));

return new TransportEntity(RB.getEncoded(false), sB,this.Z,keyPair.getPublicKey());

}


/**

* 密钥协商发起方第二步

*

* @param entity 传输实体

*/

public TransportEntity keyExchange_3(TransportEntity entity) {

BigInteger x1 = RA.getXCoord().toBigInteger();

x1 = _2w.add(x1.and(_2w.subtract(BigInteger.ONE)));


BigInteger tA = keyPair.getPrivateKey().add(x1.multiply(rA)).mod(n);

ECPoint RB = curve.decodePoint(entity.R).normalize();


BigInteger x2 = RB.getXCoord().toBigInteger();

x2 = _2w.add(x2.and(_2w.subtract(BigInteger.ONE)));


ECPoint bPublicKey=curve.decodePoint(entity.K).normalize();

ECPoint temp = bPublicKey.add(RB.multiply(x2).normalize()).normalize();

ECPoint U = temp.multiply(ecc_bc_spec.getH().multiply(tA)).normalize();

if (U.isInfinity())

throw new IllegalStateException();

this.V=U;


byte[] xU = U.getXCoord().toBigInteger().toByteArray();

byte[] yU = U.getYCoord().toBigInteger().toByteArray();

byte[] KA = KDF(join(xU, yU,

this.Z, entity.Z), 16);

key = KA;

System.out.print("协商得A密钥:");

printHexString(KA);

byte[] s1= sm3hash(new byte[] { 0x02 }, yU,

sm3hash(xU, this.Z, entity.Z, RA.getXCoord().toBigInteger().toByteArray(),

RA.getYCoord().toBigInteger().toByteArray(), RB.getXCoord().toBigInteger().toByteArray(),

RB.getYCoord().toBigInteger().toByteArray()));

if(Arrays.equals(entity.S, s1))

System.out.println("B->A 密钥确认成功");

else

System.out.println("B->A 密钥确认失败");

byte[] sA= sm3hash(new byte[] { 0x03 }, yU,

sm3hash(xU, this.Z, entity.Z, RA.getXCoord().toBigInteger().toByteArray(),

RA.getYCoord().toBigInteger().toByteArray(), RB.getXCoord().toBigInteger().toByteArray(),

RB.getYCoord().toBigInteger().toByteArray()));


return new TransportEntity(RA.getEncoded(false), sA,this.Z,keyPair.getPublicKey());

}


/**

* 密钥确认最后一步

*

* @param entity 传输实体

*/

public void keyExchange_4(TransportEntity entity) {

byte[] xV = V.getXCoord().toBigInteger().toByteArray();

byte[] yV = V.getYCoord().toBigInteger().toByteArray();

ECPoint RA = curve.decodePoint(entity.R).normalize();

byte[] s2= sm3hash(new byte[] { 0x03 }, yV,

sm3hash(xV, entity.Z, this.Z, RA.getXCoord().toBigInteger().toByteArray(),

RA.getYCoord().toBigInteger().toByteArray(), this.RA.getXCoord().toBigInteger().toByteArray(),

this.RA.getYCoord().toBigInteger().toByteArray()));

if(Arrays.equals(entity.S, s2))

System.out.println("A->B 密钥确认成功");

else

System.out.println("A->B 密钥确认失败");

}

}


public static void main(String[] args) throws UnsupportedEncodingException {


SM2 sm02 = new SM2();


System.out.println("-----------------公钥加密与解密-----------------");

ECPoint publicKey = sm02.importPublicKey("E:/publickey.pem");

BigInteger privateKey = sm02.importPrivateKey("E:/privatekey.pem");

byte[] data = sm02.encrypt("测试加密aaaaaaaaaaa123aabb", publicKey);

System.out.print("密文:");

SM2.printHexString(data);

System.out.println("解密后明文:" + sm02.decrypt(data, privateKey));


System.out.println("-----------------签名与验签-----------------");

String IDA = "Heartbeats";

String M = "要签名的信息";

Signature signature = sm02.sign(M, IDA, new SM2KeyPair(publicKey, privateKey));

System.out.println("用户标识:" + IDA);

System.out.println("签名信息:" + M);

System.out.println("数字签名:" + signature);

System.out.println("验证签名:" + sm02.verify(M, signature, IDA, publicKey));


System.out.println("-----------------密钥协商-----------------");

String aID = "AAAAAAAAAAAAA";

SM2KeyPair aKeyPair = sm02.generateKeyPair();

KeyExchange aKeyExchange = new KeyExchange(aID,aKeyPair);


String bID = "BBBBBBBBBBBBB";

SM2KeyPair bKeyPair = sm02.generateKeyPair();

KeyExchange bKeyExchange = new KeyExchange(bID,bKeyPair);

TransportEntity entity1 = aKeyExchange.keyExchange_1();

TransportEntity entity2 = bKeyExchange.keyExchange_2(entity1);

TransportEntity entity3 = aKeyExchange.keyExchange_3(entity2);

bKeyExchange.keyExchange_4(entity3);

}


public static class Signature {

BigInteger r;

BigInteger s;


public Signature(BigInteger r, BigInteger s) {

this.r = r;

this.s = s;

}


public String toString() {

return r.toString(16) + "," + s.toString(16);

}

}

}

sm3:

public class SM3 {


private static char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8',

'9', 'A', 'B', 'C', 'D', 'E', 'F'};

private static final String ivHexStr = "7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e";

private static final BigInteger IV = new BigInteger(ivHexStr.replaceAll(" ",

""), 16);

private static final Integer Tj15 = Integer.valueOf("79cc4519", 16);

private static final Integer Tj63 = Integer.valueOf("7a879d8a", 16);

private static final byte[] FirstPadding = {(byte) 0x80};

private static final byte[] ZeroPadding = {(byte) 0x00};


private static int T(int j) {

if (j >= 0 && j <= 15) {

return Tj15.intValue();

} else if (j >= 16 && j <= 63) {

return Tj63.intValue();

} else {

throw new RuntimeException("data invalid");

}

}


private static Integer FF(Integer x, Integer y, Integer z, int j) {

if (j >= 0 && j <= 15) {

return Integer.valueOf(x.intValue() ^ y.intValue() ^ z.intValue());

} else if (j >= 16 && j <= 63) {

return Integer.valueOf((x.intValue() & y.intValue())

| (x.intValue() & z.intValue())

| (y.intValue() & z.intValue()));

} else {

throw new RuntimeException("data invalid");

}

}


private static Integer GG(Integer x, Integer y, Integer z, int j) {

if (j >= 0 && j <= 15) {

return Integer.valueOf(x.intValue() ^ y.intValue() ^ z.intValue());

} else if (j >= 16 && j <= 63) {

return Integer.valueOf((x.intValue() & y.intValue())

| (~x.intValue() & z.intValue()));

} else {

throw new RuntimeException("data invalid");

}

}


private static Integer P0(Integer x) {

return Integer.valueOf(x.intValue()

^ Integer.rotateLeft(x.intValue(), 9)

^ Integer.rotateLeft(x.intValue(), 17));

}


private static Integer P1(Integer x) {

return Integer.valueOf(x.intValue()

^ Integer.rotateLeft(x.intValue(), 15)

^ Integer.rotateLeft(x.intValue(), 23));

}


private static byte[] padding(byte[] source) throws IOException {

if (source.length >= 0x2000000000000000l) {

throw new RuntimeException("src data invalid.");

}

long l = source.length * 8;

long k = 448 - (l + 1) % 512;

if (k < 0) {

k = k + 512;

}

ByteArrayOutputStream baos = new ByteArrayOutputStream();

baos.write(source);

baos.write(FirstPadding);

long i = k - 7;

while (i > 0) {

baos.write(ZeroPadding);

i -= 8;

}

baos.write(long2bytes(l));

return baos.toByteArray();

}


private static byte[] long2bytes(long l) {

byte[] bytes = new byte[8];

for (int i = 0; i < 8; i++) {

bytes[i] = (byte) (l >>> ((7 - i) * 8));

}

return bytes;

}


public static byte[] hash(byte[] source) throws IOException {

byte[] m1 = padding(source);

int n = m1.length / (512 / 8);

byte[] b;

byte[] vi = IV.toByteArray();

byte[] vi1 = null;

for (int i = 0; i < n; i++) {

b = Arrays.copyOfRange(m1, i * 64, (i + 1) * 64);

vi1 = CF(vi, b);

vi = vi1;

}

return vi1;

}


private static byte[] CF(byte[] vi, byte[] bi) throws IOException {

int a, b, c, d, e, f, g, h;

a = toInteger(vi, 0);

b = toInteger(vi, 1);

c = toInteger(vi, 2);

d = toInteger(vi, 3);

e = toInteger(vi, 4);

f = toInteger(vi, 5);

g = toInteger(vi, 6);

h = toInteger(vi, 7);


int[] w = new int[68];

int[] w1 = new int[64];

for (int i = 0; i < 16; i++) {

w[i] = toInteger(bi, i);

}

for (int j = 16; j < 68; j++) {

w[j] = P1(w[j - 16] ^ w[j - 9] ^ Integer.rotateLeft(w[j - 3], 15))

^ Integer.rotateLeft(w[j - 13], 7) ^ w[j - 6];

}

for (int j = 0; j < 64; j++) {

w1[j] = w[j] ^ w[j + 4];

}

int ss1, ss2, tt1, tt2;

for (int j = 0; j < 64; j++) {

ss1 = Integer

.rotateLeft(

Integer.rotateLeft(a, 12) + e

+ Integer.rotateLeft(T(j), j), 7);

ss2 = ss1 ^ Integer.rotateLeft(a, 12);

tt1 = FF(a, b, c, j) + d + ss2 + w1[j];

tt2 = GG(e, f, g, j) + h + ss1 + w[j];

d = c;

c = Integer.rotateLeft(b, 9);

b = a;

a = tt1;

h = g;

g = Integer.rotateLeft(f, 19);

f = e;

e = P0(tt2);

}

byte[] v = toByteArray(a, b, c, d, e, f, g, h);

for (int i = 0; i < v.length; i++) {

v[i] = (byte) (v[i] ^ vi[i]);

}

return v;

}


private static int toInteger(byte[] source, int index) {

StringBuilder valueStr = new StringBuilder("");

for (int i = 0; i < 4; i++) {

valueStr.append(hexDigits[(byte) ((source[index * 4 + i] & 0xF0) >> 4)]);

valueStr.append(hexDigits[(byte) (source[index * 4 + i] & 0x0F)]);

}

return Long.valueOf(valueStr.toString(), 16).intValue();


}


private static byte[] toByteArray(int a, int b, int c, int d, int e, int f,

int g, int h) throws IOException {

ByteArrayOutputStream baos = new ByteArrayOutputStream(32);

baos.write(toByteArray(a));

baos.write(toByteArray(b));

baos.write(toByteArray(c));

baos.write(toByteArray(d));

baos.write(toByteArray(e));

baos.write(toByteArray(f));

baos.write(toByteArray(g));

baos.write(toByteArray(h));

return baos.toByteArray();

}


public static byte[] toByteArray(int i) {

byte[] byteArray = new byte[4];

byteArray[0] = (byte) (i >>> 24);

byteArray[1] = (byte) ((i & 0xFFFFFF) >>> 16);

byteArray[2] = (byte) ((i & 0xFFFF) >>> 8);

byteArray[3] = (byte) (i & 0xFF);

return byteArray;

}

private static String byteToHexString(byte b) {

int n = b;

if (n < 0)

n = 256 + n;

int d1 = n / 16;

int d2 = n % 16;

return ""+hexDigits[d1] + hexDigits[d2];

}


public static String byteArrayToHexString(byte[] b) {

StringBuffer resultSb = new StringBuffer();

for (int i = 0; i < b.length; i++) {

resultSb.append(byteToHexString(b[i]));

}

return resultSb.toString();

}


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

System.out.println(SM3.byteArrayToHexString(SM3.hash("test".getBytes())));

}

}

————————————————

版权声明:本文为博主「程序猿吉良吉影」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。