package com.zpc.cryptography; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.util.encoders.Base64; public class SM2Utils { public static byte[] encrypt(byte[] publicKey, byte[] data) throws IOException { if (publicKey == null || publicKey.length == 0) { return null; } if (data == null || data.length == 0) { return null; } byte[] source = new byte[data.length]; System.arraycopy(data, 0, source, 0, data.length); Cipher cipher = new Cipher(); SM2 sm2 = SM2.Instance(); ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey); ECPoint c1 = cipher.Init_enc(sm2, userKey); cipher.Encrypt(source); byte[] c3 = new byte[32]; cipher.Dofinal(c3); DERInteger x = new DERInteger(c1.getX().toBigInteger()); DERInteger y = new DERInteger(c1.getY().toBigInteger()); DEROctetString derDig = new DEROctetString(c3); DEROctetString derEnc = new DEROctetString(source); ASN1EncodableVector v = new ASN1EncodableVector(); v.add(x); v.add(y); v.add(derDig); v.add(derEnc); DERSequence seq = new DERSequence(v); ByteArrayOutputStream bos = new ByteArrayOutputStream(); DEROutputStream dos = new DEROutputStream(bos); dos.writeObject(seq); return bos.toByteArray(); } public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException { if (privateKey == null || privateKey.length == 0) { return null; } if (encryptedData == null || encryptedData.length == 0) { return null; } byte[] enc = new byte[encryptedData.length]; System.arraycopy(encryptedData, 0, enc, 0, encryptedData.length); SM2 sm2 = SM2.Instance(); BigInteger userD = new BigInteger(1, privateKey); ByteArrayInputStream bis = new ByteArrayInputStream(enc); ASN1InputStream dis = new ASN1InputStream(bis); ASN1Primitive derObj = dis.readObject(); //DERObject derObj = dis.readObject(); ASN1Sequence asn1 = (ASN1Sequence) derObj; //DERInteger x = (DERInteger) asn1.getObjectAt(0); //DERInteger y = (DERInteger) asn1.getObjectAt(1); ASN1Integer x = (ASN1Integer) asn1.getObjectAt(0); ASN1Integer y = (ASN1Integer) asn1.getObjectAt(1); ECPoint c1 = sm2.ecc_curve.createPoint(x.getValue(), y.getValue(), true); Cipher cipher = new Cipher(); cipher.Init_dec(userD, c1); DEROctetString data = (DEROctetString) asn1.getObjectAt(3); enc = data.getOctets(); cipher.Decrypt(enc); byte[] c3 = new byte[32]; cipher.Dofinal(c3); return enc; } /** * 簽名 * * @param userId * @param privateKey * @param sourceData * @return * @throws IOException */ public static byte[] sign(byte[] userId, byte[] privateKey, byte[] sourceData) throws IOException { if (privateKey == null || privateKey.length == 0) { return null; } if (sourceData == null || sourceData.length == 0) { return null; } SM2 sm2 = SM2.Instance(); BigInteger userD = new BigInteger(privateKey); //System.out.println("userD: " + userD.toString(16)); //System.out.println(""); ECPoint userKey = sm2.ecc_point_g.multiply(userD); //System.out.println("橢圓曲線點X: " + userKey.getX().toBigInteger().toString(16)); //System.out.println("橢圓曲線點Y: " + userKey.getY().toBigInteger().toString(16)); //System.out.println(""); byte[] z = sm2.sm2GetZ(userId, userKey); //System.out.println("SM3摘要Z: " + Util.getHexString(z)); //System.out.println(""); //System.out.println("M: " + Util.getHexString(sourceData)); //System.out.println(""); SM3Digest sm3 = new SM3Digest(); sm3.update(z, 0, z.length); sm3.update(sourceData, 0, sourceData.length); byte[] md = new byte[32]; sm3.doFinal(md, 0); //System.out.println("SM3摘要值: " + Util.getHexString(md)); //System.out.println(""); SM2Result sm2Result = new SM2Result(); sm2.sm2Sign(md, userD, userKey, sm2Result); //System.out.println("r: " + sm2Result.r.toString(16)); //System.out.println("s: " + sm2Result.s.toString(16)); //System.out.println(""); DERInteger d_r = new DERInteger(sm2Result.r); DERInteger d_s = new DERInteger(sm2Result.s); ASN1EncodableVector v2 = new ASN1EncodableVector(); v2.add(d_r); v2.add(d_s); DERSequence sign = new DERSequence(v2); //DERObject sign = new DERSequence(v2); //byte[] signdata = sign.getDEREncoded(); byte[] signdata = sign.getEncoded(); return signdata; } @SuppressWarnings("unchecked") public static boolean verifySign(byte[] userId, byte[] publicKey, byte[] sourceData, byte[] signData) throws IOException { if (publicKey == null || publicKey.length == 0) { return false; } if (sourceData == null || sourceData.length == 0) { return false; } SM2 sm2 = SM2.Instance(); ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey); SM3Digest sm3 = new SM3Digest(); byte[] z = sm2.sm2GetZ(userId, userKey); sm3.update(z, 0, z.length); sm3.update(sourceData, 0, sourceData.length); byte[] md = new byte[32]; sm3.doFinal(md, 0); //System.out.println("SM3摘要值: " + Util.getHexString(md)); //System.out.println(""); ByteArrayInputStream bis = new ByteArrayInputStream(signData); ASN1InputStream dis = new ASN1InputStream(bis); //DERObject derObj = dis.readObject(); ASN1Primitive derObj = dis.readObject(); Enumeration<ASN1Integer> e = ((ASN1Sequence) derObj).getObjects(); BigInteger r = e.nextElement().getValue(); BigInteger s = e.nextElement().getValue(); SM2Result sm2Result = new SM2Result(); sm2Result.r = r; sm2Result.s = s; //System.out.println("r: " + sm2Result.r.toString(16)); //System.out.println("s: " + sm2Result.s.toString(16)); //System.out.println(""); sm2.sm2Verify(md, userKey, sm2Result.r, sm2Result.s, sm2Result); return sm2Result.r.equals(sm2Result.R); } public static void main(String[] args) throws Exception { String plainText = "message digest"; //1.源數據數組 byte[] sourceData = plainText.getBytes(); // 國密規範測試私鑰 String prik = "128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263"; //2.私鑰先轉十六進制,而後進行Base64編碼 String prikS = new String(Base64.encode(Util.hexToByte(prik))); System.out.println("轉換後的私鑰:prikS====" + prikS); //System.out.println(""); // 國密規範測試用戶ID String userId = "ALICE123@YAHOO.COM"; //獲取userId十六進制字符串 System.out.println("十六進制userId: " + Util.getHexString(userId.getBytes())); //System.out.println(""); //System.out.println("簽名: "); //3.用userId和私鑰,對明文數據簽名(userid、prik、sourceData) byte[] c = SM2Utils.sign(userId.getBytes(), Base64.decode(prikS.getBytes()), sourceData); System.out.println("SM2簽名後值====" + Util.getHexString(c)); //System.out.println(""); // 國密規範測試公鑰 String pubk = "040AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857"; String pubkS = new String(Base64.encode(Util.hexToByte(pubk))); System.out.println("轉換後的公鑰pubkS====" + pubkS); //System.out.println(""); //System.out.println("驗籤: "); //4.用公鑰進行驗籤(userId、pubk、sourceData、簽名數據c) boolean vs = SM2Utils.verifySign(userId.getBytes(), Base64.decode(pubkS.getBytes()), sourceData, c); System.out.println("驗簽結果: " + vs); //System.out.println(""); //System.out.println("加密: "); //5.SM2加密算法 byte[] cipherText = SM2Utils.encrypt(Base64.decode(pubkS.getBytes()), sourceData); System.out.println("SM2加密後結果===" + new String(Base64.encode(cipherText))); System.out.println(""); //System.out.println("解密: "); //6.SM2解密算法 plainText = new String(SM2Utils.decrypt(Base64.decode(prikS.getBytes()), cipherText)); System.out.println("解密後獲取的結果===" + plainText); } }
兩個相關JAR從這裏下載java
https://pan.baidu.com/s/1ggDmn3H算法
https://pan.baidu.com/s/1mkcK3nM數組