├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── antherd │ │ └── smcrypto │ │ ├── NashornProvider.java │ │ ├── Provider.java │ │ ├── sm2 │ │ ├── Keypair.java │ │ ├── Point.java │ │ ├── SignatureOptions.java │ │ └── Sm2.java │ │ ├── sm3 │ │ └── Sm3.java │ │ └── sm4 │ │ ├── Sm4.java │ │ └── Sm4Options.java └── resources │ ├── sm2.js │ ├── sm3.js │ └── sm4.js └── test └── java └── com └── antherd └── smcrypto ├── Sm2Test.java ├── Sm3Test.java └── Sm4Test.java /.gitignore: -------------------------------------------------------------------------------- 1 | .mvn 2 | target/ 3 | !**/src/main/**/target/ 4 | !**/src/test/**/target/ 5 | 6 | ### STS ### 7 | .apt_generated 8 | .classpath 9 | .factorypath 10 | .project 11 | .settings 12 | .springBeans 13 | .sts4-cache 14 | 15 | ### IntelliJ IDEA ### 16 | .idea 17 | *.iws 18 | *.iml 19 | *.ipr 20 | 21 | ### NetBeans ### 22 | /nbproject/private/ 23 | /nbbuild/ 24 | /dist/ 25 | /nbdist/ 26 | /.nb-gradle/ 27 | build/ 28 | !**/src/main/**/build/ 29 | !**/src/test/**/build/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | /.mvn/ 34 | /mvnw 35 | /mvnw.cmd 36 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.3.2.1 2 | * 兼容高版本JDK,提示添加 nashorn-core 依赖 3 | ## 0.3.2 4 | * 基于[sm-crypto js版本](https://github.com/antherd/sm-crypto-js) 封装。sm-crypto js 版本号 [0.3.2] 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 antherd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sm-crypto 2 | 3 | 国密算法sm2、sm3和sm4的java版。基于js版本进行封装,无缝兼容js版公私钥加解密。 4 | 5 | > PS: js版:[https://github.com/JuneAndGreen/sm-crypto](https://github.com/JuneAndGreen/sm-crypto) 6 | > 7 | > PS: 小程序版:[https://github.com/wechat-miniprogram/sm-crypto](https://github.com/wechat-miniprogram/sm-crypto) 8 | 9 | ## 如何使用 10 | ### 如何引入依赖 11 | 如果需要使用已发布的版本,在`dependencies`中添加如下依赖 12 | ```xml 13 | 14 | com.antherd 15 | sm-crypto 16 | 0.3.2.1 17 | 18 | ``` 19 | 20 | ## sm2 21 | 22 | ### 获取密钥对 23 | 24 | ```java 25 | Keypair keypair = Sm2.generateKeyPairHex(); 26 | String privateKey = keypair.getPrivateKey(); // 公钥 27 | String publicKey = keypair.getPublicKey(); // 私钥 28 | ``` 29 | 30 | ### 加密解密 31 | 32 | ```java 33 | // cipherMode 1 - C1C3C2,0 - C1C2C3,默认为1 34 | String encryptData = Sm2.doEncrypt(msg, publicKey); // 加密结果 35 | String decryptData = Sm2.doDecrypt(encryptData, privateKey); // 解密结果 36 | ``` 37 | 38 | ### 签名验签 39 | 40 | > ps:理论上来说,只做纯签名是最快的。 41 | 42 | ```java 43 | // 纯签名 + 生成椭圆曲线点 44 | String sigValueHex = Sm2.doSignature(msg, privateKey); // 签名 45 | boolean verifyResult = Sm2.doVerifySignature(msg, sigValueHex, publicKey); // 验签结果 46 | 47 | // 纯签名 48 | Queue pointPool = new LinkedList(Arrays.asList(Sm2.getPoint(), Sm2.getPoint(), Sm2.getPoint(), Sm2.getPoint())); 49 | SignatureOptions signatureOptions2 = new SignatureOptions(); 50 | signatureOptions2.setPointPool(pointPool); // 传入事先已生成好的椭圆曲线点,可加快签名速度 51 | String sigValueHex2 = Sm2.doSignature(msg, privateKey, signatureOptions2); 52 | boolean verifyResult2 = Sm2.doVerifySignature(msg, sigValueHex2, publicKey); // 验签结果 53 | 54 | // 纯签名 + 生成椭圆曲线点 + der编解码 55 | SignatureOptions signatureOptions3 = new SignatureOptions(); 56 | signatureOptions3.setDer(true); 57 | String sigValueHex3 = Sm2.doSignature(msg, privateKey, signatureOptions3); // 签名 58 | boolean verifyResult3 = Sm2.doVerifySignature(msg, sigValueHex3, publicKey, signatureOptions3); // 验签结果 59 | 60 | // 纯签名 + 生成椭圆曲线点 + sm3杂凑 61 | SignatureOptions signatureOptions4 = new SignatureOptions(); 62 | signatureOptions4.setHash(true); 63 | String sigValueHex4 = Sm2.doSignature(msg, privateKey, signatureOptions4); // 签名 64 | boolean verifyResult4 = Sm2.doVerifySignature(msg, sigValueHex4, publicKey, signatureOptions4); // 验签结果 65 | 66 | // 纯签名 + 生成椭圆曲线点 + sm3杂凑(不做公钥推导) 67 | SignatureOptions signatureOptions5 = new SignatureOptions(); 68 | signatureOptions5.setHash(true); 69 | signatureOptions5.setPublicKey(publicKey); // 传入公钥的话,可以去掉sm3杂凑中推导公钥的过程,速度会比纯签名 + 生成椭圆曲线点 + sm3杂凑快 70 | String sigValueHex5 = Sm2.doSignature(msg, privateKey, signatureOptions5); // 签名 71 | boolean verifyResult5 = Sm2.doVerifySignature(msg, sigValueHex5, publicKey, signatureOptions5); // 验签结果 72 | 73 | // 纯签名 + 生成椭圆曲线点 + sm3杂凑 + 不做公钥推 + 添加 userId(长度小于 8192) 74 | // 默认 userId 值为 1234567812345678 75 | SignatureOptions signatureOptions6 = new SignatureOptions(); 76 | signatureOptions6.setHash(true); 77 | signatureOptions6.setPublicKey(publicKey); 78 | signatureOptions6.setUserId("testUserId"); 79 | String sigValueHex6 = Sm2.doSignature(msg, privateKey, signatureOptions6); // 签名 80 | boolean verifyResult6 = Sm2.doVerifySignature(msg, sigValueHex6, publicKey, signatureOptions6); // 验签结果 81 | ``` 82 | 83 | ### 获取椭圆曲线点 84 | 85 | ```java 86 | Point point = Sm2.getPoint(); // 获取一个椭圆曲线点,可在sm2签名时传入 87 | ``` 88 | 89 | ## sm3 90 | 91 | ```java 92 | String hashData = Sm3.sm3("abc"); // 杂凑 93 | ``` 94 | 95 | ## sm4 96 | 97 | ### 加密 98 | 99 | ```java 100 | String msg = "hello world! 我是 antherd."; 101 | String key = "0123456789abcdeffedcba9876543210"; // 16 进制字符串,要求为 128 比特 102 | 103 | String encryptData1 = Sm4.encrypt(msg, key); // 加密,默认使用 pkcs#5 填充,输出16进制字符串 104 | 105 | Sm4Options sm4Options2 = new Sm4Options(); 106 | sm4Options2.setPadding("none"); 107 | String encryptData2 = Sm4.encrypt(msg, key, sm4Options2); // 加密,不使用 padding,输出16进制字符串 108 | 109 | Sm4Options sm4Options3 = new Sm4Options(); 110 | sm4Options3.setPadding("none"); 111 | byte[] encryptData3 = Sm4.hexToBytes(Sm4.encrypt(msg, key, sm4Options3)); // 加密,不使用 padding,输出转为字节数组 112 | 113 | Sm4Options sm4Options4 = new Sm4Options(); 114 | sm4Options4.setMode("cbc"); 115 | sm4Options4.setIv("fedcba98765432100123456789abcdef"); 116 | String encryptData4 = Sm4.encrypt(msg, key, sm4Options4); // 加密,cbc 模式,输出16进制字符串 117 | ``` 118 | 119 | ### 解密 120 | 121 | ```java 122 | String encryptData = "0e395deb10f6e8a17e17823e1fd9bd98a1bff1df508b5b8a1efb79ec633d1bb129432ac1b74972dbe97bab04f024e89c"; // 加密后的 16 进制字符串 123 | String key = "0123456789abcdeffedcba9876543210"; // 16 进制字符串,要求为 128 比特 124 | 125 | String decryptData5 = Sm4.decrypt(encryptData, key); // 解密,默认使用 pkcs#5 填充,输出 utf8 字符串 126 | 127 | Sm4Options sm4Options6 = new Sm4Options(); 128 | sm4Options6.setPadding("none"); 129 | String decryptData6 = Sm4.decrypt(encryptData, key, sm4Options6); // 解密,不使用 padding,输出 utf8 字符串 130 | 131 | Sm4Options sm4Options7 = new Sm4Options(); 132 | sm4Options7.setPadding("none"); 133 | byte[] decryptData7 = Sm4.utf8ToArray(Sm4.decrypt(encryptData, key, sm4Options7)); // 解密,不使用 padding,输出转为字节数组 134 | 135 | Sm4Options sm4Options8 = new Sm4Options(); 136 | sm4Options8.setMode("cbc"); 137 | sm4Options8.setIv("fedcba98765432100123456789abcdef"); 138 | String decryptData8 = Sm4.decrypt(encryptData, key, sm4Options8); // 解密,cbc 模式,输出 utf8 字符串 139 | ``` 140 | 141 | ## 协议 142 | 143 | [MIT](https://github.com/antherd/sm-crypto/blob/master/LICENSE) 144 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | com.antherd 6 | sm-crypto 7 | 0.3.2.1 8 | 9 | sm-crypto 10 | 国密算法sm2、sm3和sm4的java版 11 | https://github.com/antherd/sm-crypto 12 | 13 | 14 | 15 | MIT License 16 | https://github.com/antherd/sm-crypto/blob/master/LICENSE 17 | repo 18 | 19 | 20 | 21 | 22 | https://github.com/antherd/sm-crypto 23 | 24 | scm:git:git://github.com/antherd/sm-crypto.git 25 | 26 | 27 | scm:git:ssh://git@github.com/antherd/sm-crypto.git 28 | 29 | HEAD 30 | 31 | 32 | 33 | 34 | geyiwei 35 | geyiwei@outlook.com 36 | 37 | 38 | 39 | 40 | 1.8 41 | 1.8 42 | 1.8 43 | 44 | 45 | 46 | 47 | junit 48 | junit 49 | 4.13.1 50 | test 51 | 52 | 53 | 54 | 55 | 56 | 57 | sonatype-nexus-snapshots 58 | https://s01.oss.sonatype.org/content/repositories/snapshots 59 | 60 | 61 | sonatype-nexus-staging 62 | https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ 63 | 64 | 65 | 66 | 67 | 68 | 69 | org.sonatype.plugins 70 | nexus-staging-maven-plugin 71 | 1.6.7 72 | true 73 | 74 | sonatype-nexus-staging 75 | https://s01.oss.sonatype.org/ 76 | true 77 | 78 | 79 | 80 | 81 | 82 | org.apache.maven.plugins 83 | maven-source-plugin 84 | 2.2.1 85 | 86 | 87 | attach-sources 88 | 89 | jar-no-fork 90 | 91 | 92 | 93 | 94 | 95 | org.apache.maven.plugins 96 | maven-javadoc-plugin 97 | 2.9.1 98 | 99 | ${java.home}/../bin/javadoc 100 | 101 | -Xdoclint:none 102 | 103 | 104 | 105 | 106 | attach-javadocs 107 | 108 | jar 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | org.apache.maven.plugins 117 | maven-gpg-plugin 118 | 1.5 119 | 120 | 121 | sign-artifacts 122 | verify 123 | 124 | sign 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /src/main/java/com/antherd/smcrypto/NashornProvider.java: -------------------------------------------------------------------------------- 1 | package com.antherd.smcrypto; 2 | 3 | import java.util.concurrent.atomic.AtomicBoolean; 4 | 5 | /** 6 | * @author Ice2Faith 7 | */ 8 | public class NashornProvider { 9 | 10 | public static final String JDK_NASHORN_CLASS_NAME = "jdk.nashorn.api.scripting.NashornScriptEngine"; 11 | public static final String OPENJDK_NASHORN_CLASS_NAME = "org.openjdk.nashorn.api.scripting.NashornScriptEngine"; 12 | public static final String NASHORN_MAVEN_DEPENDENCY = "" + 13 | "\n" + 14 | " org.openjdk.nashorn\n" + 15 | " nashorn-core\n" + 16 | " 15.4\n" + 17 | ""; 18 | 19 | private static final AtomicBoolean printed = new AtomicBoolean(false); 20 | private static final AtomicBoolean checked = new AtomicBoolean(false); 21 | private static final AtomicBoolean status = new AtomicBoolean(false); 22 | 23 | static { 24 | printNonNashorn(); 25 | } 26 | 27 | public static void printNonNashorn() { 28 | if (printed.getAndSet(true)) { 29 | return; 30 | } 31 | boolean has = checkHasNashorn(); 32 | if (has) { 33 | return; 34 | } 35 | System.err.println("none nashorn JavaScript engine found! please add this dependency into your pom.xml: \n" + NASHORN_MAVEN_DEPENDENCY); 36 | } 37 | 38 | public static synchronized boolean checkHasNashorn() { 39 | if (checked.get()) { 40 | return status.get(); 41 | } 42 | ClassLoader loader = Thread.currentThread().getContextClassLoader(); 43 | String[] arr = new String[]{JDK_NASHORN_CLASS_NAME, OPENJDK_NASHORN_CLASS_NAME}; 44 | for (int i = 0; i < arr.length; i++) { 45 | String className = arr[i]; 46 | try { 47 | Class clazz = Class.forName(className); 48 | if (clazz != null) { 49 | status.set(true); 50 | break; 51 | } 52 | } catch (Throwable e) { 53 | 54 | } 55 | try { 56 | Class clazz = loader.loadClass(className); 57 | if (clazz != null) { 58 | status.set(true); 59 | break; 60 | } 61 | } catch (Throwable e) { 62 | 63 | } 64 | } 65 | checked.set(true); 66 | return status.get(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/antherd/smcrypto/Provider.java: -------------------------------------------------------------------------------- 1 | package com.antherd.smcrypto; 2 | 3 | import javax.script.ScriptEngine; 4 | import javax.script.ScriptEngineManager; 5 | import javax.script.ScriptException; 6 | import java.io.BufferedReader; 7 | import java.io.InputStream; 8 | import java.io.InputStreamReader; 9 | 10 | /** 11 | * @author Ice2Faith 12 | */ 13 | public class Provider { 14 | public static final String SM2_CLASSPATH_RESOURCE_PATH = "sm2.js"; 15 | public static final String SM3_CLASSPATH_RESOURCE_PATH = "sm3.js"; 16 | public static final String SM4_CLASSPATH_RESOURCE_PATH = "sm4.js"; 17 | public static final String ENGINE_NAME = "JavaScript"; 18 | 19 | public static ScriptEngine getJavaScriptEngine(String resourcePath) throws ScriptException { 20 | return getEngine(ENGINE_NAME, resourcePath); 21 | } 22 | 23 | public static ScriptEngine getEngine(String engineName, String resourcePath) throws ScriptException { 24 | ScriptEngine engine = new ScriptEngineManager().getEngineByName(engineName); 25 | if (resourcePath != null) { 26 | InputStream inputStream = Provider.class.getClassLoader().getResourceAsStream(resourcePath); 27 | assert inputStream != null; 28 | engine.eval(new BufferedReader(new InputStreamReader(inputStream))); 29 | } 30 | return engine; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/antherd/smcrypto/sm2/Keypair.java: -------------------------------------------------------------------------------- 1 | package com.antherd.smcrypto.sm2; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 公私钥对 7 | * @author geyiwei 8 | */ 9 | public class Keypair implements Serializable { 10 | 11 | protected String privateKey; 12 | protected String publicKey; 13 | 14 | public Keypair() { 15 | } 16 | 17 | public Keypair(String privateKey, String publicKey) { 18 | this.privateKey = privateKey; 19 | this.publicKey = publicKey; 20 | } 21 | 22 | public String getPrivateKey() { 23 | return privateKey; 24 | } 25 | 26 | public void setPrivateKey(String privateKey) { 27 | this.privateKey = privateKey; 28 | } 29 | 30 | public String getPublicKey() { 31 | return publicKey; 32 | } 33 | 34 | public void setPublicKey(String publicKey) { 35 | this.publicKey = publicKey; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "Keypair{" + 41 | "privateKey='" + privateKey + '\'' + 42 | ", publicKey='" + publicKey + '\'' + 43 | '}'; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/antherd/smcrypto/sm2/Point.java: -------------------------------------------------------------------------------- 1 | package com.antherd.smcrypto.sm2; 2 | 3 | import java.io.Serializable; 4 | import java.util.Map; 5 | 6 | public class Point extends Keypair implements Serializable { 7 | 8 | private Map k; 9 | private Map x1; 10 | 11 | public Point() { 12 | } 13 | 14 | public Point(Map k, Map x1) { 15 | this.k = k; 16 | this.x1 = x1; 17 | } 18 | 19 | public Point(String privateKey, String publicKey, Map k, Map x1) { 20 | super(privateKey, publicKey); 21 | this.k = k; 22 | this.x1 = x1; 23 | } 24 | 25 | public Map getK() { 26 | return k; 27 | } 28 | 29 | public void setK(Map k) { 30 | this.k = k; 31 | } 32 | 33 | public Map getX1() { 34 | return x1; 35 | } 36 | 37 | public void setX1(Map x1) { 38 | this.x1 = x1; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return "Point{" + 44 | "privateKey=" + privateKey + 45 | ", publicKey=" + publicKey + 46 | ", k=" + k + 47 | ", x1=" + x1 + 48 | '}'; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/antherd/smcrypto/sm2/SignatureOptions.java: -------------------------------------------------------------------------------- 1 | package com.antherd.smcrypto.sm2; 2 | 3 | import java.util.Queue; 4 | 5 | /** 6 | * @author geyiwei 7 | */ 8 | public class SignatureOptions { 9 | 10 | /** 11 | * 椭圆曲线点 12 | */ 13 | Queue pointPool; 14 | 15 | /** 16 | * der编解码 17 | */ 18 | boolean der; 19 | 20 | /** 21 | * sm3杂凑 22 | */ 23 | boolean hash; 24 | 25 | /** 26 | * 公钥 27 | */ 28 | String publicKey; 29 | 30 | /** 31 | * userId(长度小于 8192)默认值为 1234567812345678 32 | */ 33 | String userId; 34 | 35 | public SignatureOptions() { 36 | } 37 | 38 | public SignatureOptions(Queue pointPool, boolean der, boolean hash, String publicKey, String userId) { 39 | this.pointPool = pointPool; 40 | this.der = der; 41 | this.hash = hash; 42 | this.publicKey = publicKey; 43 | this.userId = userId; 44 | } 45 | 46 | public Queue getPointPool() { 47 | return pointPool; 48 | } 49 | 50 | public void setPointPool(Queue pointPool) { 51 | this.pointPool = pointPool; 52 | } 53 | 54 | public boolean isDer() { 55 | return der; 56 | } 57 | 58 | public void setDer(boolean der) { 59 | this.der = der; 60 | } 61 | 62 | public boolean isHash() { 63 | return hash; 64 | } 65 | 66 | public void setHash(boolean hash) { 67 | this.hash = hash; 68 | } 69 | 70 | public String getPublicKey() { 71 | return publicKey; 72 | } 73 | 74 | public void setPublicKey(String publicKey) { 75 | this.publicKey = publicKey; 76 | } 77 | 78 | public String getUserId() { 79 | return userId; 80 | } 81 | 82 | public void setUserId(String userId) { 83 | this.userId = userId; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/com/antherd/smcrypto/sm2/Sm2.java: -------------------------------------------------------------------------------- 1 | package com.antherd.smcrypto.sm2; 2 | 3 | import com.antherd.smcrypto.NashornProvider; 4 | import com.antherd.smcrypto.Provider; 5 | 6 | import javax.script.*; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | /** 11 | * @author geyiwei 12 | */ 13 | public class Sm2 { 14 | public static final int MODE_C1C3C2 = 0; 15 | public static final int MODE_C1C2C3 = 1; 16 | 17 | static { 18 | NashornProvider.printNonNashorn(); 19 | } 20 | private static Invocable invocable = null; 21 | 22 | static { 23 | try { 24 | invocable = (Invocable) Provider.getJavaScriptEngine(Provider.SM2_CLASSPATH_RESOURCE_PATH); 25 | } catch (ScriptException e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | 30 | /** 31 | * 生成密钥对:publicKey = privateKey * G 32 | * 33 | * @return 公私钥对 34 | * @throws ScriptException Scripting通用异常 35 | */ 36 | public static Keypair generateKeyPairHex() throws ScriptException { 37 | Bindings bindings = null; 38 | try { 39 | bindings = (Bindings) invocable.invokeFunction("generateKeyPairHex"); 40 | } catch (NoSuchMethodException e) { 41 | e.printStackTrace(); 42 | } 43 | return new Keypair((String) bindings.get("privateKey"), (String) bindings.get("publicKey")); 44 | } 45 | 46 | /** 47 | * 加密 48 | * 49 | * @param msg 明文 50 | * @param publicKey 公钥 51 | * @param cipherMode 1 - C1C3C2,0 - C1C2C3 52 | * @return 密文 53 | * @throws ScriptException Scripting通用异常 54 | */ 55 | public static String doEncrypt(String msg, String publicKey, int cipherMode) throws ScriptException { 56 | if (msg == null || msg.trim().isEmpty()) { 57 | return ""; 58 | } 59 | String encryptMsg = null; 60 | try { 61 | Object[] param = new Object[]{msg, publicKey, cipherMode}; 62 | encryptMsg = (String) invocable.invokeFunction("doEncrypt", param); 63 | } catch (NoSuchMethodException e) { 64 | e.printStackTrace(); 65 | } 66 | return encryptMsg; 67 | } 68 | 69 | /** 70 | * 加密 cipherMode = 1 71 | * 72 | * @param msg 明文 73 | * @param publicKey 公钥 74 | * @return 密文 75 | * @throws ScriptException Scripting通用异常 76 | */ 77 | public static String doEncrypt(String msg, String publicKey) throws ScriptException { 78 | return doEncrypt(msg, publicKey, MODE_C1C2C3); 79 | } 80 | 81 | /** 82 | * 解密 83 | * 84 | * @param encryptData 密文 85 | * @param privateKey 私钥 86 | * @param cipherMode 1 - C1C3C2,0 - C1C2C3 87 | * @return 明文 88 | * @throws ScriptException Scripting通用异常 89 | */ 90 | public static String doDecrypt(String encryptData, String privateKey, int cipherMode) throws ScriptException { 91 | if (encryptData == null || encryptData.trim().isEmpty()) { 92 | return ""; 93 | } 94 | String msg = null; 95 | try { 96 | Object[] param = new Object[]{encryptData, privateKey, cipherMode}; 97 | msg = (String) invocable.invokeFunction("doDecrypt", param); 98 | } catch (NoSuchMethodException e) { 99 | e.printStackTrace(); 100 | } 101 | return msg; 102 | } 103 | 104 | /** 105 | * 解密 cipherMode = 1 106 | * 107 | * @param encryptData 密文 108 | * @param privateKey 私钥 109 | * @return 明文 110 | * @throws ScriptException Scripting通用异常 111 | */ 112 | public static String doDecrypt(String encryptData, String privateKey) throws ScriptException { 113 | return doDecrypt(encryptData, privateKey, MODE_C1C2C3); 114 | } 115 | 116 | /** 117 | * 签名 118 | * 119 | * @param msg 明文 120 | * @param publicKey 公钥 121 | * @param signatureOptions 签名配置 122 | * @return 签名 123 | * @throws ScriptException Scripting通用异常 124 | */ 125 | public static String doSignature(String msg, String publicKey, SignatureOptions signatureOptions) throws ScriptException { 126 | String signature = null; 127 | try { 128 | signature = (String) invocable.invokeFunction("doSignature", msg, publicKey, getOptionsMap(signatureOptions)); 129 | } catch (NoSuchMethodException e) { 130 | e.printStackTrace(); 131 | } 132 | return signature; 133 | } 134 | 135 | /** 136 | * 签名 137 | * 138 | * @param msg 明文 139 | * @param publicKey 公钥 140 | * @return 签名 141 | * @throws ScriptException Scripting通用异常 142 | */ 143 | public static String doSignature(String msg, String publicKey) throws ScriptException { 144 | return doSignature(msg, publicKey, null); 145 | } 146 | 147 | /** 148 | * 验签 149 | * 150 | * @param msg 明文 151 | * @param signHex 签名 152 | * @param publicKey 公钥 153 | * @param signatureOptions 签名配置 154 | * @return 验签是否通过 155 | * @throws ScriptException Scripting通用异常 156 | */ 157 | public static boolean doVerifySignature(String msg, String signHex, String publicKey, SignatureOptions signatureOptions) throws ScriptException { 158 | boolean result = false; 159 | try { 160 | result = (boolean) invocable.invokeFunction("doVerifySignature", msg, signHex, publicKey, getOptionsMap(signatureOptions)); 161 | } catch (NoSuchMethodException e) { 162 | e.printStackTrace(); 163 | } 164 | return result; 165 | } 166 | 167 | /** 168 | * 验签 169 | * 170 | * @param msg 明文 171 | * @param signHex 签名 172 | * @param publicKey 公钥 173 | * @return 验签是否通过 174 | * @throws ScriptException Scripting通用异常 175 | */ 176 | public static boolean doVerifySignature(String msg, String signHex, String publicKey) throws ScriptException { 177 | return doVerifySignature(msg, signHex, publicKey, null); 178 | } 179 | 180 | /** 181 | * 若签名配置中为默认值, js调用时不添加此参数 182 | * 183 | * @param signatureOptions 签名配置 184 | * @return 签名配置Map 185 | */ 186 | private static Map getOptionsMap(SignatureOptions signatureOptions) { 187 | Map options = new HashMap<>(6); 188 | if (signatureOptions == null) { 189 | return options; 190 | } 191 | if (signatureOptions.getPointPool() != null && signatureOptions.getPointPool().size() == 4) { 192 | options.put("pointPool", signatureOptions.getPointPool()); 193 | } 194 | if (signatureOptions.isDer()) { 195 | options.put("der", signatureOptions.isDer()); 196 | } 197 | if (signatureOptions.isHash()) { 198 | options.put("hash", signatureOptions.isHash()); 199 | } 200 | String publicKey = signatureOptions.getPublicKey(); 201 | if (publicKey != null && !"".equals(publicKey.trim())) { 202 | options.put("publicKey", publicKey); 203 | } 204 | String userId = signatureOptions.getUserId(); 205 | if (userId != null && !"".equals(userId.trim())) { 206 | options.put("userId", userId); 207 | } 208 | return options; 209 | } 210 | 211 | /** 212 | * 获取椭圆曲线点 213 | * 214 | * @return 椭圆曲线点 215 | */ 216 | public static Point getPoint() { 217 | Point point = null; 218 | try { 219 | Bindings bindings = (Bindings) invocable.invokeFunction("getPoint"); 220 | point = new Point((String) bindings.get("privateKey"), (String) bindings.get("publicKey"), (Map) bindings.get("k"), (Map) bindings.get("x1")); 221 | } catch (ScriptException | NoSuchMethodException e) { 222 | e.printStackTrace(); 223 | } 224 | return point; 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /src/main/java/com/antherd/smcrypto/sm3/Sm3.java: -------------------------------------------------------------------------------- 1 | package com.antherd.smcrypto.sm3; 2 | 3 | import com.antherd.smcrypto.NashornProvider; 4 | import com.antherd.smcrypto.Provider; 5 | 6 | import javax.script.Invocable; 7 | import javax.script.ScriptException; 8 | 9 | /** 10 | * @author geyiwei 11 | */ 12 | public class Sm3 { 13 | static { 14 | NashornProvider.printNonNashorn(); 15 | } 16 | private static Invocable invocable = null; 17 | 18 | static { 19 | try { 20 | invocable = (Invocable) Provider.getJavaScriptEngine(Provider.SM3_CLASSPATH_RESOURCE_PATH); 21 | } catch (ScriptException e) { 22 | e.printStackTrace(); 23 | } 24 | } 25 | 26 | /** 27 | * 杂凑 28 | * 29 | * @param msg 明文 30 | * @return 杂凑 31 | * @throws ScriptException Scripting通用异常 32 | */ 33 | public static String sm3(String msg) throws ScriptException { 34 | if (msg == null || msg.trim().isEmpty()) { 35 | return ""; 36 | } 37 | String hashData = null; 38 | try { 39 | hashData = (String) invocable.invokeFunction("constructSm3", msg); 40 | } catch (NoSuchMethodException e) { 41 | e.printStackTrace(); 42 | } 43 | return hashData; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/antherd/smcrypto/sm4/Sm4.java: -------------------------------------------------------------------------------- 1 | package com.antherd.smcrypto.sm4; 2 | 3 | import com.antherd.smcrypto.NashornProvider; 4 | import com.antherd.smcrypto.Provider; 5 | 6 | import javax.script.Invocable; 7 | import javax.script.ScriptException; 8 | import java.nio.charset.StandardCharsets; 9 | import java.security.SecureRandom; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | /** 14 | * @author geyiwei 15 | */ 16 | public class Sm4 { 17 | static { 18 | NashornProvider.printNonNashorn(); 19 | } 20 | private static Invocable invocable = null; 21 | public static SecureRandom RANDOM = new SecureRandom(); 22 | 23 | static { 24 | try { 25 | invocable = (Invocable) Provider.getJavaScriptEngine(Provider.SM4_CLASSPATH_RESOURCE_PATH); 26 | } catch (ScriptException e) { 27 | e.printStackTrace(); 28 | } 29 | } 30 | 31 | 32 | /** 33 | * 随机生成一个可用的 SM4 秘钥 34 | * 35 | * @return SM4 秘钥 36 | */ 37 | public static String generateKeyHex() { 38 | byte[] bytes = new byte[16]; 39 | RANDOM.nextBytes(bytes); 40 | return bytesToHex(bytes); 41 | } 42 | 43 | /** 44 | * 加密 45 | * 46 | * @param msg 明文 47 | * @param key key 16 进制字符串,要求为 128 比特 48 | * @param sm4Options 加密配置 49 | * @return 密文 50 | * @throws ScriptException Scripting通用异常 51 | */ 52 | public static String encrypt(String msg, String key, Sm4Options sm4Options) throws ScriptException { 53 | if (msg == null || msg.trim().isEmpty()) { 54 | return ""; 55 | } 56 | String encryptData = null; 57 | try { 58 | encryptData = (String) invocable.invokeFunction("encrypt", msg, key, getOptionsMap(sm4Options)); 59 | } catch (NoSuchMethodException e) { 60 | e.printStackTrace(); 61 | } 62 | return encryptData; 63 | } 64 | 65 | /** 66 | * 加密 67 | * 68 | * @param msg 明文 69 | * @param key key 16 进制字符串,要求为 128 比特 70 | * @return 密文 71 | * @throws ScriptException Scripting通用异常 72 | */ 73 | public static String encrypt(String msg, String key) throws ScriptException { 74 | return encrypt(msg, key, null); 75 | } 76 | 77 | /** 78 | * 解密 79 | * 80 | * @param encryptData 密文 81 | * @param key key 16 进制字符串,要求为 128 比特 82 | * @param sm4Options 加密配置 83 | * @return 明文 84 | * @throws ScriptException Scripting通用异常 85 | */ 86 | public static String decrypt(String encryptData, String key, Sm4Options sm4Options) throws ScriptException { 87 | if (encryptData == null || encryptData.trim().isEmpty()) { 88 | return ""; 89 | } 90 | String decryptData = null; 91 | try { 92 | decryptData = (String) invocable.invokeFunction("decrypt", encryptData, key, getOptionsMap(sm4Options)); 93 | } catch (NoSuchMethodException e) { 94 | e.printStackTrace(); 95 | } 96 | return decryptData; 97 | } 98 | 99 | /** 100 | * 解密 101 | * 102 | * @param encryptData 密文 103 | * @param key 16 进制字符串,要求为 128 比特 104 | * @return 明文 105 | * @throws ScriptException Scripting通用异常 106 | */ 107 | public static String decrypt(String encryptData, String key) throws ScriptException { 108 | return decrypt(encryptData, key, null); 109 | } 110 | 111 | /** 112 | * 16 进制串转字节数组 113 | * 114 | * @param hex 16进制字符串 115 | * @return byte数组 116 | */ 117 | public static byte[] hexToBytes(String hex) { 118 | int length = hex.length(); 119 | byte[] result; 120 | if (length % 2 == 1) { 121 | length++; 122 | result = new byte[(length / 2)]; 123 | hex = "0" + hex; 124 | } else { 125 | result = new byte[(length / 2)]; 126 | } 127 | int j = 0; 128 | for (int i = 0; i < length; i += 2) { 129 | result[j] = hexToByte(hex.substring(i, i + 2)); 130 | j++; 131 | } 132 | return result; 133 | } 134 | 135 | /** 136 | * 16 进制字符转字节 137 | * 138 | * @param hex 16进制字符 0x00到0xFF 139 | * @return byte 140 | */ 141 | private static byte hexToByte(String hex) { 142 | return (byte) Integer.parseInt(hex, 16); 143 | } 144 | 145 | /** 146 | * byte数组转 16 进制字符串 147 | * 148 | * @param bytes byte数组 149 | * @return 16 进制字符串 150 | */ 151 | public static String bytesToHex(byte[] bytes) { 152 | if (bytes == null) { 153 | return null; 154 | } 155 | StringBuilder sb = new StringBuilder(); 156 | for (byte aByte : bytes) { 157 | String hex = Integer.toHexString(aByte & 0xFF); 158 | if (hex.length() < 2) { 159 | sb.append(0); 160 | } 161 | sb.append(hex); 162 | } 163 | return sb.toString(); 164 | } 165 | 166 | /** 167 | * utf8 串转字节数组 168 | * 169 | * @param str utf8 串 170 | * @return byte数组 171 | */ 172 | public static byte[] utf8ToArray(String str) { 173 | return str.getBytes(StandardCharsets.UTF_8); 174 | } 175 | 176 | /** 177 | * 字节数组转 utf8 串 178 | * 179 | * @param arr byte数组 180 | * @return utf8 串 181 | */ 182 | public static String arrayToUtf8(byte[] arr) { 183 | return new String(arr, StandardCharsets.UTF_8); 184 | } 185 | 186 | /** 187 | * 若sm4配置中为默认值, js调用时不添加此参数 188 | * 189 | * @param sm4Options 加密配置 190 | * @return 加密配置Map 191 | */ 192 | private static Map getOptionsMap(Sm4Options sm4Options) { 193 | Map options = new HashMap<>(); 194 | if (sm4Options == null) { 195 | return options; 196 | } 197 | String padding = sm4Options.getPadding(); 198 | if (padding != null && !"".equals(padding.trim())) { 199 | options.put("padding", padding); 200 | } 201 | String mode = sm4Options.getMode(); 202 | if (mode != null && !"".equals(mode.trim())) { 203 | options.put("mode", mode); 204 | } 205 | String iv = sm4Options.getIv(); 206 | if (iv != null && !"".equals(iv.trim())) { 207 | options.put("iv", iv); 208 | } 209 | return options; 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/main/java/com/antherd/smcrypto/sm4/Sm4Options.java: -------------------------------------------------------------------------------- 1 | package com.antherd.smcrypto.sm4; 2 | 3 | /** 4 | * @author geyiwei 5 | */ 6 | public class Sm4Options { 7 | 8 | String padding; 9 | String mode; 10 | String iv; 11 | 12 | public Sm4Options() { 13 | } 14 | 15 | public Sm4Options(String padding, String mode, String iv) { 16 | this.padding = padding; 17 | this.mode = mode; 18 | this.iv = iv; 19 | } 20 | 21 | public String getPadding() { 22 | return padding; 23 | } 24 | 25 | public void setPadding(String padding) { 26 | this.padding = padding; 27 | } 28 | 29 | public String getMode() { 30 | return mode; 31 | } 32 | 33 | public void setMode(String mode) { 34 | this.mode = mode; 35 | } 36 | 37 | public String getIv() { 38 | return iv; 39 | } 40 | 41 | public void setIv(String iv) { 42 | this.iv = iv; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "Sm4Options{" + 48 | "padding='" + padding + '\'' + 49 | ", mode='" + mode + '\'' + 50 | ", iv='" + iv + '\'' + 51 | '}'; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/resources/sm2.js: -------------------------------------------------------------------------------- 1 | sm2 = function(t){function i(e){if(r[e])return r[e].exports;var n=r[e]={i:e,l:!1,exports:{}};return t[e].call(n.exports,n,n.exports,i),n.l=!0,n.exports}var r={};return i.m=t,i.c=r,i.d=function(t,r,e){i.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:e})},i.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(r,"a",r),r},i.o=function(t,i){return Object.prototype.hasOwnProperty.call(t,i)},i.p="",i(i.s=2)}([function(t,i,r){(function(){function r(t,i,r){null!=t&&("number"==typeof t?this.fromNumber(t,i,r):null==i&&"string"!=typeof t?this.fromString(t,256):this.fromString(t,i))}function e(){return new r(null)}function n(t,i,r,e,n,o){for(;--o>=0;){var s=i*this[t++]+r[e]+n;n=Math.floor(s/67108864),r[e++]=67108863&s}return n}function o(t,i,r,e,n,o){for(var s=32767&i,u=i>>15;--o>=0;){var h=32767&this[t],a=this[t++]>>15,f=u*h+a*s;h=s*h+((32767&f)<<15)+r[e]+(1073741823&n),n=(h>>>30)+(f>>>15)+u*a+(n>>>30),r[e++]=1073741823&h}return n}function s(t,i,r,e,n,o){for(var s=16383&i,u=i>>14;--o>=0;){var h=16383&this[t],a=this[t++]>>14,f=u*h+a*s;h=s*h+((16383&f)<<14)+r[e]+n,n=(h>>28)+(f>>14)+u*a,r[e++]=268435455&h}return n}function u(t){return pi.charAt(t)}function h(t,i){var r=vi[t.charCodeAt(i)];return null==r?-1:r}function a(t){for(var i=this.t-1;i>=0;--i)t[i]=this[i];t.t=this.t,t.s=this.s}function f(t){this.t=1,this.s=t<0?-1:0,t>0?this[0]=t:t<-1?this[0]=t+this.DV:this.t=0}function l(t){var i=e();return i.fromInt(t),i}function c(t,i){var e;if(16==i)e=4;else if(8==i)e=3;else if(256==i)e=8;else if(2==i)e=1;else if(32==i)e=5;else{if(4!=i)return void this.fromRadix(t,i);e=2}this.t=0,this.s=0;for(var n=t.length,o=!1,s=0;--n>=0;){var u=8==e?255&t[n]:h(t,n);u<0?"-"==t.charAt(n)&&(o=!0):(o=!1,0==s?this[this.t++]=u:s+e>this.DB?(this[this.t-1]|=(u&(1<>this.DB-s):this[this.t-1]|=u<=this.DB&&(s-=this.DB))}8==e&&0!=(128&t[0])&&(this.s=-1,s>0&&(this[this.t-1]|=(1<0&&this[this.t-1]==t;)--this.t}function v(t){if(this.s<0)return"-"+this.negate().toString(t);var i;if(16==t)i=4;else if(8==t)i=3;else if(2==t)i=1;else if(32==t)i=5;else{if(4!=t)return this.toRadix(t);i=2}var r,e=(1<0)for(h>h)>0&&(n=!0,o=u(r));s>=0;)h>(h+=this.DB-i)):(r=this[s]>>(h-=i)&e,h<=0&&(h+=this.DB,--s)),r>0&&(n=!0),n&&(o+=u(r));return n?o:"0"}function y(){var t=e();return r.ZERO.subTo(this,t),t}function m(){return this.s<0?this.negate():this}function g(t){var i=this.s-t.s;if(0!=i)return i;var r=this.t;if(0!=(i=r-t.t))return this.s<0?-i:i;for(;--r>=0;)if(0!=(i=this[r]-t[r]))return i;return 0}function d(t){var i,r=1;return 0!=(i=t>>>16)&&(t=i,r+=16),0!=(i=t>>8)&&(t=i,r+=8),0!=(i=t>>4)&&(t=i,r+=4),0!=(i=t>>2)&&(t=i,r+=2),0!=(i=t>>1)&&(t=i,r+=1),r}function T(){return this.t<=0?0:this.DB*(this.t-1)+d(this[this.t-1]^this.s&this.DM)}function F(t,i){var r;for(r=this.t-1;r>=0;--r)i[r+t]=this[r];for(r=t-1;r>=0;--r)i[r]=0;i.t=this.t+t,i.s=this.s}function b(t,i){for(var r=t;r=0;--r)i[r+s+1]=this[r]>>n|u,u=(this[r]&o)<=0;--r)i[r]=0;i[s]=u,i.t=this.t+s+1,i.s=this.s,i.clamp()}function w(t,i){i.s=this.s;var r=Math.floor(t/this.DB);if(r>=this.t)return void(i.t=0);var e=t%this.DB,n=this.DB-e,o=(1<>e;for(var s=r+1;s>e;e>0&&(i[this.t-r-1]|=(this.s&o)<>=this.DB;if(t.t>=this.DB;e+=this.s}else{for(e+=this.s;r>=this.DB;e-=t.s}i.s=e<0?-1:0,e<-1?i[r++]=this.DV+e:e>0&&(i[r++]=e),i.t=r,i.clamp()}function D(t,i){var e=this.abs(),n=t.abs(),o=e.t;for(i.t=o+n.t;--o>=0;)i[o]=0;for(o=0;o=0;)t[r]=0;for(r=0;r=i.DV&&(t[r+i.t]-=i.DV,t[r+i.t+1]=1)}t.t>0&&(t[t.t-1]+=i.am(r,i[r],t,2*r,0,1)),t.s=0,t.clamp()}function I(t,i,n){var o=t.abs();if(!(o.t<=0)){var s=this.abs();if(s.t0?(o.lShiftTo(f,u),s.lShiftTo(f,n)):(o.copyTo(u),s.copyTo(n));var l=u.t,c=u[l-1];if(0!=c){var p=c*(1<1?u[l-2]>>this.F2:0),v=this.FV/p,y=(1<=0&&(n[n.t++]=1,n.subTo(F,n)),r.ONE.dlShiftTo(l,F),F.subTo(u,u);u.t=0;){var b=n[--g]==c?this.DM:Math.floor(n[g]*v+(n[g-1]+m)*y);if((n[g]+=u.am(0,b,n,T,0,l))0&&n.rShiftTo(f,n),h<0&&r.ZERO.subTo(n,n)}}}function E(t){var i=e();return this.abs().divRemTo(t,null,i),this.s<0&&i.compareTo(r.ZERO)>0&&t.subTo(i,i),i}function q(t){this.m=t}function O(t){return t.s<0||t.compareTo(this.m)>=0?t.mod(this.m):t}function A(t){return t}function R(t){t.divRemTo(this.m,null,t)}function M(t,i,r){t.multiplyTo(i,r),this.reduce(r)}function P(t,i){t.squareTo(i),this.reduce(i)}function C(){if(this.t<1)return 0;var t=this[0];if(0==(1&t))return 0;var i=3&t;return i=i*(2-(15&t)*i)&15,i=i*(2-(255&t)*i)&255,i=i*(2-((65535&t)*i&65535))&65535,i=i*(2-t*i%this.DV)%this.DV,i>0?this.DV-i:-i}function k(t){this.m=t,this.mp=t.invDigit(),this.mpl=32767&this.mp,this.mph=this.mp>>15,this.um=(1<0&&this.m.subTo(i,i),i}function H(t){var i=e();return t.copyTo(i),this.reduce(i),i}function N(t){for(;t.t<=this.mt2;)t[t.t++]=0;for(var i=0;i>15)*this.mpl&this.um)<<15)&t.DM;for(r=i+this.m.t,t[r]+=this.m.am(0,e,t,i,0,this.m.t);t[r]>=t.DV;)t[r]-=t.DV,t[++r]++}t.clamp(),t.drShiftTo(this.m.t,t),t.compareTo(this.m)>=0&&t.subTo(this.m,t)}function L(t,i){t.squareTo(i),this.reduce(i)}function z(t,i,r){t.multiplyTo(i,r),this.reduce(r)}function j(){return 0==(this.t>0?1&this[0]:this.s)}function Z(t,i){if(t>4294967295||t<1)return r.ONE;var n=e(),o=e(),s=i.convert(this),u=d(t)-1;for(s.copyTo(n);--u>=0;)if(i.sqrTo(n,o),(t&1<0)i.mulTo(o,s,n);else{var h=n;n=o,o=h}return i.revert(n)}function _(t,i){var r;return r=t<256||i.isEven()?new q(i):new k(i),this.exp(t,r)}function K(){var t=e();return this.copyTo(t),t}function U(){if(this.s<0){if(1==this.t)return this[0]-this.DV;if(0==this.t)return-1}else{if(1==this.t)return this[0];if(0==this.t)return 0}return(this[1]&(1<<32-this.DB)-1)<>24}function G(){return 0==this.t?this.s:this[0]<<16>>16}function Y(t){return Math.floor(Math.LN2*this.DB/Math.log(t))}function J(){return this.s<0?-1:this.t<=0||1==this.t&&this[0]<=0?0:1}function Q(t){if(null==t&&(t=10),0==this.signum()||t<2||t>36)return"0";var i=this.chunkSize(t),r=Math.pow(t,i),n=l(r),o=e(),s=e(),u="";for(this.divRemTo(n,o,s);o.signum()>0;)u=(r+s.intValue()).toString(t).substr(1)+u,o.divRemTo(n,o,s);return s.intValue().toString(t)+u}function W(t,i){this.fromInt(0),null==i&&(i=10);for(var e=this.chunkSize(i),n=Math.pow(i,e),o=!1,s=0,u=0,a=0;a=e&&(this.dMultiply(n),this.dAddOffset(u,0),s=0,u=0))}s>0&&(this.dMultiply(Math.pow(i,s)),this.dAddOffset(u,0)),o&&r.ZERO.subTo(this,this)}function $(t,i,e){if("number"==typeof i)if(t<2)this.fromInt(1);else for(this.fromNumber(t,e),this.testBit(t-1)||this.bitwiseTo(r.ONE.shiftLeft(t-1),ut,this),this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(i);)this.dAddOffset(2,0),this.bitLength()>t&&this.subTo(r.ONE.shiftLeft(t-1),this);else{var n=new Array,o=7&t;n.length=1+(t>>3),i.nextBytes(n),o>0?n[0]&=(1<0)for(e>e)!=(this.s&this.DM)>>e&&(i[n++]=r|this.s<=0;)e<8?(r=(this[t]&(1<>(e+=this.DB-8)):(r=this[t]>>(e-=8)&255,e<=0&&(e+=this.DB,--t)),0!=(128&r)&&(r|=-256),0==n&&(128&this.s)!=(128&r)&&++n,(n>0||r!=this.s)&&(i[n++]=r);return i}function it(t){return 0==this.compareTo(t)}function rt(t){return this.compareTo(t)<0?this:t}function et(t){return this.compareTo(t)>0?this:t}function nt(t,i,r){var e,n,o=Math.min(t.t,this.t);for(e=0;e>=16,i+=16),0==(255&t)&&(t>>=8,i+=8),0==(15&t)&&(t>>=4,i+=4),0==(3&t)&&(t>>=2,i+=2),0==(1&t)&&++i,i}function gt(){for(var t=0;t=this.t?0!=this.s:0!=(this[i]&1<>=this.DB;if(t.t>=this.DB;e+=this.s}else{for(e+=this.s;r>=this.DB;e+=t.s}i.s=e<0?-1:0,e>0?i[r++]=e:e<-1&&(i[r++]=this.DV+e),i.t=r,i.clamp()}function St(t){var i=e();return this.addTo(t,i),i}function It(t){var i=e();return this.subTo(t,i),i}function Et(t){var i=e();return this.multiplyTo(t,i),i}function qt(){var t=e();return this.squareTo(t),t}function Ot(t){var i=e();return this.divRemTo(t,i,null),i}function At(t){var i=e();return this.divRemTo(t,null,i),i}function Rt(t){var i=e(),r=e();return this.divRemTo(t,i,r),new Array(i,r)}function Mt(t){this[this.t]=this.am(0,t-1,this,0,0,this.t),++this.t,this.clamp()}function Pt(t,i){if(0!=t){for(;this.t<=i;)this[this.t++]=0;for(this[i]+=t;this[i]>=this.DV;)this[i]-=this.DV,++i>=this.t&&(this[this.t++]=0),++this[i]}}function Ct(){}function kt(t){return t}function Vt(t,i,r){t.multiplyTo(i,r)}function Ht(t,i){t.squareTo(i)}function Nt(t){return this.exp(t,new Ct)}function Lt(t,i,r){var e=Math.min(this.t+t.t,i);for(r.s=0,r.t=e;e>0;)r[--e]=0;var n;for(n=r.t-this.t;e=0;)r[e]=0;for(e=Math.max(i-this.t,0);e2*this.m.t)return t.mod(this.m);if(t.compareTo(this.m)<0)return t;var i=e();return t.copyTo(i),this.reduce(i),i}function _t(t){return t}function Kt(t){for(t.drShiftTo(this.m.t-1,this.r2),t.t>this.m.t+1&&(t.t=this.m.t+1,t.clamp()),this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3),this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);t.compareTo(this.r2)<0;)t.dAddOffset(1,this.m.t+1);for(t.subTo(this.r2,t);t.compareTo(this.m)>=0;)t.subTo(this.m,t)}function Ut(t,i){t.squareTo(i),this.reduce(i)}function Xt(t,i,r){t.multiplyTo(i,r),this.reduce(r)}function Gt(t,i){var r,n,o=t.bitLength(),s=l(1);if(o<=0)return s;r=o<18?1:o<48?3:o<144?4:o<768?5:6,n=o<8?new q(i):i.isEven()?new jt(i):new k(i);var u=new Array,h=3,a=r-1,f=(1<1){var c=e();for(n.sqrTo(u[1],c);h<=f;)u[h]=e(),n.mulTo(c,u[h-2],u[h]),h+=2}var p,v,y=t.t-1,m=!0,g=e();for(o=d(t[y])-1;y>=0;){for(o>=a?p=t[y]>>o-a&f:(p=(t[y]&(1<0&&(p|=t[y-1]>>this.DB+o-a)),h=r;0==(1&p);)p>>=1,--h;if((o-=h)<0&&(o+=this.DB,--y),m)u[p].copyTo(s),m=!1;else{for(;h>1;)n.sqrTo(s,g),n.sqrTo(g,s),h-=2;h>0?n.sqrTo(s,g):(v=s,s=g,g=v),n.mulTo(g,u[p],s)}for(;y>=0&&0==(t[y]&1<0&&(i.rShiftTo(o,i),r.rShiftTo(o,r));i.signum()>0;)(n=i.getLowestSetBit())>0&&i.rShiftTo(n,i),(n=r.getLowestSetBit())>0&&r.rShiftTo(n,r),i.compareTo(r)>=0?(i.subTo(r,i),i.rShiftTo(1,i)):(r.subTo(i,r),r.rShiftTo(1,r));return o>0&&r.lShiftTo(o,r),r}function Jt(t){if(t<=0)return 0;var i=this.DV%t,r=this.s<0?t-1:0;if(this.t>0)if(0==i)r=this[0]%t;else for(var e=this.t-1;e>=0;--e)r=(i*r+this[e])%t;return r}function Qt(t){var i=t.isEven();if(this.isEven()&&i||0==t.signum())return r.ZERO;for(var e=t.clone(),n=this.clone(),o=l(1),s=l(0),u=l(0),h=l(1);0!=e.signum();){for(;e.isEven();)e.rShiftTo(1,e),i?(o.isEven()&&s.isEven()||(o.addTo(this,o),s.subTo(t,s)),o.rShiftTo(1,o)):s.isEven()||s.subTo(t,s),s.rShiftTo(1,s);for(;n.isEven();)n.rShiftTo(1,n),i?(u.isEven()&&h.isEven()||(u.addTo(this,u),h.subTo(t,h)),u.rShiftTo(1,u)):h.isEven()||h.subTo(t,h),h.rShiftTo(1,h);e.compareTo(n)>=0?(e.subTo(n,e),i&&o.subTo(u,o),s.subTo(h,s)):(n.subTo(e,n),i&&u.subTo(o,u),h.subTo(s,h))}return 0!=n.compareTo(r.ONE)?r.ZERO:h.compareTo(t)>=0?h.subtract(t):h.signum()<0?(h.addTo(t,h),h.signum()<0?h.add(t):h):h}function Wt(t){var i,r=this.abs();if(1==r.t&&r[0]<=yi[yi.length-1]){for(i=0;i>1)>yi.length&&(t=yi.length);for(var s=e(),u=0;u>8&255,di[Ti++]^=t>>16&255,di[Ti++]^=t>>24&255,Ti>=wi&&(Ti-=wi)}function ii(){ti((new Date).getTime())}function ri(){if(null==gi){for(ii(),gi=hi(),gi.init(di),Ti=0;Ti>>8,di[Ti++]=255&Fi;Ti=0,ii()}ni.prototype.nextBytes=ei,oi.prototype.init=si,oi.prototype.next=ui;var wi=256;i=t.exports={default:r,BigInteger:r,SecureRandom:ni}}).call(this)},function(t,i,r){"use strict";function e(t,i){for(var r=[],e=~~(i/8),n=i%8,o=0,s=t.length;o>>8-n&255);return r}function n(t,i){for(var r=[],e=t.length-1;e>=0;e--)r[e]=255&(t[e]^i[e]);return r}function o(t,i){for(var r=[],e=t.length-1;e>=0;e--)r[e]=t[e]&i[e]&255;return r}function s(t,i){for(var r=[],e=t.length-1;e>=0;e--)r[e]=255&(t[e]|i[e]);return r}function u(t,i){for(var r=[],e=0,n=t.length-1;n>=0;n--){var o=t[n]+i[n]+e;o>255?(e=1,r[n]=255&o):(e=0,r[n]=255&o)}return r}function h(t){for(var i=[],r=t.length-1;r>=0;r--)i[r]=255&~t[r];return i}function a(t){return n(n(t,e(t,9)),e(t,17))}function f(t){return n(n(t,e(t,15)),e(t,23))}function l(t,i,r,e){return e>=0&&e<=15?n(n(t,i),r):s(s(o(t,i),o(t,r)),o(i,r))}function c(t,i,r,e){return e>=0&&e<=15?n(n(t,i),r):s(o(t,i),o(h(t),r))}function p(t,i){for(var r=[],o=[],s=0;s<16;s++){var h=4*s;r.push(i.slice(h,h+4))}for(var p=16;p<68;p++)r.push(n(n(f(n(n(r[p-16],r[p-9]),e(r[p-3],15))),e(r[p-13],7)),r[p-6]));for(var v=0;v<64;v++)o.push(n(r[v],r[v+4]));for(var y=[121,204,69,25],m=[122,135,157,138],g=t.slice(0,4),d=t.slice(4,8),T=t.slice(8,12),F=t.slice(12,16),b=t.slice(16,20),B=t.slice(20,24),w=t.slice(24,28),x=t.slice(28,32),D=void 0,S=void 0,I=void 0,E=void 0,q=0;q<64;q++){var O=q>=0&&q<=15?y:m;D=e(u(u(e(g,12),b),e(O,q)),7),S=n(D,e(g,12)),I=u(u(u(l(g,d,T,q),F),S),o[q]),E=u(u(u(c(b,B,w,q),x),D),r[q]),F=T,T=e(d,9),d=g,g=I,x=w,w=e(B,19),B=b,b=a(E)}return n([].concat(g,d,T,F,b,B,w,x),t)}t.exports=function(t){var i=8*t.length,r=i%512;r=r>=448?512-r%448-1:448-r-1;for(var e=new Array((r-7)/8),n=0,o=e.length;n=0;u--)if(i.length>8){var h=i.length-8;s[u]=parseInt(i.substr(h),2),i=i.substr(0,h)}else i.length>0?(s[u]=parseInt(i,2),i=""):s[u]=0;for(var a=[].concat(t,[128],e,s),f=a.length/64,l=[115,128,22,111,73,20,178,185,23,36,66,215,218,138,6,0,169,111,48,188,22,49,56,170,227,141,238,77,176,251,14,78],c=0;c2&&void 0!==arguments[2]?arguments[2]:1;t=m.hexToArray(m.utf8ToHex(t)),i=m.getGlobalCurve().decodePointHex(i);var n=m.generateKeyPairHex(),o=new c(n.privateKey,16),s=n.publicKey;s.length>128&&(s=s.substr(s.length-128));var u=i.multiply(o),h=m.hexToArray(m.leftPad(u.getX().toBigInteger().toRadix(16),64)),a=m.hexToArray(m.leftPad(u.getY().toBigInteger().toRadix(16),64)),f=m.arrayToHex(g([].concat(h,t,a))),l=1,p=0,v=[],y=[].concat(h,a),d=function(){v=g([].concat(e(y),[l>>24&255,l>>16&255,l>>8&255,255&l])),l++,p=0};d();for(var T=0,F=t.length;T2&&void 0!==arguments[2]?arguments[2]:1;i=new c(i,16);var n=t.substr(128,64),o=t.substr(192);r===B&&(n=t.substr(t.length-64),o=t.substr(128,t.length-128-64));var s=m.hexToArray(o),u=m.getGlobalCurve().decodePointHex("04"+t.substr(0,128)),h=u.multiply(i),a=m.hexToArray(m.leftPad(h.getX().toBigInteger().toRadix(16),64)),f=m.hexToArray(m.leftPad(h.getY().toBigInteger().toRadix(16),64)),l=1,p=0,v=[],y=[].concat(a,f),d=function(){v=g([].concat(e(y),[l>>24&255,l>>16&255,l>>8&255,255&l])),l++,p=0};d();for(var T=0,F=s.length;T2&&void 0!==arguments[2]?arguments[2]:{},e=r.pointPool,n=r.der,o=r.hash,s=r.publicKey,u=r.userId,l="string"==typeof t?m.utf8ToHex(t):m.arrayToHex(t);o&&(s=s||a(i),l=h(l,s,u));var p=new c(i,16),y=new c(l,16),g=null,d=null,T=null;do{do{var F=void 0;F=e&&e.length?e.pop():f(),g=F.k,d=y.add(F.x1).mod(b)}while(d.equals(c.ZERO)||d.add(g).equals(b));T=p.add(c.ONE).modInverse(b).multiply(g.subtract(d.multiply(p))).mod(b)}while(T.equals(c.ZERO));return n?v(d,T):m.leftPad(d.toString(16),64)+m.leftPad(T.toString(16),64)}function u(t,i,r){var e=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},n=e.der,o=e.hash,s=e.userId,u="string"==typeof t?m.utf8ToHex(t):m.arrayToHex(t);o&&(u=h(u,r,s));var a=void 0,f=void 0;if(n){var l=y(i);a=l.r,f=l.s}else a=new c(i.substring(0,64),16),f=new c(i.substring(64),16);var p=F.decodePointHex(r),v=new c(u,16),g=a.add(f).mod(b);if(g.equals(c.ZERO))return!1;var d=T.multiply(f).add(p.multiply(g)),B=v.add(d.getX().toBigInteger()).mod(b);return a.equals(B)}function h(t,i){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"1234567812345678";r=m.utf8ToHex(r);var e=m.leftPad(T.curve.a.toBigInteger().toRadix(16),64),n=m.leftPad(T.curve.b.toBigInteger().toRadix(16),64),o=m.leftPad(T.getX().toBigInteger().toRadix(16),64),s=m.leftPad(T.getY().toBigInteger().toRadix(16),64);i.length>128&&(i=i.substr(2,128));var u=i.substr(0,64),h=i.substr(64,64),a=m.hexToArray(r+e+n+o+s+u+h),f=4*r.length;a.unshift(255&f),a.unshift(f>>8&255);var l=g(a);return m.arrayToHex(g(l.concat(m.hexToArray(t))))}function a(t){var i=T.multiply(new c(t,16));return"04"+m.leftPad(i.getX().toBigInteger().toString(16),64)+m.leftPad(i.getY().toBigInteger().toString(16),64)}function f(){var t=m.generateKeyPairHex(),i=F.decodePointHex(t.publicKey);return t.k=new c(t.privateKey,16),t.x1=i.getX().toBigInteger(),t}var l=r(0),c=l.BigInteger,p=r(3),v=p.encodeDer,y=p.decodeDer,m=r(4),g=r(1),d=m.generateEcparam(),T=d.G,F=d.curve,b=d.n,B=0;t.exports={generateKeyPairHex:m.generateKeyPairHex,doEncrypt:n,doDecrypt:o,doSignature:s,doVerifySignature:u,getPoint:f}},function(t,i,r){"use strict";function e(t,i){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!i||"object"!=typeof i&&"function"!=typeof i?t:i}function n(t,i){if("function"!=typeof i&&null!==i)throw new TypeError("Super expression must either be null or a function, not "+typeof i);t.prototype=Object.create(i&&i.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),i&&(Object.setPrototypeOf?Object.setPrototypeOf(t,i):t.__proto__=i)}function o(t,i){if(!(t instanceof i))throw new TypeError("Cannot call a class as a function")}function s(t){var i=t.toString(16);if("-"!==i[0])i.length%2==1?i="0"+i:i.match(/^[0-7]/)||(i="00"+i);else{i=i.substr(1);var r=i.length;r%2==1?r+=1:i.match(/^[0-7]/)||(r+=2);for(var e="",n=0;n>>2]|=(255&t.charCodeAt(e))<<24-e%4*8;for(var n=[],o=0;o>>2]>>>24-o%4*8&255;n.push((s>>>4).toString(16)),n.push((15&s).toString(16))}return n.join("")}function u(t,i){return t.length>=i?t:new Array(i-t.length+1).join("0")+t}function h(t){return t.map(function(t){return t=t.toString(16),1===t.length?"0"+t:t}).join("")}function a(t){for(var i=[],r=0,e=0;e<2*t.length;e+=2)i[e>>>3]|=parseInt(t[r],10)<<24-e%8*4,r++;try{for(var n=[],o=0;o>>2]>>>24-o%4*8&255;n.push(String.fromCharCode(s))}return decodeURIComponent(escape(n.join("")))}catch(t){throw new Error("Malformed UTF-8 data")}}function f(t){var i=[],r=t.length;r%2!=0&&(t=u(t,r+1)),r=t.length;for(var e=0;e0;n--){e=e.twice();var o=i.testBit(n);o!==t.testBit(n)&&(e=e.add(o?this:r))}return e}}]),t}(),f=function(){function t(i,r,n){e(this,t),this.q=i,this.a=this.fromBigInteger(r),this.b=this.fromBigInteger(n),this.infinity=new a(this,null,null)}return n(t,[{key:"equals",value:function(t){return t===this||this.q.equals(t.q)&&this.a.equals(t.a)&&this.b.equals(t.b)}},{key:"fromBigInteger",value:function(t){return new h(this.q,t)}},{key:"decodePointHex",value:function(t){switch(parseInt(t.substr(0,2),16)){case 0:return this.infinity;case 2:case 3:return null;case 4:case 6:case 7:var i=(t.length-2)/2,r=t.substr(2,i),e=t.substr(i+2,i);return new a(this,this.fromBigInteger(new s(r,16)),this.fromBigInteger(new s(e,16)));default:return null}}}]),t}();t.exports={ECPointFp:a,ECCurveFp:f}}]); 2 | 3 | /** 4 | * 生成密钥对:publicKey = privateKey * G 5 | */ 6 | generateKeyPairHex = function () { 7 | return sm2.generateKeyPairHex() 8 | } 9 | 10 | /** 11 | * 加密 12 | */ 13 | doEncrypt = function (msg, publicKey, cipherMode) { 14 | return sm2.doEncrypt(msg, publicKey, cipherMode) 15 | } 16 | 17 | /** 18 | * 解密 19 | */ 20 | doDecrypt = function (encryptData, privateKey, cipherMode) { 21 | return sm2.doDecrypt(encryptData, privateKey, cipherMode) 22 | } 23 | 24 | /** 25 | * 签名 26 | */ 27 | doSignature = function (msg, privateKey, signatureOptions) { 28 | return sm2.doSignature(msg, privateKey, signatureOptions) 29 | } 30 | 31 | /** 32 | * 验签 33 | */ 34 | doVerifySignature = function (msg, signHex, publicKey, signature) { 35 | return sm2.doVerifySignature(msg, signHex, publicKey, signature) 36 | } 37 | 38 | /** 39 | * 获取椭圆曲线点 40 | */ 41 | getPoint = function () { 42 | return sm2.getPoint() 43 | } 44 | -------------------------------------------------------------------------------- /src/main/resources/sm3.js: -------------------------------------------------------------------------------- 1 | sm3=function(r){function n(e){if(t[e])return t[e].exports;var o=t[e]={i:e,l:!1,exports:{}};return r[e].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var t={};return n.m=r,n.c=t,n.d=function(r,t,e){n.o(r,t)||Object.defineProperty(r,t,{configurable:!1,enumerable:!0,get:e})},n.n=function(r){var t=r&&r.__esModule?function(){return r.default}:function(){return r};return n.d(t,"a",t),t},n.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},n.p="",n(n.s=6)}({1:function(r,n,t){"use strict";function e(r,n){for(var t=[],e=~~(n/8),o=n%8,u=0,i=r.length;u>>8-o&255);return t}function o(r,n){for(var t=[],e=r.length-1;e>=0;e--)t[e]=255&(r[e]^n[e]);return t}function u(r,n){for(var t=[],e=r.length-1;e>=0;e--)t[e]=r[e]&n[e]&255;return t}function i(r,n){for(var t=[],e=r.length-1;e>=0;e--)t[e]=255&(r[e]|n[e]);return t}function s(r,n){for(var t=[],e=0,o=r.length-1;o>=0;o--){var u=r[o]+n[o]+e;u>255?(e=1,t[o]=255&u):(e=0,t[o]=255&u)}return t}function c(r){for(var n=[],t=r.length-1;t>=0;t--)n[t]=255&~r[t];return n}function f(r){return o(o(r,e(r,9)),e(r,17))}function a(r){return o(o(r,e(r,15)),e(r,23))}function l(r,n,t,e){return e>=0&&e<=15?o(o(r,n),t):i(i(u(r,n),u(r,t)),u(n,t))}function p(r,n,t,e){return e>=0&&e<=15?o(o(r,n),t):i(u(r,n),u(c(r),t))}function h(r,n){for(var t=[],u=[],i=0;i<16;i++){var c=4*i;t.push(n.slice(c,c+4))}for(var h=16;h<68;h++)t.push(o(o(a(o(o(t[h-16],t[h-9]),e(t[h-3],15))),e(t[h-13],7)),t[h-6]));for(var v=0;v<64;v++)u.push(o(t[v],t[v+4]));for(var g=[121,204,69,25],d=[122,135,157,138],x=r.slice(0,4),y=r.slice(4,8),b=r.slice(8,12),w=r.slice(12,16),m=r.slice(16,20),j=r.slice(20,24),A=r.slice(24,28),O=r.slice(28,32),P=void 0,I=void 0,S=void 0,_=void 0,E=0;E<64;E++){var M=E>=0&&E<=15?g:d;P=e(s(s(e(x,12),m),e(M,E)),7),I=o(P,e(x,12)),S=s(s(s(l(x,y,b,E),w),I),u[E]),_=s(s(s(p(m,j,A,E),O),P),t[E]),w=b,b=e(y,9),y=x,x=S,O=A,A=e(j,19),j=m,m=f(_)}return o([].concat(x,y,b,w,m,j,A,O),r)}r.exports=function(r){var n=8*r.length,t=n%512;t=t>=448?512-t%448-1:448-t-1;for(var e=new Array((t-7)/8),o=0,u=e.length;o=0;s--)if(n.length>8){var c=n.length-8;i[s]=parseInt(n.substr(c),2),n=n.substr(0,c)}else n.length>0?(i[s]=parseInt(n,2),n=""):i[s]=0;for(var f=[].concat(r,[128],e,i),a=f.length/64,l=[115,128,22,111,73,20,178,185,23,36,66,215,218,138,6,0,169,111,48,188,22,49,56,170,227,141,238,77,176,251,14,78],p=0;p>>6),n.push(128|63&o);else if(o<=55295||o>=57344&&o<=65535)n.push(224|o>>>12),n.push(128|o>>>6&63),n.push(128|63&o);else{if(!(o>=65536&&o<=1114111))throw n.push(o),new Error("input is not supported");t++,n.push(240|o>>>18&28),n.push(128|o>>>12&63),n.push(128|o>>>6&63),n.push(128|63&o)}}return n}var u=t(1);r.exports=function(r){return r="string"==typeof r?o(r):Array.prototype.slice.call(r),e(u(r))}}}); 2 | 3 | /** 4 | * 杂凑 5 | */ 6 | constructSm3 = function (msg) { 7 | return sm3(msg) 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/sm4.js: -------------------------------------------------------------------------------- 1 | sm4=function(r){function n(o){if(t[o])return t[o].exports;var e=t[o]={i:o,l:!1,exports:{}};return r[o].call(e.exports,e,e.exports,n),e.l=!0,e.exports}var t={};return n.m=r,n.c=t,n.d=function(r,t,o){n.o(r,t)||Object.defineProperty(r,t,{configurable:!1,enumerable:!0,get:o})},n.n=function(r){var t=r&&r.__esModule?function(){return r.default}:function(){return r};return n.d(t,"a",t),t},n.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},n.p="",n(n.s=7)}({7:function(r,n,t){"use strict";function o(r){if(Array.isArray(r)){for(var n=0,t=Array(r.length);n>>6),n.push(128|63&e);else if(e<=55295||e>=57344&&e<=65535)n.push(224|e>>>12),n.push(128|e>>>6&63),n.push(128|63&e);else{if(!(e>=65536&&e<=1114111))throw n.push(e),new Error("input is not supported");t++,n.push(240|e>>>18&28),n.push(128|e>>>12&63),n.push(128|e>>>6&63),n.push(128|63&e)}}return n}function f(r){for(var n=[],t=0,o=r.length;t=240&&r[t]<=247?(n.push(fromCodePoint(((7&r[t])<<18)+((63&r[t+1])<<12)+((63&r[t+2])<<6)+(63&r[t+3]))),t+=3):r[t]>=224&&r[t]<=239?(n.push(fromCodePoint(((15&r[t])<<12)+((63&r[t+1])<<6)+(63&r[t+2]))),t+=2):r[t]>=192&&r[t]<=223?(n.push(fromCodePoint(((31&r[t])<<6)+(63&r[t+1]))),t++):n.push(fromCodePoint(r[t]));return n.join("")}function s(r,n){return r<>>32-n}function a(r){return(255&w[r>>>24&255])<<24|(255&w[r>>>16&255])<<16|(255&w[r>>>8&255])<<8|255&w[255&r]}function c(r){return r^s(r,2)^s(r,10)^s(r,18)^s(r,24)}function p(r){return r^s(r,13)^s(r,23)}function h(r,n,t){for(var o=new Array(4),e=new Array(4),i=0;i<4;i++)e[0]=255&r[4*i],e[1]=255&r[4*i+1],e[2]=255&r[4*i+2],e[3]=255&r[4*i+3],o[i]=e[0]<<24|e[1]<<16|e[2]<<8|e[3];for(var u,f=0;f<32;f+=4)u=o[1]^o[2]^o[3]^t[f+0],o[0]^=c(a(u)),u=o[2]^o[3]^o[0]^t[f+1],o[1]^=c(a(u)),u=o[3]^o[0]^o[1]^t[f+2],o[2]^=c(a(u)),u=o[0]^o[1]^o[2]^t[f+3],o[3]^=c(a(u));for(var s=0;s<16;s+=4)n[s]=o[3-s/4]>>>24&255,n[s+1]=o[3-s/4]>>>16&255,n[s+2]=o[3-s/4]>>>8&255,n[s+3]=255&o[3-s/4]}function v(r,n,t){for(var o=new Array(4),e=new Array(4),i=0;i<4;i++)e[0]=255&r[0+4*i],e[1]=255&r[1+4*i],e[2]=255&r[2+4*i],e[3]=255&r[3+4*i],o[i]=e[0]<<24|e[1]<<16|e[2]<<8|e[3];o[0]^=2746333894,o[1]^=1453994832,o[2]^=1736282519,o[3]^=2993693404;for(var u,f=0;f<32;f+=4)u=o[1]^o[2]^o[3]^A[f+0],n[f+0]=o[0]^=p(a(u)),u=o[2]^o[3]^o[0]^A[f+1],n[f+1]=o[1]^=p(a(u)),u=o[3]^o[0]^o[1]^A[f+2],n[f+2]=o[2]^=p(a(u)),u=o[0]^o[1]^o[2]^A[f+3],n[f+3]=o[3]^=p(a(u));if(t===g)for(var s,c=0;c<16;c++)s=n[c],n[c]=n[31-c],n[31-c]=s}function l(r,n,t){var s=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},a=s.padding,c=void 0===a?"pkcs#5":a,p=s.mode,l=s.iv,w=void 0===l?[]:l,A=s.output,m=void 0===A?"string":A;if("cbc"===p&&("string"==typeof w&&(w=e(w)),16!==w.length))throw new Error("iv is invalid");if("string"==typeof n&&(n=e(n)),16!==n.length)throw new Error("key is invalid");if(r="string"==typeof r?t!==g?u(r):e(r):[].concat(o(r)),"pkcs#5"===c&&t!==g)for(var b=y-r.length%y,P=0;P=y;){var E=r.slice(C,C+16),O=new Array(16);if("cbc"===p)for(var _=0;_ 0x10FFFF || floor(codePoint) != codePoint) {throw RangeError('Invalid code point: ' + codePoint);}if (codePoint <= 0xFFFF) {codeUnits.push(codePoint);} else {codePoint -= 0x10000;highSurrogate = (codePoint >> 10) + 0xD800;lowSurrogate = (codePoint % 0x400) + 0xDC00;codeUnits.push(highSurrogate, lowSurrogate);}if (index + 1 == length || codeUnits.length > MAX_SIZE) {result += stringFromCharCode.apply(null, codeUnits);codeUnits.length = 0;}}return result;} 3 | 4 | /** 5 | * 加密 6 | */ 7 | encrypt = function (msg, key, options) { 8 | return sm4.encrypt(msg, key, 1, options) 9 | } 10 | 11 | /** 12 | * 解密 13 | */ 14 | decrypt = function (encryptData, key, options) { 15 | return sm4.decrypt(encryptData, key, 0, options) 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/antherd/smcrypto/Sm2Test.java: -------------------------------------------------------------------------------- 1 | package com.antherd.smcrypto; 2 | 3 | import com.antherd.smcrypto.sm2.Keypair; 4 | import com.antherd.smcrypto.sm2.Point; 5 | import com.antherd.smcrypto.sm2.SignatureOptions; 6 | import com.antherd.smcrypto.sm2.Sm2; 7 | import org.junit.Test; 8 | 9 | import javax.script.ScriptException; 10 | import java.util.*; 11 | 12 | public class Sm2Test { 13 | 14 | @Test 15 | public void test() throws ScriptException { 16 | 17 | /** 18 | * 生成密钥对 19 | */ 20 | Keypair keypair = Sm2.generateKeyPairHex(); 21 | String privateKey = keypair.getPrivateKey(); // 公钥 22 | String publicKey = keypair.getPublicKey(); // 私钥 23 | System.out.println("privateKey: " + privateKey); 24 | System.out.println("publicKey: " + publicKey); 25 | 26 | /** 27 | * 加密解密 28 | */ 29 | String msg = "这是需要加密的文字!!!"; 30 | System.out.println("msg: " + msg); 31 | String encryptData = Sm2.doEncrypt(msg, publicKey); // 加密结果 32 | String decryptData = Sm2.doDecrypt(encryptData, privateKey); // 解密结果 33 | System.out.println("encryptData: " + encryptData); 34 | System.out.println("decryptData: " + decryptData); 35 | 36 | // 签名验签 ps:理论上来说,只做纯签名是最快的。 37 | /** 38 | * 纯签名 + 生成椭圆曲线点 39 | */ 40 | long startTime = System.currentTimeMillis(); 41 | String sigValueHex = Sm2.doSignature(msg, privateKey); // 签名 42 | System.out.println("[纯签名 + 生成椭圆曲线点] 耗时: " + (System.currentTimeMillis() - startTime)); 43 | boolean verifyResult = Sm2.doVerifySignature(msg, sigValueHex, publicKey); // 验签结果 44 | System.out.println("sigValueHex: " + sigValueHex); 45 | System.out.println("verifyResult: " + verifyResult); 46 | 47 | /** 48 | * 纯签名 49 | */ 50 | Queue pointPool = new LinkedList(Arrays.asList(Sm2.getPoint(), Sm2.getPoint(), Sm2.getPoint(), Sm2.getPoint())); 51 | SignatureOptions signatureOptions2 = new SignatureOptions(); 52 | signatureOptions2.setPointPool(pointPool); // 传入事先已生成好的椭圆曲线点,可加快签名速度 53 | long startTime2 = System.currentTimeMillis(); 54 | String sigValueHex2 = Sm2.doSignature(msg, privateKey, signatureOptions2); 55 | System.out.println("[纯签名] 耗时: " + (System.currentTimeMillis() - startTime2)); 56 | boolean verifyResult2 = Sm2.doVerifySignature(msg, sigValueHex2, publicKey); // 验签结果 57 | System.out.println("sigValueHex2: " + sigValueHex2); 58 | System.out.println("verifyResult2: " + verifyResult2); 59 | 60 | /** 61 | * 纯签名 + 生成椭圆曲线点 + der编解码 62 | */ 63 | SignatureOptions signatureOptions3 = new SignatureOptions(); 64 | signatureOptions3.setDer(true); 65 | long startTime3 = System.currentTimeMillis(); 66 | String sigValueHex3 = Sm2.doSignature(msg, privateKey, signatureOptions3); // 签名 67 | System.out.println("[纯签名 + 生成椭圆曲线点 + der编解码] 耗时: " + (System.currentTimeMillis() - startTime3)); 68 | boolean verifyResult3 = Sm2.doVerifySignature(msg, sigValueHex3, publicKey, signatureOptions3); // 验签结果 69 | System.out.println("sigValueHex3: " + sigValueHex3); 70 | System.out.println("verifyResult3: " + verifyResult3); 71 | 72 | /** 73 | * 纯签名 + 生成椭圆曲线点 + sm3杂凑 74 | */ 75 | SignatureOptions signatureOptions4 = new SignatureOptions(); 76 | signatureOptions4.setHash(true); 77 | long startTime4 = System.currentTimeMillis(); 78 | String sigValueHex4 = Sm2.doSignature(msg, privateKey, signatureOptions4); // 签名 79 | System.out.println("[纯签名 + 生成椭圆曲线点 + sm3杂凑] 耗时: " + (System.currentTimeMillis() - startTime4)); 80 | boolean verifyResult4 = Sm2.doVerifySignature(msg, sigValueHex4, publicKey, signatureOptions4); // 验签结果 81 | System.out.println("sigValueHex4: " + sigValueHex4); 82 | System.out.println("verifyResult4: " + verifyResult4); 83 | 84 | /** 85 | * 纯签名 + 生成椭圆曲线点 + sm3杂凑(不做公钥推导) 86 | */ 87 | SignatureOptions signatureOptions5 = new SignatureOptions(); 88 | signatureOptions5.setHash(true); 89 | signatureOptions5.setPublicKey(publicKey); // 传入公钥的话,可以去掉sm3杂凑中推导公钥的过程,速度会比纯签名 + 生成椭圆曲线点 + sm3杂凑快 90 | long startTime5 = System.currentTimeMillis(); 91 | String sigValueHex5 = Sm2.doSignature(msg, privateKey, signatureOptions5); // 签名 92 | System.out.println("[纯签名 + 生成椭圆曲线点 + sm3杂凑(不做公钥推导)] 耗时: " + (System.currentTimeMillis() - startTime5)); 93 | boolean verifyResult5 = Sm2.doVerifySignature(msg, sigValueHex5, publicKey, signatureOptions5); // 验签结果 94 | System.out.println("sigValueHex5: " + sigValueHex5); 95 | System.out.println("verifyResult5: " + verifyResult5); 96 | 97 | /** 98 | * 纯签名 + 生成椭圆曲线点 + sm3杂凑 + 不做公钥推 + 添加 userId(长度小于 8192) 99 | * 默认 userId 值为 1234567812345678 100 | */ 101 | SignatureOptions signatureOptions6 = new SignatureOptions(); 102 | signatureOptions6.setHash(true); 103 | signatureOptions6.setPublicKey(publicKey); 104 | signatureOptions6.setUserId("testUserId"); 105 | long startTime6 = System.currentTimeMillis(); 106 | String sigValueHex6 = Sm2.doSignature(msg, privateKey, signatureOptions6); // 签名 107 | System.out.println("[纯签名 + 生成椭圆曲线点 + sm3杂凑 + 不做公钥推 + 添加 userId(长度小于 8192)] 耗时: " + (System.currentTimeMillis() - startTime6)); 108 | boolean verifyResult6 = Sm2.doVerifySignature(msg, sigValueHex6, publicKey, signatureOptions6); // 验签结果 109 | System.out.println("sigValueHex6: " + sigValueHex6); 110 | System.out.println("verifyResult6: " + verifyResult6); 111 | 112 | /** 113 | * 获取椭圆曲线点 114 | */ 115 | Point point = Sm2.getPoint(); // 获取一个椭圆曲线点,可在sm2签名时传入 116 | System.out.println("point: " + point); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/test/java/com/antherd/smcrypto/Sm3Test.java: -------------------------------------------------------------------------------- 1 | package com.antherd.smcrypto; 2 | 3 | import com.antherd.smcrypto.sm3.Sm3; 4 | import org.junit.Test; 5 | 6 | import javax.script.ScriptException; 7 | 8 | public class Sm3Test { 9 | 10 | @Test 11 | public void test() throws ScriptException { 12 | 13 | /** 14 | * 杂凑 15 | */ 16 | String hashData = Sm3.sm3("abc"); // 杂凑 17 | System.out.println("hashData: " + hashData); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/com/antherd/smcrypto/Sm4Test.java: -------------------------------------------------------------------------------- 1 | package com.antherd.smcrypto; 2 | 3 | import com.antherd.smcrypto.sm4.Sm4; 4 | import com.antherd.smcrypto.sm4.Sm4Options; 5 | import org.junit.Test; 6 | 7 | import javax.script.ScriptException; 8 | 9 | public class Sm4Test { 10 | 11 | @Test 12 | public void test() throws ScriptException { 13 | 14 | /** 15 | * 加密 16 | */ 17 | String msg = "hello world! 我是 antherd."; 18 | String key = "0123456789abcdeffedcba9876543210"; // 16 进制字符串,要求为 128 比特 19 | 20 | String encryptData1 = Sm4.encrypt(msg, key); // 加密,默认使用 pkcs#5 填充,输出16进制字符串 21 | System.out.println("encryptData1: " + encryptData1); 22 | 23 | Sm4Options sm4Options2 = new Sm4Options(); 24 | sm4Options2.setPadding("none"); 25 | String encryptData2 = Sm4.encrypt(msg, key, sm4Options2); // 加密,不使用 padding,输出16进制字符串 26 | System.out.println("encryptData2: " + encryptData2); 27 | 28 | Sm4Options sm4Options3 = new Sm4Options(); 29 | sm4Options3.setPadding("none"); 30 | byte[] encryptData3 = Sm4.hexToBytes(Sm4.encrypt(msg, key, sm4Options3)); // 加密,不使用 padding,输出转为字节数组 31 | System.out.println("encryptData3: " + Sm4.bytesToHex(encryptData3)); // 字节数组转为16进制字符串 32 | 33 | Sm4Options sm4Options4 = new Sm4Options(); 34 | sm4Options4.setMode("cbc"); 35 | sm4Options4.setIv("fedcba98765432100123456789abcdef"); 36 | String encryptData4 = Sm4.encrypt(msg, key, sm4Options4); // 加密,cbc 模式,输出16进制字符串 37 | System.out.println("encryptData4: " + encryptData4); 38 | 39 | /** 40 | * 解密 41 | */ 42 | String encryptData = "0e395deb10f6e8a17e17823e1fd9bd98a1bff1df508b5b8a1efb79ec633d1bb129432ac1b74972dbe97bab04f024e89c"; // 加密后的 16 进制字符串 43 | 44 | String decryptData5 = Sm4.decrypt(encryptData, key); // 解密,默认使用 pkcs#5 填充,输出 utf8 字符串 45 | System.out.println("decryptData5:" + decryptData5); 46 | 47 | Sm4Options sm4Options6 = new Sm4Options(); 48 | sm4Options2.setPadding("none"); 49 | String decryptData6 = Sm4.decrypt(encryptData, key, sm4Options6); // 解密,不使用 padding,输出 utf8 字符串 50 | System.out.println("decryptData6:" + decryptData6); 51 | 52 | Sm4Options sm4Options7 = new Sm4Options(); 53 | sm4Options2.setPadding("none"); 54 | byte[] decryptData7 = Sm4.utf8ToArray(Sm4.decrypt(encryptData, key, sm4Options7)); // 解密,不使用 padding,输出转为字节数组 55 | System.out.println("decryptData7:" + Sm4.arrayToUtf8(decryptData7)); 56 | 57 | Sm4Options sm4Options8 = new Sm4Options(); 58 | sm4Options4.setMode("cbc"); 59 | sm4Options4.setIv("fedcba98765432100123456789abcdef"); 60 | String decryptData8 = Sm4.decrypt(encryptData, key, sm4Options8); // 解密,cbc 模式,输出 utf8 字符串 61 | System.out.println("encryptData8: " + decryptData8); 62 | } 63 | } 64 | --------------------------------------------------------------------------------