1、主要内容2、设计目的与需求分析3、实验环境4、系统介绍
4.1 系统组成4.2.所用密码学知识4.3 系统代码实现 5、系统流程图分析
系统总流程图 6、关键代码演示7、 [源码下载](https://pan.baidu.com/s/1YAjLNcMkAyJnRxFKZdH_cA)
1、主要内容(1)基于 SM2 加密、签名算法,结合 SM3 哈希算法生成 SM4 的加密密钥
(2)使用 SM4 加密生成密文
(3)根据密文及 SM2 恢复解密密钥,使用 SM4 恢复明文并进行验证
充分利用我们所学的 SM2,SM3 和 SM4 算法,构造一个具 有签名特性的加解密算法。
将多种加密算法结合对于了解密码算法和构造密码算法有着 非同寻常的意义,同时将多种密钥算法相互结合的思想早在古典密码中的维吉尼亚密码中有体现。但此次基于 SM2,SM3 和 SM4 的密码算法的结合具有创新意义。
win10、IntelliJ IDEA 20204、系统介绍 4.1 系统组成
采用了 SM2 的加解密和签名技术,SM3 的杂凑算法,MD5 的杂 凑算法,SM4 的分组密码加解密技术,对通信双方构造一个签密算法。
4.2.所用密码学知识SM2 算法:SM2 椭圆曲线公钥密码算法是我国自主设计的公钥密码算法,包括 SM2-1 椭圆曲线数字签名算法,SM2-2 椭圆曲线密钥交换协议,SM2-3 椭圆曲线公钥加密 算法,分别用于实现数字签名密钥协商和数据加密等功能。SM2 算法与 RSA 算法不同的 是,SM2 算法是基于椭圆曲线上点群离散对数难题,相对于 RSA 算法,256 位的 SM2 密 码强度已经比 2048 位的 RSA 密码强度要高。 SM2 原理:SM2 椭圆曲线公钥密码算法:我国自主知识产权的商用密码算法,是 ECC (Elliptic Curve Cryptosystem)算法的一种,基于椭圆曲线离散对数问题,计算复杂度 是指数级,求解难度较大,同等安全程度要求下,椭圆曲线密码较其他公钥所需密钥长度小很多。 ECC 算法描述: 1、用户 A 选定一条适合加密的椭圆曲线 Ep(a,b)(如:y2=x3+ax+b),并取椭圆曲线上 一点,作为基点 G。 2、用户 A 选择一个私有密钥 k,并生成公开密钥(公钥 PB)K=kG。 3、用户 A 将 Ep(a,b)和点(公钥)K,G 传给用户 B。 4、用户 B 接到信息后 ,将待传输的明文(M)编码到 Ep(a,b)上一点 M,并产生 一个随机整数 r(r4.3 系统代码实现 主要采用了 JAVA 语言对 SM2,SM3,SM4,MD5 算法进行了部分改写。 对于已经开源的代码我们可以之间从互联网上进行获取。但对于代码的兼容性进行了 部分的修改,同时在主函数上进行了一次签密算法的应用
5、系统流程图分析SM2:
(1)SM2的签名过程如图
(2)SM2的加密如图:
(3)SM2解密过程
(4)SM3加密过程
(5)SM4加密过程
系统总流程图 6、关键代码演示
(6)SM4解密过程
话不多说,上代码
package org.pzone.crypto; import org.bouncycastle.math.ec.ECPoint; import java.math.BigInteger; public class SM2KeyPair { private final ECPoint publicKey; private final BigInteger privateKey; SM2KeyPair(ECPoint publicKey, BigInteger privateKey) { this.publicKey = publicKey; this.privateKey = privateKey; } public ECPoint getPublicKey() { return publicKey; } public BigInteger getPrivateKey() { return privateKey; } }package org.pzone.crypto; import java.math.BigInteger; public class Params { 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); }package org.pzone.crypto; import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; import java.io.*; import java.math.BigInteger; import java.security.SecureRandom; import java.util.Arrays; 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; } 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(); } public static String transHexString(byte[] b) { String Str=""; for (int i = 0; i < b.length; i++) { String hex = Integer.toHexString(b[i] & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } Str=Str+hex; } return Str; } 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; } private boolean allZero(byte[] buffer) { for (int i = 0; i < buffer.length; i++) { if (buffer[i] != 0) return false; } return true; } public byte[] encrypt(String input, ECPoint publicKey) { byte[] inputBuffer = input.getBytes(); if (debug) printHexString(inputBuffer); byte[] C1Buffer; ECPoint kpb; byte[] t; do { BigInteger k = random(n); if (debug) { System.out.print("k: "); printHexString(k.toByteArray()); } ECPoint C1 = G.multiply(k); C1Buffer = C1.getEncoded(false); if (debug) { System.out.print("C1: "); printHexString(C1Buffer); } BigInteger h = ecc_bc_spec.getH(); if (h != null) { ECPoint S = publicKey.multiply(h); if (S.isInfinity()) throw new IllegalStateException(); } kpb = publicKey.multiply(k).normalize(); 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)); byte[] C2 = new byte[inputBuffer.length]; for (int i = 0; i < inputBuffer.length; i++) { C2[i] = (byte) (inputBuffer[i] ^ t[i]); } byte[] C3 = sm3hash(kpb.getXCoord().toBigInteger().toByteArray(), inputBuffer, kpb.getYCoord().toBigInteger().toByteArray()); 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; } 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(); BigInteger h = ecc_bc_spec.getH(); if (h != null) { ECPoint S = C1.multiply(h); if (S.isInfinity()) throw new IllegalStateException(); } ECPoint dBC1 = C1.multiply(privateKey).normalize(); 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(); } 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); 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; } } // // 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; // } private boolean between(BigInteger param, BigInteger min, BigInteger max) { if (param.compareTo(min) >= 0 && param.compareTo(max) < 0) { return true; } else { return false; } } 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; } 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; } 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(); } } 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; } 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(); } } 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; } 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; } 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; } 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; } 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); } 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; } 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; } 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); } } 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()); } 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()); } 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()); } 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()); } 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(); SM2 x = new SM2(); SM2KeyPair keys = x.generateKeyPair(); ECPoint publicKey = keys.getPublicKey(); BigInteger privateKey = keys.getPrivateKey(); System.out.println("-----------------公钥加密与解密-----------------"); 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); } } }package org.pzone.crypto; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.util.Arrays; 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("6".getBytes()))); } }package org.pzone.crypto; // // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.Mode; import cn.hutool.crypto.Padding; import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.symmetric.SymmetricCrypto; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; public class SM4 extends SymmetricCrypto { private static final long serialVersionUID = 1L; public static final String ALGORITHM_NAME = "SM4"; public SM4() { super("SM4"); } public SM4(byte[] key) { super("SM4", key); } public SM4(Mode mode, Padding padding) { this(mode.name(), padding.name()); } public SM4(Mode mode, Padding padding, byte[] key) { this((Mode)mode, (Padding)padding, (byte[])key, (byte[])null); } public SM4(Mode mode, Padding padding, byte[] key, byte[] iv) { this(mode.name(), padding.name(), key, iv); } public SM4(Mode mode, Padding padding, SecretKey key) { this(mode, padding, key, (IvParameterSpec)null); } public SM4(Mode mode, Padding padding, SecretKey key, byte[] iv) { this(mode, padding, key, ArrayUtil.isEmpty(iv) ? (IvParameterSpec)null : new IvParameterSpec(iv)); } public SM4(Mode mode, Padding padding, SecretKey key, IvParameterSpec iv) { this(mode.name(), padding.name(), key, iv); } public SM4(String mode, String padding) { this(mode, padding, (byte[])null); } public SM4(String mode, String padding, byte[] key) { this((String)mode, (String)padding, (byte[])key, (byte[])null); } public SM4(String mode, String padding, byte[] key, byte[] iv) { this(mode, padding, SecureUtil.generateKey("SM4", key), ArrayUtil.isEmpty(iv) ? (IvParameterSpec)null : new IvParameterSpec(iv)); } public SM4(String mode, String padding, SecretKey key) { this((String)mode, (String)padding, (SecretKey)key, (IvParameterSpec)null); } public SM4(String mode, String padding, SecretKey key, IvParameterSpec iv) { super(StrUtil.format("SM4/{}/{}", new Object[]{mode, padding}), key, iv); } } class SM4Main { public static void main(String[] args) { String strkey="Alice"; byte[] key=strkey.getBytes(); String content = "alice"; // byte[] key={5,6,7,0,0,6,2,8,0,1,0,0xC,9,0xE,0xE,5,9}; SymmetricCrypto sm4 =new SM4(key); System.out.println("SM4加解密:"); String encryptHex = sm4.encryptHex(content); System.out.println("encryptHex0:"+encryptHex); String decryptStr = sm4.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8); System.out.println("decryptStr0:"+decryptStr); } }package org.pzone.crypto; import cn.hutool.core.util.CharsetUtil; import cn.hutool.crypto.symmetric.SymmetricCrypto; import org.bouncycastle.math.ec.ECPoint; import java.io.IOException; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class Main { public static void main(String[] args) throws IOException, NoSuchAlgorithmException { SM2 sm02 = new SM2(); SM2KeyPair keys = sm02.generateKeyPair(); ECPoint publicKey = keys.getPublicKey(); BigInteger privateKey = keys.getPrivateKey(); System.out.println("-----------------------SM3计算摘要值-----------------------"); String message="有志者事竟成"; System.out.println("明文消息为:"+message); String Hm=SM3.byteArrayToHexString(SM3.hash(message.getBytes()));//通过哈希函数计算明文的摘要值 System.out.println("明文‘"+message+"’的哈希摘要值:"+Hm); System.out.println("-----------------------SM2加密摘要值-----------------------"); byte[] data = sm02.encrypt(Hm, publicKey);//SM2加密算法加密哈希摘要值 System.out.println("SM2加密结果:"); SM2.printHexString(data);//十六进制输出 System.out.println("--------------------------SM2签名--------------------------"); String IDA = "Alice"; String Message=SM2.transHexString(data); SM2.Signature signature = sm02.sign(Message, IDA, new SM2KeyPair(publicKey, privateKey));//SM2签名算法 System.out.println("用户标识:" + IDA); System.out.println("签名信息:" + Message); System.out.println("数字签名:" + signature); System.out.println("----------------------生成SM4加密秘钥----------------------"); MessageDigest md5 = MessageDigest.getInstance("MD5");//申明使用MD5算法 md5.update(Hm.getBytes()); byte[] sm4_encrypkey=md5.digest(); System.out.println("SM4加密秘钥:"+SM2.transHexString(sm4_encrypkey)); System.out.println("--------------------------SM4加密--------------------------"); String content = IDA; SymmetricCrypto sm4 =new SM4(sm4_encrypkey); String sm4_encrypHex = sm4.encryptHex(content);//加密用户标识 System.out.println("SM4加密结果:"+sm4_encrypHex); System.out.println("--------------------------SM2解密--------------------------"); String decryp_Hm=sm02.decrypt(data, privateKey);//SM2解密得到H(m) System.out.println("解密后的摘要值:" + decryp_Hm); System.out.println("------------------------恢复SM4解密秘钥---------------------"); MessageDigest decryp_md5 = MessageDigest.getInstance("MD5");//申明使用MD5算法 md5.update(decryp_Hm.getBytes());//SM2加密结果通过MD5得到解密秘钥 String sm4_decrypKey=SM2.transHexString(md5.digest()); System.out.println("SM4解密密钥:"+sm4_decrypKey); System.out.println("--------------------------SM4解密--------------------------"); SymmetricCrypto sm4_2 =new SM4(sm4_decrypKey.getBytes()); String decryptStr = sm4.decryptStr(sm4_encrypHex, CharsetUtil.CHARSET_UTF_8);//解密得到用户标识 System.out.println("SM4解密结果:"+decryptStr); System.out.println("--------------------------SM2验证--------------------------"); System.out.println("验证签名:" + sm02.verify(Message, signature, decryptStr, publicKey)); } }7、 源码下载https://pan.baidu.com/s/1YAjLNcMkAyJnRxFKZdH_cA
提取码:1234



