From a757e304eba54021145c8a90fd159c834d1cf7e3 Mon Sep 17 00:00:00 2001 From: photowey Date: Sat, 2 Dec 2023 23:30:12 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20SM2Util=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E5=AF=86=E9=92=A5=E5=AF=B9=E5=92=8C=E8=AF=81?= =?UTF-8?q?=E4=B9=A6=E7=9A=84=E5=AD=97=E7=AC=A6=E4=B8=B2=E5=BD=A2=E5=BC=8F?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E5=85=B6=E5=AF=B9=E8=B1=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: photowey --- build.gradle | 6 +- src/main/java/twgc/gm/sm2/SM2Util.java | 100 +++++++++++--- src/test/java/SM2UtilTest.java | 176 +++++++++++++++++++++++-- src/test/resources/testdata.yml | 25 ++++ 4 files changed, 280 insertions(+), 27 deletions(-) create mode 100644 src/test/resources/testdata.yml diff --git a/build.gradle b/build.gradle index a9c0e54..ee34234 100644 --- a/build.gradle +++ b/build.gradle @@ -38,13 +38,13 @@ check.dependsOn 'checkstyle' jacoco { toolVersion = "0.8.5" - reportsDir = file("$buildDir/customJacocoReportDir") + reportsDirectory = layout.buildDirectory.dir('customJacocoReportDir') } jacocoTestReport { reports { - xml.enabled false - csv.enabled false + xml.required = false + csv.required = false html.destination file("${buildDir}/jacocoHtml") } } diff --git a/src/main/java/twgc/gm/sm2/SM2Util.java b/src/main/java/twgc/gm/sm2/SM2Util.java index bcad125..226778c 100644 --- a/src/main/java/twgc/gm/sm2/SM2Util.java +++ b/src/main/java/twgc/gm/sm2/SM2Util.java @@ -1,20 +1,5 @@ package twgc.gm.sm2; -import java.io.FileInputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.StringWriter; -import java.math.BigInteger; -import java.security.*; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.security.spec.ECGenParameterSpec; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.X509EncodedKeySpec; -import javax.security.auth.x500.X500Principal; - import org.bouncycastle.asn1.gm.GMNamedCurves; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x9.X9ECParameters; @@ -50,6 +35,19 @@ import twgc.gm.random.SecureRandomFactory; import twgc.gm.utils.Const; +import javax.security.auth.x500.X500Principal; +import java.io.*; +import java.math.BigInteger; +import java.security.*; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.X509EncodedKeySpec; +import java.util.function.Supplier; + /** * @author SamYuan; 吴仙杰 * @Description 国密SM2工具类, 算法提供者 Bouncy Castle @@ -220,6 +218,50 @@ public static X509Certificate loadX509CertificateFromFile(String filename) throw } } + /** + * 从字符串加载私钥 + * + * @param privateKey 字符串字私钥 + * @param password 密码 + * @return {@link PrivateKey} 私钥对象 + * @throws IOException + * @throws OperatorCreationException + * @throws PKCSException + */ + public static PrivateKey loadPrivFromString(String privateKey, String password) throws IOException, OperatorCreationException, PKCSException { + return loadPriv(password, () -> new StringReader(privateKey)); + } + + /** + * 从字符串加载公钥 + * + * @param publicKey 字符串公钥 + * @return {@link PublicKey} 公钥对象 + * @throws IOException + * @throws NoSuchProviderException + * @throws NoSuchAlgorithmException + * @throws InvalidKeySpecException + */ + public static PublicKey loadPublicFromString(String publicKey) throws IOException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException { + return loadPublic(() -> new StringReader(publicKey)); + } + + /** + * 从字符串加载证书 + * + * @param cert 字符串证书 + * @return {@link X509Certificate} 证书对象 + * @throws IOException + * @throws CertificateException + * @throws NoSuchProviderException + */ + public static X509Certificate loadX509CertificateFromString(String cert) throws IOException, CertificateException, NoSuchProviderException { + try (InputStream in = new ByteArrayInputStream(cert.getBytes())) { + CertificateFactory cf = CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME); + return (X509Certificate) cf.generateCertificate(in); + } + } + public static PublicKey derivePublicFromPrivate(PrivateKey privateKey) { BCECPrivateKey localECPrivateKey = (BCECPrivateKey) privateKey; BigInteger d = localECPrivateKey.getD(); @@ -228,4 +270,32 @@ public static PublicKey derivePublicFromPrivate(PrivateKey privateKey) { return new BCECPublicKey(privateKey.getAlgorithm(), pubKeySpec, BouncyCastleProvider.CONFIGURATION); } + + public static PrivateKey loadPriv(String password, Supplier fx) throws IOException, OperatorCreationException, PKCSException { + PrivateKey priv = null; + try (PEMParser pemParser = new PEMParser(fx.get())) { + Object obj = pemParser.readObject(); + if (password != null && password.length() > 0) { + if (obj instanceof PKCS8EncryptedPrivateKeyInfo) { + PKCS8EncryptedPrivateKeyInfo epkInfo = (PKCS8EncryptedPrivateKeyInfo) obj; + InputDecryptorProvider decryptor = new JceOpenSSLPKCS8DecryptorProviderBuilder() + .setProvider(BouncyCastleProvider.PROVIDER_NAME) + .build(password.toCharArray()); + PrivateKeyInfo pkInfo = epkInfo.decryptPrivateKeyInfo(decryptor); + priv = CONVERTER.getPrivateKey(pkInfo); + } + } else { + priv = CONVERTER.getPrivateKey((PrivateKeyInfo) obj); + } + } + return priv; + } + + public static PublicKey loadPublic(Supplier fx) throws IOException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException { + try (PemReader pemReader = new PemReader(fx.get())) { + PemObject spki = pemReader.readPemObject(); + Security.getProvider(BouncyCastleProvider.PROVIDER_NAME); + return KeyFactory.getInstance(Const.EC_VALUE, BouncyCastleProvider.PROVIDER_NAME).generatePublic(new X509EncodedKeySpec(spki.getContent())); + } + } } \ No newline at end of file diff --git a/src/test/java/SM2UtilTest.java b/src/test/java/SM2UtilTest.java index 6809572..c2f556e 100644 --- a/src/test/java/SM2UtilTest.java +++ b/src/test/java/SM2UtilTest.java @@ -1,12 +1,3 @@ -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.*; -import java.security.cert.X509Certificate; -import java.util.Date; -import javax.security.auth.x500.X500Principal; - import org.apache.commons.lang3.RandomStringUtils; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500NameBuilder; @@ -25,7 +16,18 @@ import twgc.gm.random.RandomSNAllocator; import twgc.gm.sm2.SM2Util; import twgc.gm.sm2.SM2X509CertFactory; +import twgc.gm.utils.ConfigLoader; +import javax.security.auth.x500.X500Principal; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.*; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Map; @FixMethodOrder(MethodSorters.JVM) @@ -291,6 +293,162 @@ public void issueCertificate() throws Exception { } + /** + * 测试从 `testdata.yml` 加载配置文件 + * + * @throws IOException + */ + @Test + public void testLoadConfigMap() throws IOException { + InputStream in = SM2UtilTest.class.getResourceAsStream("testdata.yml"); + Map> configMap = ConfigLoader.loadConfig(in); + + Assert.assertNotNull(configMap); + + Map javagm = configMap.get("javagm"); + Assert.assertNotNull(javagm); + + Object testdata = javagm.get("testdata"); + + Assert.assertNotNull(testdata); + String publicKey = (String) ((Map) testdata).get("public-key"); + String privateKey = (String) ((Map) testdata).get("private-key"); + String cert = (String) ((Map) testdata).get("cert"); + + Assert.assertNotNull(publicKey); + Assert.assertNotNull(privateKey); + Assert.assertNotNull(cert); + } + + /** + * 测试从从字符串加载私钥对象 + * + *
+     * javagm:
+     *   testdata:
+     *     private-key: |
+     *       -----BEGIN PRIVATE KEY-----
+     *       MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgc0UCgfELjC0V+xUm
+     *       ELYFmy0J0cee42ZpKyQ4FRTBlJSgCgYIKoEcz1UBgi2hRANCAATJbIFbxcAaDxMk
+     *       7XExTRU/bBnGEu6YfaleJxnLZS40NDNjZV+ztveWfLZk2+oWieykM3/yZ/6IieJk
+     *       5uuohUjD
+     *       -----END PRIVATE KEY-----
+     *     public-key: |
+     *       -----BEGIN PUBLIC KEY-----
+     *       MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEyWyBW8XAGg8TJO1xMU0VP2wZxhLu
+     *       mH2pXicZy2UuNDQzY2Vfs7b3lny2ZNvqFonspDN/8mf+iIniZObrqIVIww==
+     *       -----END PUBLIC KEY-----
+     *     cert: |
+     *       -----BEGIN CERTIFICATE-----
+     *       MIIBdzCCAR2gAwIBAgIJAfA3Qnph7CieMAoGCCqBHM9VAYN1MBIxEDAOBgNVBAMM
+     *       B1Jvb3QgQ0EwHhcNMjMxMjAyMTQzMjMxWhcNODkxMjI3MDAwMDAwWjASMRAwDgYD
+     *       VQQDEwdSb290IENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEyWyBW8XAGg8T
+     *       JO1xMU0VP2wZxhLumH2pXicZy2UuNDQzY2Vfs7b3lny2ZNvqFonspDN/8mf+iIni
+     *       ZObrqIVIw6NcMFowHQYDVR0OBBYEFOMvj2LPGlkOw1M1Pj34klVi8SFgMA8GA1Ud
+     *       EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMBgGA1UdEQQRMA+BDXRlc3RAdHdn
+     *       Yy5jb20wCgYIKoEcz1UBg3UDSAAwRQIgTeoLjt+eP3kwQg17G+l12wj4MQNed1hW
+     *       aZZkJe43rkICIQCdI3WhnrvzhbEijsTXL1woIwnFgY9MIci7BmKLMpMM6w==
+     *       -----END CERTIFICATE-----
+     * 
+ */ + @Test + public void testLoadPrivFromString() throws Exception { + InputStream in = SM2UtilTest.class.getResourceAsStream("testdata.yml"); + Map> configMap = ConfigLoader.loadConfig(in); + Map javagm = configMap.get("javagm"); + Object testdata = javagm.get("testdata"); + + // 模拟从 配置文件 (`testdata.yml` | `application.yml` | 配置中心等) 获取密钥对字符串 + String privateKey = (String) ((Map) testdata).get("private-key"); + + PrivateKey privKey = SM2Util.loadPrivFromString(privateKey, ""); + Assert.assertNotNull(privKey); + } + + /** + * 测试从从字符串加载公钥对象 + * + * @throws Exception + */ + @Test + public void testLoadPublicFromString() throws Exception { + InputStream in = SM2UtilTest.class.getResourceAsStream("testdata.yml"); + Map> configMap = ConfigLoader.loadConfig(in); + Map javagm = configMap.get("javagm"); + Object testdata = javagm.get("testdata"); + + // 模拟从 配置文件 (`testdata.yml` | `application.yml` | 配置中心等) 获取密钥对字符串 + String publicKey = (String) ((Map) testdata).get("public-key"); + PublicKey pubKey = SM2Util.loadPublicFromString(publicKey); + Assert.assertNotNull(pubKey); + } + + /** + * 测试从字符串加载密钥对并测试加解密 + * + * @throws Exception + */ + @Test + public void testLoadPublicAndPrivFromString() throws Exception { + InputStream in = SM2UtilTest.class.getResourceAsStream("testdata.yml"); + Map> configMap = ConfigLoader.loadConfig(in); + Map javagm = configMap.get("javagm"); + Object testdata = javagm.get("testdata"); + + // 模拟从 配置文件 (`testdata.yml` | `application.yml` | 配置中心等) 获取密钥对字符串 + String publicKey = (String) ((Map) testdata).get("public-key"); + String privateKey = (String) ((Map) testdata).get("private-key"); + + PublicKey pubKey = SM2Util.loadPublicFromString(publicKey); + PrivateKey privKey = SM2Util.loadPrivFromString(privateKey, ""); + + Assert.assertNotNull(pubKey); + Assert.assertNotNull(privKey); + + SM2EnginePool sm2EnginePool = new SM2EnginePool(1, SM2Engine.Mode.C1C3C2); + SM2Engine sm2Engine = null; + + try { + SM2Util instance = new SM2Util(); + sm2Engine = sm2EnginePool.borrowObject(); + byte[] encrypted = instance.encrypt(sm2Engine, pubKey, message); + byte[] rs = instance.decrypt(sm2Engine, privKey, encrypted); + Assert.assertEquals(new String(message), new String(rs)); + + byte[] encrypted2 = instance.encrypt(sm2Engine, pubKey, "msg".getBytes()); + rs = instance.decrypt(sm2Engine, privKey, encrypted2); + Assert.assertNotEquals(new String(message), new String(rs)); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(exceptionHappened); + } finally { + if (sm2Engine != null) { + sm2EnginePool.returnObject(sm2Engine); + } + } + } + + /** + * 测试从字符串加载证书对象 + * + * @throws Exception + */ + @Test + public void testLoadX509CertificateFromString() throws Exception { + InputStream in = SM2UtilTest.class.getResourceAsStream("testdata.yml"); + Map> configMap = ConfigLoader.loadConfig(in); + Map javagm = configMap.get("javagm"); + Object testdata = javagm.get("testdata"); + + // 模拟从 配置文件 (`testdata.yml` | `application.yml` | 配置中心等) 获取证书字符串 + String cert = (String) ((Map) testdata).get("cert"); + Assert.assertNotNull(cert); + + X509Certificate certificate = SM2Util.loadX509CertificateFromString(cert); + Assert.assertNotNull(certificate); + Assert.assertEquals("SM3WITHSM2", certificate.getSigAlgName()); + } + static { try { Security.addProvider(new BouncyCastleProvider()); diff --git a/src/test/resources/testdata.yml b/src/test/resources/testdata.yml new file mode 100644 index 0000000..036743b --- /dev/null +++ b/src/test/resources/testdata.yml @@ -0,0 +1,25 @@ +javagm: + testdata: + private-key: | + -----BEGIN PRIVATE KEY----- + MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgc0UCgfELjC0V+xUm + ELYFmy0J0cee42ZpKyQ4FRTBlJSgCgYIKoEcz1UBgi2hRANCAATJbIFbxcAaDxMk + 7XExTRU/bBnGEu6YfaleJxnLZS40NDNjZV+ztveWfLZk2+oWieykM3/yZ/6IieJk + 5uuohUjD + -----END PRIVATE KEY----- + public-key: | + -----BEGIN PUBLIC KEY----- + MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEyWyBW8XAGg8TJO1xMU0VP2wZxhLu + mH2pXicZy2UuNDQzY2Vfs7b3lny2ZNvqFonspDN/8mf+iIniZObrqIVIww== + -----END PUBLIC KEY----- + cert: | + -----BEGIN CERTIFICATE----- + MIIBdzCCAR2gAwIBAgIJAfA3Qnph7CieMAoGCCqBHM9VAYN1MBIxEDAOBgNVBAMM + B1Jvb3QgQ0EwHhcNMjMxMjAyMTQzMjMxWhcNODkxMjI3MDAwMDAwWjASMRAwDgYD + VQQDEwdSb290IENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEyWyBW8XAGg8T + JO1xMU0VP2wZxhLumH2pXicZy2UuNDQzY2Vfs7b3lny2ZNvqFonspDN/8mf+iIni + ZObrqIVIw6NcMFowHQYDVR0OBBYEFOMvj2LPGlkOw1M1Pj34klVi8SFgMA8GA1Ud + EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMBgGA1UdEQQRMA+BDXRlc3RAdHdn + Yy5jb20wCgYIKoEcz1UBg3UDSAAwRQIgTeoLjt+eP3kwQg17G+l12wj4MQNed1hW + aZZkJe43rkICIQCdI3WhnrvzhbEijsTXL1woIwnFgY9MIci7BmKLMpMM6w== + -----END CERTIFICATE----- \ No newline at end of file From 8cbae2cba83c674e1f50fcc0c410ef9eb57e17a5 Mon Sep 17 00:00:00 2001 From: photowey Date: Sun, 3 Dec 2023 20:47:49 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat:=201.SM2Util=20=E5=A4=8D=E7=94=A8?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E5=87=BD=E6=95=B0;2.SM2UtilTest=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20configMap=20=E6=88=90=E5=91=98=E5=8F=98=E9=87=8F;3.?= =?UTF-8?q?=E5=9B=9E=E6=BB=9A=20jacoco=20=E9=85=8D=E7=BD=AE.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: photowey --- build.gradle | 6 ++-- src/main/java/twgc/gm/sm2/SM2Util.java | 34 ++++++++----------- src/test/java/SM2UtilTest.java | 45 ++++++++++++-------------- 3 files changed, 37 insertions(+), 48 deletions(-) diff --git a/build.gradle b/build.gradle index ee34234..a9c0e54 100644 --- a/build.gradle +++ b/build.gradle @@ -38,13 +38,13 @@ check.dependsOn 'checkstyle' jacoco { toolVersion = "0.8.5" - reportsDirectory = layout.buildDirectory.dir('customJacocoReportDir') + reportsDir = file("$buildDir/customJacocoReportDir") } jacocoTestReport { reports { - xml.required = false - csv.required = false + xml.enabled false + csv.enabled false html.destination file("${buildDir}/jacocoHtml") } } diff --git a/src/main/java/twgc/gm/sm2/SM2Util.java b/src/main/java/twgc/gm/sm2/SM2Util.java index 226778c..e7c78a6 100644 --- a/src/main/java/twgc/gm/sm2/SM2Util.java +++ b/src/main/java/twgc/gm/sm2/SM2Util.java @@ -183,31 +183,23 @@ public static String pemFrom(X509Certificate x509Certificate) throws IOException } public static PrivateKey loadPrivFromFile(String filename, String password) throws IOException, OperatorCreationException, PKCSException { - PrivateKey priv = null; - try (PEMParser pemParser = new PEMParser(new FileReader(filename))) { - Object obj = pemParser.readObject(); - if (password != null && password.length() > 0) { - if (obj instanceof PKCS8EncryptedPrivateKeyInfo) { - PKCS8EncryptedPrivateKeyInfo epkInfo = (PKCS8EncryptedPrivateKeyInfo) obj; - InputDecryptorProvider decryptor = new JceOpenSSLPKCS8DecryptorProviderBuilder() - .setProvider(BouncyCastleProvider.PROVIDER_NAME) - .build(password.toCharArray()); - PrivateKeyInfo pkInfo = epkInfo.decryptPrivateKeyInfo(decryptor); - priv = CONVERTER.getPrivateKey(pkInfo); - } - } else { - priv = CONVERTER.getPrivateKey((PrivateKeyInfo) obj); + return loadPriv(password, () -> { + try { + return new FileReader(filename); + } catch (FileNotFoundException e) { + throw new RuntimeException("Private key \"" + filename + "\" not found", e); } - } - return priv; + }); } public static PublicKey loadPublicFromFile(String filename) throws IOException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException { - try (PemReader pemReader = new PemReader(new FileReader(filename))) { - PemObject spki = pemReader.readPemObject(); - Security.getProvider(BouncyCastleProvider.PROVIDER_NAME); - return KeyFactory.getInstance(Const.EC_VALUE, BouncyCastleProvider.PROVIDER_NAME).generatePublic(new X509EncodedKeySpec(spki.getContent())); - } + return loadPublic(() -> { + try { + return new FileReader(filename); + } catch (FileNotFoundException e) { + throw new RuntimeException("Public key \"" + filename + "\" not found", e); + } + }); } public static X509Certificate loadX509CertificateFromFile(String filename) throws IOException, CertificateException, diff --git a/src/test/java/SM2UtilTest.java b/src/test/java/SM2UtilTest.java index c2f556e..acd7765 100644 --- a/src/test/java/SM2UtilTest.java +++ b/src/test/java/SM2UtilTest.java @@ -48,6 +48,8 @@ public class SM2UtilTest { X509Certificate x509Certificate; KeyPair keyPair; + Map> configMap; + public static void saveCSRInPem(PKCS10CertificationRequest csr, String csrFile) throws IOException, OperatorCreationException { String csrPem = SM2Util.pemFrom(csr); Files.write(Paths.get(csrFile), csrPem.getBytes()); @@ -128,6 +130,19 @@ public void generateFile() { Assert.assertTrue(privFile.exists()); Assert.assertTrue(reqFile.exists()); Assert.assertTrue(certFile.exists()); + + } + + @Before + public void loadTestDataConfigMap() { + try { + InputStream in = SM2UtilTest.class.getResourceAsStream("testdata.yml"); + this.configMap = ConfigLoader.loadConfig(in); + + Assert.assertNotNull(this.configMap); + } catch (Exception e) { + Assert.fail(exceptionHappened); + } } //encrypt and decrypt @@ -299,13 +314,8 @@ public void issueCertificate() throws Exception { * @throws IOException */ @Test - public void testLoadConfigMap() throws IOException { - InputStream in = SM2UtilTest.class.getResourceAsStream("testdata.yml"); - Map> configMap = ConfigLoader.loadConfig(in); - - Assert.assertNotNull(configMap); - - Map javagm = configMap.get("javagm"); + public void testLoadConfigMap() { + Map javagm = this.configMap.get("javagm"); Assert.assertNotNull(javagm); Object testdata = javagm.get("testdata"); @@ -353,12 +363,8 @@ public void testLoadConfigMap() throws IOException { */ @Test public void testLoadPrivFromString() throws Exception { - InputStream in = SM2UtilTest.class.getResourceAsStream("testdata.yml"); - Map> configMap = ConfigLoader.loadConfig(in); - Map javagm = configMap.get("javagm"); + Map javagm = this.configMap.get("javagm"); Object testdata = javagm.get("testdata"); - - // 模拟从 配置文件 (`testdata.yml` | `application.yml` | 配置中心等) 获取密钥对字符串 String privateKey = (String) ((Map) testdata).get("private-key"); PrivateKey privKey = SM2Util.loadPrivFromString(privateKey, ""); @@ -372,12 +378,9 @@ public void testLoadPrivFromString() throws Exception { */ @Test public void testLoadPublicFromString() throws Exception { - InputStream in = SM2UtilTest.class.getResourceAsStream("testdata.yml"); - Map> configMap = ConfigLoader.loadConfig(in); - Map javagm = configMap.get("javagm"); + Map javagm = this.configMap.get("javagm"); Object testdata = javagm.get("testdata"); - // 模拟从 配置文件 (`testdata.yml` | `application.yml` | 配置中心等) 获取密钥对字符串 String publicKey = (String) ((Map) testdata).get("public-key"); PublicKey pubKey = SM2Util.loadPublicFromString(publicKey); Assert.assertNotNull(pubKey); @@ -390,12 +393,9 @@ public void testLoadPublicFromString() throws Exception { */ @Test public void testLoadPublicAndPrivFromString() throws Exception { - InputStream in = SM2UtilTest.class.getResourceAsStream("testdata.yml"); - Map> configMap = ConfigLoader.loadConfig(in); - Map javagm = configMap.get("javagm"); + Map javagm = this.configMap.get("javagm"); Object testdata = javagm.get("testdata"); - // 模拟从 配置文件 (`testdata.yml` | `application.yml` | 配置中心等) 获取密钥对字符串 String publicKey = (String) ((Map) testdata).get("public-key"); String privateKey = (String) ((Map) testdata).get("private-key"); @@ -435,12 +435,9 @@ public void testLoadPublicAndPrivFromString() throws Exception { */ @Test public void testLoadX509CertificateFromString() throws Exception { - InputStream in = SM2UtilTest.class.getResourceAsStream("testdata.yml"); - Map> configMap = ConfigLoader.loadConfig(in); - Map javagm = configMap.get("javagm"); + Map javagm = this.configMap.get("javagm"); Object testdata = javagm.get("testdata"); - // 模拟从 配置文件 (`testdata.yml` | `application.yml` | 配置中心等) 获取证书字符串 String cert = (String) ((Map) testdata).get("cert"); Assert.assertNotNull(cert); From d41897066a1603fc46b8d19aa0074df99bf95eda Mon Sep 17 00:00:00 2001 From: photowey Date: Fri, 8 Dec 2023 00:28:00 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat:=201.=E4=B8=BA=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A,?= =?UTF-8?q?=E8=A7=A6=E5=8F=91=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: photowey --- src/main/java/twgc/gm/sm2/SM2Util.java | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main/java/twgc/gm/sm2/SM2Util.java b/src/main/java/twgc/gm/sm2/SM2Util.java index e7c78a6..fedde43 100644 --- a/src/main/java/twgc/gm/sm2/SM2Util.java +++ b/src/main/java/twgc/gm/sm2/SM2Util.java @@ -263,6 +263,16 @@ public static PublicKey derivePublicFromPrivate(PrivateKey privateKey) { BouncyCastleProvider.CONFIGURATION); } + /** + * 加载私钥 + * + * @param password 密码 + * @param fx {@link Reader} 回调函数 + * @return {@link PrivateKey} + * @throws IOException + * @throws OperatorCreationException + * @throws PKCSException + */ public static PrivateKey loadPriv(String password, Supplier fx) throws IOException, OperatorCreationException, PKCSException { PrivateKey priv = null; try (PEMParser pemParser = new PEMParser(fx.get())) { @@ -283,6 +293,16 @@ public static PrivateKey loadPriv(String password, Supplier fx) throws I return priv; } + /** + * 加载公钥 + * + * @param fx {@link Reader} 回调函数 + * @return {@link PublicKey} + * @throws IOException + * @throws NoSuchProviderException + * @throws NoSuchAlgorithmException + * @throws InvalidKeySpecException + */ public static PublicKey loadPublic(Supplier fx) throws IOException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException { try (PemReader pemReader = new PemReader(fx.get())) { PemObject spki = pemReader.readPemObject(); From 321aee660c5cfebeb36619706a9bf0a4faa9703f Mon Sep 17 00:00:00 2001 From: photowey Date: Sat, 9 Dec 2023 00:06:40 +0800 Subject: [PATCH 4/5] =?UTF-8?q?feat:=201.=E6=A0=BC=E5=BC=8F=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81(IDEA=20=E9=81=B5=E5=BE=AA=20checkstyle.xml)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: photowey --- src/main/java/twgc/gm/sm2/SM2Util.java | 25 ++++++++++++------------- src/test/java/SM2UtilTest.java | 21 ++++++++++----------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/main/java/twgc/gm/sm2/SM2Util.java b/src/main/java/twgc/gm/sm2/SM2Util.java index fedde43..bf03963 100644 --- a/src/main/java/twgc/gm/sm2/SM2Util.java +++ b/src/main/java/twgc/gm/sm2/SM2Util.java @@ -1,5 +1,17 @@ package twgc.gm.sm2; +import javax.security.auth.x500.X500Principal; +import java.io.*; +import java.math.BigInteger; +import java.security.*; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.X509EncodedKeySpec; +import java.util.function.Supplier; import org.bouncycastle.asn1.gm.GMNamedCurves; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x9.X9ECParameters; @@ -35,19 +47,6 @@ import twgc.gm.random.SecureRandomFactory; import twgc.gm.utils.Const; -import javax.security.auth.x500.X500Principal; -import java.io.*; -import java.math.BigInteger; -import java.security.*; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.security.spec.ECGenParameterSpec; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.X509EncodedKeySpec; -import java.util.function.Supplier; - /** * @author SamYuan; 吴仙杰 * @Description 国密SM2工具类, 算法提供者 Bouncy Castle diff --git a/src/test/java/SM2UtilTest.java b/src/test/java/SM2UtilTest.java index acd7765..f8ba179 100644 --- a/src/test/java/SM2UtilTest.java +++ b/src/test/java/SM2UtilTest.java @@ -1,3 +1,13 @@ +import javax.security.auth.x500.X500Principal; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.*; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Map; import org.apache.commons.lang3.RandomStringUtils; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500NameBuilder; @@ -18,17 +28,6 @@ import twgc.gm.sm2.SM2X509CertFactory; import twgc.gm.utils.ConfigLoader; -import javax.security.auth.x500.X500Principal; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.*; -import java.security.cert.X509Certificate; -import java.util.Date; -import java.util.Map; - @FixMethodOrder(MethodSorters.JVM) public class SM2UtilTest { From 6b2a5b87e4ef6041e5981132cae3ebd9076f7d97 Mon Sep 17 00:00:00 2001 From: photowey Date: Sat, 9 Dec 2023 16:38:23 +0800 Subject: [PATCH 5/5] =?UTF-8?q?feat:=201.=E4=BC=98=E5=8C=96=20import?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: photowey --- src/main/java/twgc/gm/sm2/SM2Util.java | 3 ++- src/test/java/SM2UtilTest.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/twgc/gm/sm2/SM2Util.java b/src/main/java/twgc/gm/sm2/SM2Util.java index bf03963..0ce9b95 100644 --- a/src/main/java/twgc/gm/sm2/SM2Util.java +++ b/src/main/java/twgc/gm/sm2/SM2Util.java @@ -1,6 +1,5 @@ package twgc.gm.sm2; -import javax.security.auth.x500.X500Principal; import java.io.*; import java.math.BigInteger; import java.security.*; @@ -12,6 +11,8 @@ import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; import java.util.function.Supplier; +import javax.security.auth.x500.X500Principal; + import org.bouncycastle.asn1.gm.GMNamedCurves; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x9.X9ECParameters; diff --git a/src/test/java/SM2UtilTest.java b/src/test/java/SM2UtilTest.java index f8ba179..b3d77a6 100644 --- a/src/test/java/SM2UtilTest.java +++ b/src/test/java/SM2UtilTest.java @@ -1,4 +1,3 @@ -import javax.security.auth.x500.X500Principal; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -8,6 +7,8 @@ import java.security.cert.X509Certificate; import java.util.Date; import java.util.Map; +import javax.security.auth.x500.X500Principal; + import org.apache.commons.lang3.RandomStringUtils; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500NameBuilder;