├── .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 |
--------------------------------------------------------------------------------