diff --git a/pom.xml b/pom.xml index 277212e..c74d927 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,5 @@ - 4.0.0 @@ -26,11 +26,7 @@ org.springframework.boot spring-boot-starter - + org.springframework.boot spring-boot-starter-web @@ -39,6 +35,11 @@ org.springframework.boot spring-boot-starter-aop + + + org.springframework.boot + spring-boot-starter-thymeleaf + com.google.guava guava @@ -64,7 +65,11 @@ commons-codec 1.10 - + org.projectlombok lombok @@ -78,7 +83,7 @@ cn.hutool - hutool-core + hutool-all 4.0.3 @@ -86,46 +91,84 @@ org.springframework.boot spring-boot-starter-data-redis - + org.owasp.esapi esapi 2.2.0.0 + + + + dev + + true + + + dev + + + + + test + + test + + + + + prod + + prod + + + + ${project.artifactId}-${project.version}-${profiles.active} + + + src/main/resources + true + + + ${project.basedir}/profiles/${profiles.active} + + - - org.springframework.boot - spring-boot-maven-plugin - - - - org.springframework.boot.experimental - spring-boot-thin-layout - 1.0.12.RELEASE - - - - - - org.springframework.boot.experimental - spring-boot-thin-maven-plugin - 1.0.12.RELEASE - - - resolve - - resolve - - false - - - - + + org.springframework.boot + spring-boot-maven-plugin + + + + org.springframework.boot.experimental + spring-boot-thin-layout + 1.0.12.RELEASE + + + + + + org.springframework.boot.experimental + spring-boot-thin-maven-plugin + 1.0.12.RELEASE + + + resolve + + resolve + + false + + + diff --git a/profiles/dev/application-dev.properties b/profiles/dev/application-dev.properties new file mode 100644 index 0000000..e84d003 --- /dev/null +++ b/profiles/dev/application-dev.properties @@ -0,0 +1,5 @@ +server.port=9999 + + +logging.path=d://logs + diff --git a/profiles/prod/application-prod.properties b/profiles/prod/application-prod.properties new file mode 100644 index 0000000..92fa7a8 --- /dev/null +++ b/profiles/prod/application-prod.properties @@ -0,0 +1,2 @@ +server.port=8080 +logging.path=./logs \ No newline at end of file diff --git a/profiles/test/application-test.properties b/profiles/test/application-test.properties new file mode 100644 index 0000000..92fa7a8 --- /dev/null +++ b/profiles/test/application-test.properties @@ -0,0 +1,2 @@ +server.port=8080 +logging.path=./logs \ No newline at end of file diff --git a/src/main/java/com/taoyuanx/securitydemo/SecurityDemoApplication.java b/src/main/java/com/taoyuanx/securitydemo/SecurityDemoApplication.java index 67b80b3..e75dcd7 100644 --- a/src/main/java/com/taoyuanx/securitydemo/SecurityDemoApplication.java +++ b/src/main/java/com/taoyuanx/securitydemo/SecurityDemoApplication.java @@ -7,7 +7,7 @@ import org.springframework.context.annotation.ComponentScan; @SpringBootApplication @ServletComponentScan("com.taoyuanx.securitydemo.web") -class SecurityDemoApplication { +public class SecurityDemoApplication { public static void main(String[] args) { SpringApplication.run(SecurityDemoApplication.class, args); diff --git a/src/main/java/com/taoyuanx/securitydemo/config/GlobalConfig.java b/src/main/java/com/taoyuanx/securitydemo/config/GlobalConfig.java index 9aa8bf3..b8128fb 100644 --- a/src/main/java/com/taoyuanx/securitydemo/config/GlobalConfig.java +++ b/src/main/java/com/taoyuanx/securitydemo/config/GlobalConfig.java @@ -2,7 +2,10 @@ package com.taoyuanx.securitydemo.config; import com.taoyuanx.securitydemo.security.ratelimit.AbstractRateLimiter; import com.taoyuanx.securitydemo.security.ratelimit.RedisRateLimiter; +import com.taoyuanx.securitydemo.utils.RSAUtil; import lombok.Data; +import org.apache.commons.codec.binary.Base64; +import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -10,6 +13,10 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import org.springframework.data.redis.core.StringRedisTemplate; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.cert.Certificate; import java.util.List; /** @@ -20,7 +27,7 @@ import java.util.List; @Data @ConfigurationProperties("application.config") @Configuration -public class GlobalConfig { +public class GlobalConfig implements InitializingBean { @Autowired Environment environment; @@ -36,6 +43,15 @@ public class GlobalConfig { private String systemFileFormat; + private String rsaP12Path; + private String rsaP12Password; + + private PublicKey publicKey; + private PrivateKey privateKey; + private Certificate certificate; + + private String publickKeyBase64; + public String getConfig(String configKey) { return environment.getProperty(configKey); } @@ -54,4 +70,17 @@ public class GlobalConfig { } + @Override + public void afterPropertiesSet() throws Exception { + //证书初始化 + KeyStore keyStore = RSAUtil.getKeyStore(rsaP12Path, rsaP12Password); + publicKey = RSAUtil.getPublicKey(keyStore); + privateKey = RSAUtil.getPrivateKey(keyStore, rsaP12Password); + certificate = RSAUtil.getCertificate(keyStore); + publickKeyBase64 = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCejQE9rKg8v5TuaS9tODR9QNPg\n" + + "P9MDhtyIFmKLmQTu2an/pEW18XWXEKi04ORYfwr7BjAJ9HMWspGRg8rbSjbethud\n" + + "QnJUDtrqHNDYzJ1HhQT7sngGvpuH9ME7ZW4yZcMDS7/i5tQSps31JmGI+ULZg1cv\n" + + "G5A/SbSqiE5PXSfIhQIDAQAB"; + Base64.encodeBase64String(certificate.getEncoded()); + } } diff --git a/src/main/java/com/taoyuanx/securitydemo/controller/CryptController.java b/src/main/java/com/taoyuanx/securitydemo/controller/CryptController.java new file mode 100644 index 0000000..b622353 --- /dev/null +++ b/src/main/java/com/taoyuanx/securitydemo/controller/CryptController.java @@ -0,0 +1,88 @@ +package com.taoyuanx.securitydemo.controller; + +import cn.hutool.crypto.Mode; +import cn.hutool.crypto.Padding; +import cn.hutool.crypto.symmetric.AES; +import com.taoyuanx.securitydemo.common.Result; +import com.taoyuanx.securitydemo.common.ResultBuilder; +import com.taoyuanx.securitydemo.config.GlobalConfig; +import com.taoyuanx.securitydemo.exception.ServiceException; + +import com.taoyuanx.securitydemo.utils.*; +import com.taoyuanx.securitydemo.vo.EncryptForm; +import org.apache.commons.codec.binary.Hex; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.security.interfaces.RSAPrivateKey; +import java.util.Objects; + +/** + * @author dushitaoyuan + * @desc 加密控制器 + * @date 2020/1/15 + */ +@Controller +@RequestMapping("crypt") +public class CryptController { + @Autowired + GlobalConfig globalConfig; + + /** + * 服务端公钥获取 + */ + @GetMapping("serverPub") + @ResponseBody + public String serverPub() { + return globalConfig.getPublickKeyBase64(); + } + + /** + * 服务端公钥获取 + */ + @GetMapping("cryptPage") + public String cryptPage(Model model, HttpServletRequest request) { + model.addAttribute("serverPub", globalConfig.getPublickKeyBase64()); + String serverRandom = RandomCodeUtil.getRandCode(16); + request.getSession().setAttribute("serverRandom", serverRandom); + model.addAttribute("serverRandom", serverRandom); + String iv=RandomCodeUtil.getRandCode(16); + model.addAttribute("iv", iv); + request.getSession().setAttribute("iv", iv); + return "crypt"; + } + + /** + * 接受加密请求 + */ + @PostMapping("reciveEncrypt") + @ResponseBody + public Result reciveEncrypt(EncryptForm encryptForm, HttpServletRequest request) throws Exception { + Object serverRandom = request.getSession().getAttribute("serverRandom"); + if (!(Objects.nonNull(encryptForm.getServerRandom()) && encryptForm.getServerRandom().equals(serverRandom))) { + throw new ServiceException("非法请求"); + } + String dataHash = encryptForm.getDataHash(); + //解密aes对称密码 + String clientAesEncodePassword = RSAUtil.decryptByPrivateKey(encryptForm.getClientAesEncodePassword(), (RSAPrivateKey) globalConfig.getPrivateKey()); + byte[] clientAesIv = request.getSession().getAttribute("iv").toString().getBytes("UTF-8"); + String aesMode = "AES/CBC/PKCS5Padding"; + //解密数据 + String data = null; + try { + AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, clientAesEncodePassword.getBytes("UTF-8"), clientAesIv); + byte[] bytes = Hex.decodeHex(encryptForm.getEncodeData().toCharArray()); + data = new String(aes.decrypt(bytes), "UTF-8"); + } catch (Exception e) { + throw new ServiceException("解密失败"); + } + String hash = HashUtil.hash(data, HashUtil.SHA256, HashUtil.HEX); + if (!hash.equals(encryptForm.getDataHash())) { + throw new ServiceException("数据hash不匹配"); + } + return ResultBuilder.success("ok"); + } +} diff --git a/src/main/java/com/taoyuanx/securitydemo/exception/ServiceException.java b/src/main/java/com/taoyuanx/securitydemo/exception/ServiceException.java index d5554ee..813c468 100644 --- a/src/main/java/com/taoyuanx/securitydemo/exception/ServiceException.java +++ b/src/main/java/com/taoyuanx/securitydemo/exception/ServiceException.java @@ -18,7 +18,7 @@ public class ServiceException extends RuntimeException { this.errorCode=errorCode; } public Integer getErrorCode(){ - return getErrorCode(); + return errorCode; } diff --git a/src/main/java/com/taoyuanx/securitydemo/utils/HashUtil.java b/src/main/java/com/taoyuanx/securitydemo/utils/HashUtil.java new file mode 100644 index 0000000..3355673 --- /dev/null +++ b/src/main/java/com/taoyuanx/securitydemo/utils/HashUtil.java @@ -0,0 +1,135 @@ +package com.taoyuanx.securitydemo.utils; + +/** + * @author 都市桃源 + * 数据摘要工具类 + */ + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.codec.digest.DigestUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; + +public class HashUtil { + //hash字符类型 base64 和hex + public static final String HEX = "hex"; + public static final String BASE64 = "base64"; + + //hash算法类型 md5,sha256,sha1 + public static final String MD5 = "md5"; + public static final String SHA256 = "sha256"; + public static final String SHA1 = "sha1"; + + public static byte[] hash(String content, String hashType) throws Exception { + if (null == content || "".equals(content)) { + throw new Exception("hash 内容为空"); + } + return doHash(content.getBytes(), hashType); + } + + + public static byte[] hash(byte[] content, String hashType) throws Exception { + if (null == content || "".equals(content)) { + throw new Exception("hash 内容为空"); + } + return doHash(content, hashType); + } + + + /** + * @param content hash内容 + * @param hashType hash类型 + * @param stringType 编码类型 base64 和 hex + * @return + * @throws Exception + */ + public static String hash(String content, String hashType, String stringType) throws Exception { + if (null == content || "".equals(content)) { + throw new Exception("hash 内容为空"); + } + return bytes2Str(doHash(content.getBytes(), hashType), stringType); + } + + public static String hash(byte[] content, String hashType, String stringType) throws Exception { + if (null == content || content.length == 0) { + throw new Exception("hash 内容为空"); + } + + return bytes2Str(doHash(content, hashType), stringType); + } + + + public static String hash(InputStream content, String hashType, String stringType) throws Exception { + if (null == content) { + throw new Exception("hash 内容为空"); + } + + return bytes2Str(doHash(content, hashType), stringType); + } + + private static String bytes2Str(byte[] bytes, String stringType) { + switch (stringType) { + case HEX: + return Hex.encodeHexString(bytes); + case BASE64: + return Base64.encodeBase64String(bytes); + default: + return Base64.encodeBase64String(bytes); + } + } + + public static String bytesToAscllString(byte[] bytes) { + StringBuilder buf = new StringBuilder(); + for (byte b : bytes) { + buf.append((char) b); + } + return buf.toString(); + } + + private static byte[] doHash(byte[] content, String hashType) { + switch (hashType) { + case MD5: + return DigestUtils.getMd5Digest().digest(content); + case SHA256: + return DigestUtils.getSha256Digest().digest(content); + case SHA1: + return DigestUtils.getSha1Digest().digest(content); + default: + return DigestUtils.getMd5Digest().digest(content); + } + } + + private static byte[] doHash(InputStream content, String hashType) throws IOException { + byte[] buffer = new byte[1024 * 1024 * 4]; + MessageDigest digest = null; + switch (hashType) { + case MD5: + digest = DigestUtils.getMd5Digest(); + break; + case SHA256: + digest = DigestUtils.getSha256Digest(); + break; + case SHA1: + digest = DigestUtils.getSha1Digest(); + break; + default: + digest = DigestUtils.getMd5Digest(); + break; + } + int len = -1; + while ((len = content.read(buffer, 0, 1024)) != -1) { + digest.update(buffer, 0, len); + } + content.close(); + return digest.digest(); + } + + public static void main(String[] args) throws Exception { + System.out.println(hash("1", MD5, HEX)); + } + + +} diff --git a/src/main/java/com/taoyuanx/securitydemo/utils/HelperUtil.java b/src/main/java/com/taoyuanx/securitydemo/utils/HelperUtil.java new file mode 100644 index 0000000..95f59a7 --- /dev/null +++ b/src/main/java/com/taoyuanx/securitydemo/utils/HelperUtil.java @@ -0,0 +1,70 @@ +package com.taoyuanx.securitydemo.utils; + + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; + +/** + * @author dushitaoyuan + * @date 2019/1/7 18:34 + * @desc 帮助类 + **/ +public class HelperUtil { + private static final String CLASSPATH_PREFIX = "classpath:"; + + public static boolean isEmpty(String str) { + return str == null || str.isEmpty(); + } + + public static String getExtension(String fileName) { + return fileName.substring(fileName.lastIndexOf(".")+1).toLowerCase(); + } + + public static InputStream getInputStream(String filePath) throws FileNotFoundException { + if (filePath.startsWith(CLASSPATH_PREFIX)) { + return HelperUtil.class.getResourceAsStream(filePath.replaceFirst(CLASSPATH_PREFIX, "")); + } else { + return new FileInputStream(filePath); + } + } + + public static byte[] subarray(byte[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return null; + } + if (startIndexInclusive < 0) { + startIndexInclusive = 0; + } + if (endIndexExclusive > array.length) { + endIndexExclusive = array.length; + } + int newSize = endIndexExclusive - startIndexInclusive; + if (newSize <= 0) { + return new byte[0]; + } + + byte[] subarray = new byte[newSize]; + System.arraycopy(array, startIndexInclusive, subarray, 0, newSize); + return subarray; + } + + public static byte[] addAll(byte[] array1, byte... array2) { + if (array1 == null) { + return clone(array2); + } else if (array2 == null) { + return clone(array1); + } + byte[] joinedArray = new byte[array1.length + array2.length]; + System.arraycopy(array1, 0, joinedArray, 0, array1.length); + System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); + return joinedArray; + } + + public static byte[] clone(byte[] array) { + if (array == null) { + return null; + } + return array.clone(); + } +} diff --git a/src/main/java/com/taoyuanx/securitydemo/utils/RSAUtil.java b/src/main/java/com/taoyuanx/securitydemo/utils/RSAUtil.java new file mode 100644 index 0000000..4fc0b03 --- /dev/null +++ b/src/main/java/com/taoyuanx/securitydemo/utils/RSAUtil.java @@ -0,0 +1,278 @@ +package com.taoyuanx.securitydemo.utils; + +import org.apache.commons.codec.binary.Base64; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.CipherOutputStream; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.*; +import java.security.KeyStore; +import java.security.PublicKey; +import java.security.Signature; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.util.Enumeration; + +public final class RSAUtil { + + private static final Logger LOG = LoggerFactory.getLogger(RSAUtil.class); + public static final String KEYSTORE_TYPE_P12 = "PKCS12"; + public static final String KEYSTORE_TYPE_JKS = "JKS"; + public static final String ENCRYPT_TYPE_RSA = "RSA"; + public static final String DEFAILT_SIGN_ALGORITHM = "MD5withRSA"; + public static final String CERT_TYPE_X509 = "X.509"; + + public static KeyStore getKeyStore(String filePath, String keyPassword) throws Exception { + return getKeyStore(HelperUtil.getInputStream(filePath), keyPassword, guessKeyStoreType(filePath)); + } + + public static KeyStore getKeyStore(InputStream inputStream, String keyPassword, String keyStoreType) throws Exception { + KeyStore keyStore = KeyStore.getInstance(keyStoreType); + keyStore.load(inputStream, keyPassword.toCharArray()); + return keyStore; + } + + public static String guessKeyStoreType(String filePath) { + String ext = HelperUtil.getExtension(filePath); + if (ext.equals("p12") || ext.equals("pfx")) { + return KEYSTORE_TYPE_P12; + } + if (ext.equals("jks")) { + return KEYSTORE_TYPE_JKS; + } + return null; + } + + public static RSAPublicKey getPublicKey(KeyStore keyStore) throws Exception { + String key_aliases = null; + Enumeration enumeration = keyStore.aliases(); + if (enumeration.hasMoreElements()) { + key_aliases = enumeration.nextElement(); + RSAPublicKey publicKey = (RSAPublicKey) keyStore.getCertificate(key_aliases).getPublicKey(); + return publicKey; + } + return null; + } + + public static Certificate getCertificate(KeyStore keyStore) throws Exception { + String key_aliases = null; + Enumeration enumeration = keyStore.aliases(); + key_aliases = enumeration.nextElement(); + if (keyStore.isKeyEntry(key_aliases)) { + Certificate certificate = keyStore.getCertificate(key_aliases); + return certificate; + } + return null; + } + + public static RSAPrivateKey getPrivateKey(KeyStore keyStore, String keyPassword) throws Exception { + String key_aliases = null; + Enumeration enumeration = keyStore.aliases(); + key_aliases = enumeration.nextElement(); + if (keyStore.isKeyEntry(key_aliases)) { + RSAPrivateKey privateKey = (RSAPrivateKey) keyStore.getKey(key_aliases, keyPassword.toCharArray()); + return privateKey; + } + return null; + } + + + public static String encryptByPublicKey(String data, RSAPublicKey publicKey) throws Exception { + return Base64.encodeBase64URLSafeString(encryptByPublicKey(Base64.decodeBase64(data), publicKey)); + } + + public static byte[] encryptByPublicKey(byte[] data, RSAPublicKey publicKey) throws Exception { + if (null == publicKey) {// 如果公钥为空,采用系统公钥 + throw new Exception("rsa publicKey is null"); + } + Cipher cipher = Cipher.getInstance(ENCRYPT_TYPE_RSA); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + // 模长 + int key_len = publicKey.getModulus().bitLength() / 8; + // 加密数据长度 <= 模长-11,如果明文长度大于模长-11则要分组加密 + key_len -= 11; + byte[] dataReturn = null; + for (int i = 0; i < data.length; i += key_len) { + byte[] doFinal = cipher.doFinal(HelperUtil.subarray(data, i, i + key_len)); + dataReturn = HelperUtil.addAll(dataReturn, doFinal); + } + return dataReturn; + } + + + /** + * 私钥解密 + * + * @param data + * @param privateKey + * @return + * @throws Exception + */ + public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey) throws Exception { + return new String(decryptByPrivateKey(Base64.decodeBase64(data), privateKey)); + } + + + public static byte[] decryptByPrivateKey(byte[] data, RSAPrivateKey privateKey) throws Exception { + if (null == privateKey) { + throw new Exception("rsa privateKey is null"); + } + Cipher cipher = Cipher.getInstance(ENCRYPT_TYPE_RSA); + cipher.init(Cipher.DECRYPT_MODE, privateKey); + // 模长 + int key_len = privateKey.getModulus().bitLength() / 8; + // 分组解密 + ByteArrayOutputStream out = new ByteArrayOutputStream(data.length); + // 如果密文长度大于模长则要分组解密 + for (int i = 0; i < data.length; i += key_len) { + byte[] doFinal = cipher.doFinal(HelperUtil.subarray(data, i, i + key_len)); + out.write(doFinal, 0, doFinal.length); + } + return out.toByteArray(); + } + + + public static void encryptByPublicKey(InputStream data, RSAPublicKey publicKey, OutputStream encodeStream) throws Exception { + if (null == publicKey) { + throw new Exception("rsa publicKey is null"); + } + Cipher cipher = Cipher.getInstance(ENCRYPT_TYPE_RSA); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + CipherInputStream cipherInputStream = new CipherInputStream(data, cipher); + int buffSize = 4 << 20; + byte[] buf = new byte[buffSize]; + int len = 0; + while ((len = cipherInputStream.read(buf)) != -1) { + encodeStream.write(buf, 0, len); + } + cipherInputStream.close(); + + } + + public static void decryptByPrivateKey(InputStream data, RSAPrivateKey privateKey, OutputStream decodeStream) throws Exception { + if (null == privateKey) { + throw new Exception("rsa privateKey is null"); + } + Cipher cipher = Cipher.getInstance(ENCRYPT_TYPE_RSA); + cipher.init(Cipher.DECRYPT_MODE, privateKey); + CipherOutputStream cipherOutputStream = new CipherOutputStream(decodeStream, cipher); + int buffSize = 4 << 20; + byte[] buf = new byte[buffSize]; + int len = 0; + while ((len = data.read(buf)) != -1) { + cipherOutputStream.write(buf, 0, len); + } + cipherOutputStream.close(); + + } + + + /** + * 签名 + * + * @param data 签名内容 + * @param signAlgorithm 签名 + * @param privateKey 签名私钥 + * @return 签名值 + */ + public static byte[] sign(byte[] data, String signAlgorithm, RSAPrivateKey privateKey) throws Exception { + if (null == privateKey) { + throw new Exception("rsa privateKey is null"); + } + if (HelperUtil.isEmpty(signAlgorithm)) { + signAlgorithm = DEFAILT_SIGN_ALGORITHM; + } + Signature signture = Signature.getInstance(signAlgorithm); + signture.initSign(privateKey); + signture.update(data); + return signture.sign(); + } + + /** + * @param data 签名原文内容 + * @param sign 签名值 + * @param publicKey 验签公钥 + * @param signAlgorithm 签名算法 MD5withRSA,SHA1withRSA,SHA256withRSA + * @return + */ + public static boolean vefySign(byte[] data, byte[] sign, String signAlgorithm, PublicKey publicKey) { + try { + if (null == sign || sign.length == 0 || null == data || data.length == 0) { + return false; + } + if (null == publicKey) { + throw new Exception("rsa publicKey is null"); + } + if (HelperUtil.isEmpty(signAlgorithm)) { + signAlgorithm = DEFAILT_SIGN_ALGORITHM; + } + Signature signature = Signature.getInstance(signAlgorithm); + signature.initVerify(publicKey); + signature.update(data); + return signature.verify(sign); + } catch (Exception e) { + LOG.error("验签异常{}", e); + return false; + } + } + + + public static String sign(String data, String signAlgorithm, RSAPrivateKey privateKey) throws Exception { + return Base64.encodeBase64URLSafeString(sign(data.getBytes(), signAlgorithm, privateKey)); + } + + public static boolean vefySign(String data, String signvalue, X509Certificate cert) { + try { + if (HelperUtil.isEmpty(data) || HelperUtil.isEmpty(signvalue)) { + return false; + } + if (null == cert) { + throw new Exception("rsa X509Certificate is null"); + } + return vefySign(data.getBytes(), Base64.decodeBase64(signvalue), cert.getSigAlgName(), cert.getPublicKey()); + } catch (Exception e) { + LOG.error("验签异常{}", e); + return false; + } + } + + + public static X509Certificate readPublicKeyCer(InputStream publicInput) throws Exception { + CertificateFactory certificatefactory = CertificateFactory.getInstance(CERT_TYPE_X509); + X509Certificate cert = (X509Certificate) certificatefactory.generateCertificate(publicInput); + return cert; + } + + public static PublicKey readPublicKey(File fileInputStream) { + try { + return RSAUtil.readPublicKeyCer(new FileInputStream(fileInputStream)).getPublicKey(); + } catch (Exception e) { + throw new RuntimeException("读取公钥失败", e); + } + + } + + /** + * 读取pem格式公钥 + * + * @param certPemString pem字符串 + * @return + */ + public static PublicKey readPublicKeyPEM(String certPemString) { + try { + return RSAUtil.readPublicKeyCer(new ByteArrayInputStream(certPemString.getBytes("UTF-8"))).getPublicKey(); + } catch (Exception e) { + throw new RuntimeException("读取公钥失败", e); + } + + } + + +} diff --git a/src/main/java/com/taoyuanx/securitydemo/utils/RandomCodeUtil.java b/src/main/java/com/taoyuanx/securitydemo/utils/RandomCodeUtil.java new file mode 100644 index 0000000..afb0001 --- /dev/null +++ b/src/main/java/com/taoyuanx/securitydemo/utils/RandomCodeUtil.java @@ -0,0 +1,28 @@ +package com.taoyuanx.securitydemo.utils; + +import java.util.Random; + +/** + * @author dushitaoyuan + * @desc 随机码 + * @date 2020/1/3 + */ +public class RandomCodeUtil { + /** + * 随机生成字符 + * + * @return + */ + private static char[] rand_str = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; + + public static String getRandCode(int len) { + StringBuilder pwd = new StringBuilder(len); + Random r = new Random(); + for (int i = 0; i < len; i++) { + pwd.append(rand_str[r.nextInt(rand_str.length)]); + } + return pwd.toString(); + + } +} diff --git a/src/main/java/com/taoyuanx/securitydemo/vo/EncryptForm.java b/src/main/java/com/taoyuanx/securitydemo/vo/EncryptForm.java new file mode 100644 index 0000000..3c84d5c --- /dev/null +++ b/src/main/java/com/taoyuanx/securitydemo/vo/EncryptForm.java @@ -0,0 +1,21 @@ +package com.taoyuanx.securitydemo.vo; + +import lombok.Data; + +/** + * @author dushitaoyuan + * @desc 加密请求表单 + * @date 2020/1/15 + */ +@Data +public class EncryptForm { + //服务端随机数 + private String serverRandom; + //服务端公钥加密后的aes对称密钥 + private String clientAesEncodePassword; + //加密后的数据 + private String encodeData; + //数据hash + private String dataHash; + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 7cb8779..8adb1cd 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,4 +1,4 @@ -server.port=8080 + #数据库连接池 #spring.datasource.url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true #spring.datasource.username:root @@ -12,7 +12,7 @@ server.port=8080 #spring.datasource.timeBetweenEvictionRunsMillis=60000 #spring.datasource.filters=wall - +spring.profiles.active=@profiles.active@ spring.redis.database=2 spring.redis.host=192.168.30.211 @@ -40,5 +40,17 @@ application.config.file-storage-dir=G:/temp #系统文件访问地址,参见fileHandler application.config.systemFileFormat=http://localhost:${server.port}/api/file +#rsa p12 路径及密码 +application.config.rsaP12-path=d://client.p12 +application.config.rsaP12-password=123456 + +#thymeleaf \u6A21\u677F\u5F15\u64CE\u914D\u7F6E +spring.thymeleaf.enabled=true +spring.thymeleaf.encoding=UTF-8 +spring.thymeleaf.cache=false +spring.thymeleaf.suffix=.html logging.level.org.springframework=INFO + + +logging.path=./logs diff --git a/src/main/resources/certs/client.p12 b/src/main/resources/certs/client.p12 new file mode 100644 index 0000000..939fdad Binary files /dev/null and b/src/main/resources/certs/client.p12 differ diff --git a/src/main/resources/certs/client_cert.cer b/src/main/resources/certs/client_cert.cer new file mode 100644 index 0000000..9bc5285 --- /dev/null +++ b/src/main/resources/certs/client_cert.cer @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDizCCAnOgAwIBAgIGAW+nseYzMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQG +EwJDTjELMAkGA1UECAwCQkoxCzAJBgNVBAcMAkJKMRIwEAYDVQQKDAnmoYPmupDk +uaExEjAQBgNVBAsMCeahg+a6kOS5oTESMBAGA1UEAwwJ5qGD5rqQ5LmhMSMwIQYJ +KoZIhvcNAQkBFhRsaWFuZ2xlaV9senhAMTYzLmNvbTAgFw0yMDAxMTQxNjAwMDBa +GA8yMDU3MDExNDE2MDAwMFowfDELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkJKMQsw +CQYDVQQHDAJCSjEVMBMGA1UECgwMdGFveXVhbnguY29tMRUwEwYDVQQLDAx0YW95 +dWFueC5jb20xJTAjBgkqhkiG9w0BCQEWFmR1c2hpdGFveXVhbkBnbWFpbC5jb20w +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJ6NAT2sqDy/lO5pL204NH1A0+A/ +0wOG3IgWYouZBO7Zqf+kRbXxdZcQqLTg5Fh/CvsGMAn0cxaykZGDyttKNt62G51C +clQO2uoc0NjMnUeFBPuyeAa+m4f0wTtlbjJlwwNLv+Lm1BKmzfUmYYj5QtmDVy8b +kD9JtKqITk9dJ8iFAgMBAAGjgYcwgYQwHwYDVR0jBBgwFoAUh6OitnPZb0BV6swl +cLTxEcy+OkMwHQYDVR0OBBYEFFuy+UxzJzqVtodEp66TeZi20AOXMA8GA1UdDwEB +/wQFAwMH/4AwIAYDVR0lAQH/BBYwFAYIKwYBBQUHAwkGCCsGAQUFBwMSMA8GA1Ud +EwQIMAYBAf8CAQAwDQYJKoZIhvcNAQELBQADggEBAAAmbo7QgtCrbaGMUUbMWD2U +lbJiCxRFgoad4jkUQq/YrWYJZa0oMYWjRhKUuQKJ+KXz2HdMtwChi2RwzHzAdLda +2l3Pqg9U2XLoS4FxPRt4LwXQKDlIUYRwrBRH/beT5JUK5xcRRQR78uNT6luccL3T +hzUBYB1/rqREIpqHS1D1eV/DiFfhiFUn2GtcxV4vN+uOz2KvY0rh6li132wp9zZK +loLJfygKKNzPhiegAYu6M9+0q/CVXyNudr19BbbmP1SjNeA4WF/gjYB3ilrRDbDY +MMzDsKhkqOU42oYOdsjWuN9ZwZqAKys73EuD/DEMEqPfmRVpeGdy9GH/1IPZwto= +-----END CERTIFICATE----- diff --git a/src/main/resources/certs/client_pri.pem b/src/main/resources/certs/client_pri.pem new file mode 100644 index 0000000..4aa161a --- /dev/null +++ b/src/main/resources/certs/client_pri.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICWwIBAAKBgQCejQE9rKg8v5TuaS9tODR9QNPgP9MDhtyIFmKLmQTu2an/pEW1 +8XWXEKi04ORYfwr7BjAJ9HMWspGRg8rbSjbethudQnJUDtrqHNDYzJ1HhQT7sngG +vpuH9ME7ZW4yZcMDS7/i5tQSps31JmGI+ULZg1cvG5A/SbSqiE5PXSfIhQIDAQAB +An9e3vgwL07zTvQXXyYOnzlz7HR1A1Vm3C3MyQ+ub9TD0tiMgaFoFtv9c1QIPN7M +SI3nWgP1ztQO1ijEfwKSLHQWswMTTuE+yMOMHvKpK9qcOr/u34TR1bKVuL0PqUaa +C3nkBklM/F/Wg4qTqtGSMRA2rBrcPdiRG2Z/fUXGTTKpAkEA2oTvk96hKQ1uO6Hx +2D2aocaXs/ri8sTgrqNTYXfYPHO3r8To7/PsW00adDmf9eXARQP4Jk8DoTJzTDG/ +3iZ1OQJBALm+4qAVmePBEHJrH7AGWkZGAFo05nwtTNuRDYjJ7qsy79v4UOKq9zb0 +UmxOrHh8M7pom3Vs5JyPBRaPCtF4Ga0CQQCfeccy/pZVVJTvdlf+/a6dhEbwthft +HxvuuAnBJ2qra7RR1f4+KKGFXHcC/Y8tMVipxaTTqHS4rw4QPHqPkTeZAkEAkrUN +JGnLUZNk3Sp1Lb/mv4h8sMMFpODWyrln2jm8U+X4g2I+6LkmZ3ZUP41oNgXLiZkj +6HxomKtx1l6GqenVRQJAZ3hQDWBTYYZYoR13q++Zzy91dPZkK+CGMytgAEU+OpNf +J835Xn/ecvF94F/eflzrxHLIA0Wafc5iC8pOrRwETg== +-----END RSA PRIVATE KEY----- diff --git a/src/main/resources/certs/client_pub.pem b/src/main/resources/certs/client_pub.pem new file mode 100644 index 0000000..96b8817 --- /dev/null +++ b/src/main/resources/certs/client_pub.pem @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCejQE9rKg8v5TuaS9tODR9QNPg +P9MDhtyIFmKLmQTu2an/pEW18XWXEKi04ORYfwr7BjAJ9HMWspGRg8rbSjbethud +QnJUDtrqHNDYzJ1HhQT7sngGvpuH9ME7ZW4yZcMDS7/i5tQSps31JmGI+ULZg1cv +G5A/SbSqiE5PXSfIhQIDAQAB +-----END PUBLIC KEY----- diff --git a/src/main/resources/certs/readme.txt b/src/main/resources/certs/readme.txt new file mode 100644 index 0000000..ab9d458 --- /dev/null +++ b/src/main/resources/certs/readme.txt @@ -0,0 +1,2 @@ +证书类型为[RSA]p12 alias:taoyuanx-client + p12 密码:123456 \ No newline at end of file diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..3bf4057 --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + info + + + ${CONSOLE_LOG_PATTERN} + UTF-8 + + + + + + + ${LOG_HOME}/debug/${LOG_PREFIX}.log + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + ${LOG_HOME}/debug/${LOG_PREFIX}-%d{yyyy-MM-dd}.%i.log + + 100MB + + 15 + + + debug + ACCEPT + DENY + + + + + ${LOG_HOME}/info/${LOG_PREFIX}.log + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + ${LOG_HOME}/info/${LOG_PREFIX}-%d{yyyy-MM-dd}.%i.log + + 100MB + + 15 + + + info + ACCEPT + DENY + + + + + ${LOG_HOME}/warn/${LOG_PREFIX}.log + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + ${LOG_HOME}/warn/${LOG_PREFIX}-%d{yyyy-MM-dd}.%i.log + + 100MB + + 15 + + + warn + ACCEPT + DENY + + + + + + ${LOG_HOME}/error/${LOG_PREFIX}.log + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + ${LOG_HOME}/error/${LOG_PREFIX}-%d{yyyy-MM-dd}.%i.log + + 100MB + + 15 + + + ERROR + ACCEPT + DENY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml deleted file mode 100644 index 50df288..0000000 --- a/src/main/resources/logback.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - - %msg%n - - - - - - - ${LOG_HOME}/cert.log.%d{yyyy-MM-dd}.log - - - 30 - - - - %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - - %msg%n - - - - - 10MB - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/static/js/common/system.js b/src/main/resources/static/js/common/system.js index 3137596..3381448 100644 --- a/src/main/resources/static/js/common/system.js +++ b/src/main/resources/static/js/common/system.js @@ -1,7 +1,7 @@ //全局定义变量和全局函数 -var apiBaseUrl = "http://localhost:8080/" -var staticBaseUrl = "http://localhost:8080/" +var apiBaseUrl = "http://localhost:9999/" +var staticBaseUrl = "http://localhost:9999/" function getApiUrl(path) { return apiBaseUrl + path; diff --git a/src/main/resources/static/js/crypt/aes.js b/src/main/resources/static/js/crypt/aes.js new file mode 100644 index 0000000..827503c --- /dev/null +++ b/src/main/resources/static/js/crypt/aes.js @@ -0,0 +1,35 @@ +/* +CryptoJS v3.1.2 +code.google.com/p/crypto-js +(c) 2009-2013 by Jeff Mott. All rights reserved. +code.google.com/p/crypto-js/wiki/License +*/ +var CryptoJS=CryptoJS||function(u,p){var d={},l=d.lib={},s=function(){},t=l.Base={extend:function(a){s.prototype=this;var c=new s;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, +r=l.WordArray=t.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=p?c:4*a.length},toString:function(a){return(a||v).stringify(this)},concat:function(a){var c=this.words,e=a.words,j=this.sigBytes;a=a.sigBytes;this.clamp();if(j%4)for(var k=0;k>>2]|=(e[k>>>2]>>>24-8*(k%4)&255)<<24-8*((j+k)%4);else if(65535>>2]=e[k>>>2];else c.push.apply(c,e);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< +32-8*(c%4);a.length=u.ceil(c/4)},clone:function(){var a=t.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],e=0;e>>2]>>>24-8*(j%4)&255;e.push((k>>>4).toString(16));e.push((k&15).toString(16))}return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j>>3]|=parseInt(a.substr(j, +2),16)<<24-4*(j%8);return new r.init(e,c/2)}},b=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j>>2]>>>24-8*(j%4)&255));return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j>>2]|=(a.charCodeAt(j)&255)<<24-8*(j%4);return new r.init(e,c)}},x=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(b.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return b.parse(unescape(encodeURIComponent(a)))}}, +q=l.BufferedBlockAlgorithm=t.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=x.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,e=c.words,j=c.sigBytes,k=this.blockSize,b=j/(4*k),b=a?u.ceil(b):u.max((b|0)-this._minBufferSize,0);a=b*k;j=u.min(4*a,j);if(a){for(var q=0;q>>2]>>>24-8*(r%4)&255)<<16|(l[r+1>>>2]>>>24-8*((r+1)%4)&255)<<8|l[r+2>>>2]>>>24-8*((r+2)%4)&255,v=0;4>v&&r+0.75*v>>6*(3-v)&63));if(l=t.charAt(64))for(;d.length%4;)d.push(l);return d.join("")},parse:function(d){var l=d.length,s=this._map,t=s.charAt(64);t&&(t=d.indexOf(t),-1!=t&&(l=t));for(var t=[],r=0,w=0;w< +l;w++)if(w%4){var v=s.indexOf(d.charAt(w-1))<<2*(w%4),b=s.indexOf(d.charAt(w))>>>6-2*(w%4);t[r>>>2]|=(v|b)<<24-8*(r%4);r++}return p.create(t,r)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})(); +(function(u){function p(b,n,a,c,e,j,k){b=b+(n&a|~n&c)+e+k;return(b<>>32-j)+n}function d(b,n,a,c,e,j,k){b=b+(n&c|a&~c)+e+k;return(b<>>32-j)+n}function l(b,n,a,c,e,j,k){b=b+(n^a^c)+e+k;return(b<>>32-j)+n}function s(b,n,a,c,e,j,k){b=b+(a^(n|~c))+e+k;return(b<>>32-j)+n}for(var t=CryptoJS,r=t.lib,w=r.WordArray,v=r.Hasher,r=t.algo,b=[],x=0;64>x;x++)b[x]=4294967296*u.abs(u.sin(x+1))|0;r=r.MD5=v.extend({_doReset:function(){this._hash=new w.init([1732584193,4023233417,2562383102,271733878])}, +_doProcessBlock:function(q,n){for(var a=0;16>a;a++){var c=n+a,e=q[c];q[c]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360}var a=this._hash.words,c=q[n+0],e=q[n+1],j=q[n+2],k=q[n+3],z=q[n+4],r=q[n+5],t=q[n+6],w=q[n+7],v=q[n+8],A=q[n+9],B=q[n+10],C=q[n+11],u=q[n+12],D=q[n+13],E=q[n+14],x=q[n+15],f=a[0],m=a[1],g=a[2],h=a[3],f=p(f,m,g,h,c,7,b[0]),h=p(h,f,m,g,e,12,b[1]),g=p(g,h,f,m,j,17,b[2]),m=p(m,g,h,f,k,22,b[3]),f=p(f,m,g,h,z,7,b[4]),h=p(h,f,m,g,r,12,b[5]),g=p(g,h,f,m,t,17,b[6]),m=p(m,g,h,f,w,22,b[7]), +f=p(f,m,g,h,v,7,b[8]),h=p(h,f,m,g,A,12,b[9]),g=p(g,h,f,m,B,17,b[10]),m=p(m,g,h,f,C,22,b[11]),f=p(f,m,g,h,u,7,b[12]),h=p(h,f,m,g,D,12,b[13]),g=p(g,h,f,m,E,17,b[14]),m=p(m,g,h,f,x,22,b[15]),f=d(f,m,g,h,e,5,b[16]),h=d(h,f,m,g,t,9,b[17]),g=d(g,h,f,m,C,14,b[18]),m=d(m,g,h,f,c,20,b[19]),f=d(f,m,g,h,r,5,b[20]),h=d(h,f,m,g,B,9,b[21]),g=d(g,h,f,m,x,14,b[22]),m=d(m,g,h,f,z,20,b[23]),f=d(f,m,g,h,A,5,b[24]),h=d(h,f,m,g,E,9,b[25]),g=d(g,h,f,m,k,14,b[26]),m=d(m,g,h,f,v,20,b[27]),f=d(f,m,g,h,D,5,b[28]),h=d(h,f, +m,g,j,9,b[29]),g=d(g,h,f,m,w,14,b[30]),m=d(m,g,h,f,u,20,b[31]),f=l(f,m,g,h,r,4,b[32]),h=l(h,f,m,g,v,11,b[33]),g=l(g,h,f,m,C,16,b[34]),m=l(m,g,h,f,E,23,b[35]),f=l(f,m,g,h,e,4,b[36]),h=l(h,f,m,g,z,11,b[37]),g=l(g,h,f,m,w,16,b[38]),m=l(m,g,h,f,B,23,b[39]),f=l(f,m,g,h,D,4,b[40]),h=l(h,f,m,g,c,11,b[41]),g=l(g,h,f,m,k,16,b[42]),m=l(m,g,h,f,t,23,b[43]),f=l(f,m,g,h,A,4,b[44]),h=l(h,f,m,g,u,11,b[45]),g=l(g,h,f,m,x,16,b[46]),m=l(m,g,h,f,j,23,b[47]),f=s(f,m,g,h,c,6,b[48]),h=s(h,f,m,g,w,10,b[49]),g=s(g,h,f,m, +E,15,b[50]),m=s(m,g,h,f,r,21,b[51]),f=s(f,m,g,h,u,6,b[52]),h=s(h,f,m,g,k,10,b[53]),g=s(g,h,f,m,B,15,b[54]),m=s(m,g,h,f,e,21,b[55]),f=s(f,m,g,h,v,6,b[56]),h=s(h,f,m,g,x,10,b[57]),g=s(g,h,f,m,t,15,b[58]),m=s(m,g,h,f,D,21,b[59]),f=s(f,m,g,h,z,6,b[60]),h=s(h,f,m,g,C,10,b[61]),g=s(g,h,f,m,j,15,b[62]),m=s(m,g,h,f,A,21,b[63]);a[0]=a[0]+f|0;a[1]=a[1]+m|0;a[2]=a[2]+g|0;a[3]=a[3]+h|0},_doFinalize:function(){var b=this._data,n=b.words,a=8*this._nDataBytes,c=8*b.sigBytes;n[c>>>5]|=128<<24-c%32;var e=u.floor(a/ +4294967296);n[(c+64>>>9<<4)+15]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360;n[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(n.length+1);this._process();b=this._hash;n=b.words;for(a=0;4>a;a++)c=n[a],n[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;return b},clone:function(){var b=v.clone.call(this);b._hash=this._hash.clone();return b}});t.MD5=v._createHelper(r);t.HmacMD5=v._createHmacHelper(r)})(Math); +(function(){var u=CryptoJS,p=u.lib,d=p.Base,l=p.WordArray,p=u.algo,s=p.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:p.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,r){for(var p=this.cfg,s=p.hasher.create(),b=l.create(),u=b.words,q=p.keySize,p=p.iterations;u.length>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:q}),reset:function(){v.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a, +this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var n=d.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(p.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?s.create([1398893684, +1701076831]).concat(a).concat(b):b).toString(r)},parse:function(a){a=r.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=s.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return n.create({ciphertext:a,salt:c})}},a=d.SerializableCipher=l.extend({cfg:l.extend({format:b}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var l=a.createEncryptor(c,d);b=l.finalize(b);l=l.cfg;return n.create({ciphertext:b,key:c,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})}, +decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),p=(p.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=s.random(8));a=w.create({keySize:b+c}).compute(a,d);c=s.create(a.words.slice(b),4*c);a.sigBytes=4*b;return n.create({key:a,iv:c,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:p}),encrypt:function(b,c,d,l){l=this.cfg.extend(l);d=l.kdf.execute(d, +b.keySize,b.ivSize);l.iv=d.iv;b=a.encrypt.call(this,b,c,d.key,l);b.mixIn(d);return b},decrypt:function(b,c,d,l){l=this.cfg.extend(l);c=this._parse(c,l.format);d=l.kdf.execute(d,b.keySize,b.ivSize,c.salt);l.iv=d.iv;return a.decrypt.call(this,b,c,d.key,l)}})}(); +(function(){for(var u=CryptoJS,p=u.lib.BlockCipher,d=u.algo,l=[],s=[],t=[],r=[],w=[],v=[],b=[],x=[],q=[],n=[],a=[],c=0;256>c;c++)a[c]=128>c?c<<1:c<<1^283;for(var e=0,j=0,c=0;256>c;c++){var k=j^j<<1^j<<2^j<<3^j<<4,k=k>>>8^k&255^99;l[e]=k;s[k]=e;var z=a[e],F=a[z],G=a[F],y=257*a[k]^16843008*k;t[e]=y<<24|y>>>8;r[e]=y<<16|y>>>16;w[e]=y<<8|y>>>24;v[e]=y;y=16843009*G^65537*F^257*z^16843008*e;b[k]=y<<24|y>>>8;x[k]=y<<16|y>>>16;q[k]=y<<8|y>>>24;n[k]=y;e?(e=z^a[a[a[G^z]]],j^=a[a[j]]):e=j=1}var H=[0,1,2,4,8, +16,32,64,128,27,54],d=d.AES=p.extend({_doReset:function(){for(var a=this._key,c=a.words,d=a.sigBytes/4,a=4*((this._nRounds=d+6)+1),e=this._keySchedule=[],j=0;j>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255]):(k=k<<8|k>>>24,k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255],k^=H[j/d|0]<<24);e[j]=e[j-d]^k}c=this._invKeySchedule=[];for(d=0;dd||4>=j?k:b[l[k>>>24]]^x[l[k>>>16&255]]^q[l[k>>> +8&255]]^n[l[k&255]]},encryptBlock:function(a,b){this._doCryptBlock(a,b,this._keySchedule,t,r,w,v,l)},decryptBlock:function(a,c){var d=a[c+1];a[c+1]=a[c+3];a[c+3]=d;this._doCryptBlock(a,c,this._invKeySchedule,b,x,q,n,s);d=a[c+1];a[c+1]=a[c+3];a[c+3]=d},_doCryptBlock:function(a,b,c,d,e,j,l,f){for(var m=this._nRounds,g=a[b]^c[0],h=a[b+1]^c[1],k=a[b+2]^c[2],n=a[b+3]^c[3],p=4,r=1;r>>24]^e[h>>>16&255]^j[k>>>8&255]^l[n&255]^c[p++],s=d[h>>>24]^e[k>>>16&255]^j[n>>>8&255]^l[g&255]^c[p++],t= +d[k>>>24]^e[n>>>16&255]^j[g>>>8&255]^l[h&255]^c[p++],n=d[n>>>24]^e[g>>>16&255]^j[h>>>8&255]^l[k&255]^c[p++],g=q,h=s,k=t;q=(f[g>>>24]<<24|f[h>>>16&255]<<16|f[k>>>8&255]<<8|f[n&255])^c[p++];s=(f[h>>>24]<<24|f[k>>>16&255]<<16|f[n>>>8&255]<<8|f[g&255])^c[p++];t=(f[k>>>24]<<24|f[n>>>16&255]<<16|f[g>>>8&255]<<8|f[h&255])^c[p++];n=(f[n>>>24]<<24|f[g>>>16&255]<<16|f[h>>>8&255]<<8|f[k&255])^c[p++];a[b]=q;a[b+1]=s;a[b+2]=t;a[b+3]=n},keySize:8});u.AES=p._createHelper(d)})(); diff --git a/src/main/resources/static/js/crypt/jsencrypt.min.js b/src/main/resources/static/js/crypt/jsencrypt.min.js new file mode 100644 index 0000000..27c29d5 --- /dev/null +++ b/src/main/resources/static/js/crypt/jsencrypt.min.js @@ -0,0 +1 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.JSEncrypt={})}(this,function(t){"use strict";var e="0123456789abcdefghijklmnopqrstuvwxyz";function a(t){return e.charAt(t)}function i(t,e){return t&e}function u(t,e){return t|e}function r(t,e){return t^e}function n(t,e){return t&~e}function s(t){if(0==t)return-1;var e=0;return 0==(65535&t)&&(t>>=16,e+=16),0==(255&t)&&(t>>=8,e+=8),0==(15&t)&&(t>>=4,e+=4),0==(3&t)&&(t>>=2,e+=2),0==(1&t)&&++e,e}function o(t){for(var e=0;0!=t;)t&=t-1,++e;return e}var h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function c(t){var e,i,r="";for(e=0;e+3<=t.length;e+=3)i=parseInt(t.substring(e,e+3),16),r+=h.charAt(i>>6)+h.charAt(63&i);for(e+1==t.length?(i=parseInt(t.substring(e,e+1),16),r+=h.charAt(i<<2)):e+2==t.length&&(i=parseInt(t.substring(e,e+2),16),r+=h.charAt(i>>2)+h.charAt((3&i)<<4));0<(3&r.length);)r+="=";return r}function f(t){var e,i="",r=0,n=0;for(e=0;e>2),n=3&s,r=1):1==r?(i+=a(n<<2|s>>4),n=15&s,r=2):2==r?(i+=a(n),i+=a(s>>2),n=3&s,r=3):(i+=a(n<<2|s>>4),i+=a(15&s),r=0))}return 1==r&&(i+=a(n<<2)),i}var l,p=function(t,e){return(p=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i])})(t,e)};var g,d=function(t){var e;if(void 0===l){var i="0123456789ABCDEF",r=" \f\n\r\t \u2028\u2029";for(l={},e=0;e<16;++e)l[i.charAt(e)]=e;for(i=i.toLowerCase(),e=10;e<16;++e)l[i.charAt(e)]=e;for(e=0;e>16,r[r.length]=n>>8&255,r[r.length]=255&n,s=n=0):n<<=6}}switch(s){case 1:throw new Error("Base64 encoding incomplete: at least 2 bits missing");case 2:r[r.length]=n>>10;break;case 3:r[r.length]=n>>16,r[r.length]=n>>8&255}return r},re:/-----BEGIN [^-]+-----([A-Za-z0-9+\/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+\/=\s]+)====/,unarmor:function(t){var e=v.re.exec(t);if(e)if(e[1])t=e[1];else{if(!e[2])throw new Error("RegExp out of sync");t=e[2]}return v.decode(t)}},m=1e13,y=function(){function t(t){this.buf=[+t||0]}return t.prototype.mulAdd=function(t,e){var i,r,n=this.buf,s=n.length;for(i=0;ie&&(t=t.substring(0,e)+b),t}var w,D=function(){function i(t,e){this.hexDigits="0123456789ABCDEF",t instanceof i?(this.enc=t.enc,this.pos=t.pos):(this.enc=t,this.pos=e)}return i.prototype.get=function(t){if(void 0===t&&(t=this.pos++),t>=this.enc.length)throw new Error("Requesting byte offset "+t+" on a stream of length "+this.enc.length);return"string"==typeof this.enc?this.enc.charCodeAt(t):this.enc[t]},i.prototype.hexByte=function(t){return this.hexDigits.charAt(t>>4&15)+this.hexDigits.charAt(15&t)},i.prototype.hexDump=function(t,e,i){for(var r="",n=t;n>u&1?"1":"0";if(s.length>i)return n+E(s,i)}return n+s},i.prototype.parseOctetString=function(t,e,i){if(this.isASCII(t,e))return E(this.parseStringISO(t,e),i);var r=e-t,n="("+r+" byte)\n";(i/=2)i)return E(r,i);n=new y,s=0}}return 0>6,this.tagConstructed=0!=(32&e),this.tagNumber=31&e,31==this.tagNumber){for(var i=new y;e=t.get(),i.mulAdd(128,127&e),128&e;);this.tagNumber=i.simplify()}}return t.prototype.isUniversal=function(){return 0===this.tagClass},t.prototype.isEOC=function(){return 0===this.tagClass&&0===this.tagNumber},t}(),B=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997],A=(1<<26)/B[B.length-1],O=function(){function b(t,e,i){null!=t&&("number"==typeof t?this.fromNumber(t,e,i):null==e&&"string"!=typeof t?this.fromString(t,256):this.fromString(t,e))}return b.prototype.toString=function(t){if(this.s<0)return"-"+this.negate().toString(t);var e;if(16==t)e=4;else if(8==t)e=3;else if(2==t)e=1;else if(32==t)e=5;else{if(4!=t)return this.toRadix(t);e=2}var i,r=(1<>h)&&(n=!0,s=a(i));0<=o;)h>(h+=this.DB-e)):(i=this[o]>>(h-=e)&r,h<=0&&(h+=this.DB,--o)),0>24},b.prototype.shortValue=function(){return 0==this.t?this.s:this[0]<<16>>16},b.prototype.signum=function(){return this.s<0?-1:this.t<=0||1==this.t&&this[0]<=0?0:1},b.prototype.toByteArray=function(){var t=this.t,e=[];e[0]=this.s;var i,r=this.DB-t*this.DB%8,n=0;if(0>r)!=(this.s&this.DM)>>r&&(e[n++]=i|this.s<>(r+=this.DB-8)):(i=this[t]>>(r-=8)&255,r<=0&&(r+=this.DB,--t)),0!=(128&i)&&(i|=-256),0==n&&(128&this.s)!=(128&i)&&++n,(0=this.t?0!=this.s:0!=(this[e]&1<>n-a&u:(f=(t[p]&(1<>this.DB+n-a)),h=i;0==(1&f);)f>>=1,--h;if((n-=h)<0&&(n+=this.DB,--p),g)o[f].copyTo(s),g=!1;else{for(;1this.DB?(this[this.t-1]|=(o&(1<>this.DB-s):this[this.t-1]|=o<=this.DB&&(s-=this.DB))}8==i&&0!=(128&+t[0])&&(this.s=-1,0>r|o,o=(this[h]&n)<=this.t)e.t=0;else{var r=t%this.DB,n=this.DB-r,s=(1<>r;for(var o=i+1;o>r;0>=this.DB;if(t.t>=this.DB;r+=this.s}else{for(r+=this.s;i>=this.DB;r-=t.s}e.s=r<0?-1:0,r<-1?e[i++]=this.DV+r:0=e.DV&&(t[i+e.t]-=e.DV,t[i+e.t+1]=1)}0>this.F2:0),l=this.FV/f,p=(1<=i&&(this.dMultiply(r),this.dAddOffset(o,0),o=s=0))}0t&&this.subTo(b.ONE.shiftLeft(t-1),this);else{var r=[],n=7&t;r.length=1+(t>>3),e.nextBytes(r),0>=this.DB;if(t.t>=this.DB;r+=this.s}else{for(r+=this.s;i>=this.DB;r+=t.s}e.s=r<0?-1:0,0=this.DV;)this[e]-=this.DV,++e>=this.t&&(this[this.t++]=0),++this[e]}},b.prototype.multiplyLowerTo=function(t,e,i){var r=Math.min(this.t+t.t,e);for(i.s=0,i.t=r;0>1)&&(t=B.length);for(var n=M(),s=0;st&&n.subTo(b.ONE.shiftLeft(t-1),n),n.isProbablePrime(e)?setTimeout(function(){r()},0):setTimeout(s,0)};setTimeout(s,0)}else{var o=[],h=7&t;o.length=1+(t>>3),e.nextBytes(o),0>15,this.um=(1<>15)*this.mpl&this.um)<<15)&t.DM;for(t[i=e+this.m.t]+=this.m.am(0,r,t,e,0,this.m.t);t[i]>=t.DV;)t[i]-=t.DV,t[++i]++}t.clamp(),t.drShiftTo(this.m.t,t),0<=t.compareTo(this.m)&&t.subTo(this.m,t)},t.prototype.mulTo=function(t,e,i){t.multiplyTo(e,i),this.reduce(i)},t.prototype.sqrTo=function(t,e){t.squareTo(e),this.reduce(e)},t}(),P=function(){function t(t){this.m=t,this.r2=M(),this.q3=M(),O.ONE.dlShiftTo(2*t.t,this.r2),this.mu=this.r2.divide(t)}return t.prototype.convert=function(t){if(t.s<0||t.t>2*this.m.t)return t.mod(this.m);if(t.compareTo(this.m)<0)return t;var e=M();return t.copyTo(e),this.reduce(e),e},t.prototype.revert=function(t){return t},t.prototype.reduce=function(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);0<=t.compareTo(this.m);)t.subTo(this.m,t)},t.prototype.mulTo=function(t,e,i){t.multiplyTo(e,i),this.reduce(i)},t.prototype.sqrTo=function(t,e){t.squareTo(e),this.reduce(e)},t}();function M(){return new O(null)}function q(t,e){return new O(t,e)}"Microsoft Internet Explorer"==navigator.appName?(O.prototype.am=function(t,e,i,r,n,s){for(var o=32767&e,h=e>>15;0<=--s;){var a=32767&this[t],u=this[t++]>>15,c=h*a+u*o;n=((a=o*a+((32767&c)<<15)+i[r]+(1073741823&n))>>>30)+(c>>>15)+h*u+(n>>>30),i[r++]=1073741823&a}return n},w=30):"Netscape"!=navigator.appName?(O.prototype.am=function(t,e,i,r,n,s){for(;0<=--s;){var o=e*this[t++]+i[r]+n;n=Math.floor(o/67108864),i[r++]=67108863&o}return n},w=26):(O.prototype.am=function(t,e,i,r,n,s){for(var o=16383&e,h=e>>14;0<=--s;){var a=16383&this[t],u=this[t++]>>14,c=h*a+u*o;n=((a=o*a+((16383&c)<<14)+i[r]+n)>>28)+(c>>14)+h*u,i[r++]=268435455&a}return n},w=28),O.prototype.DB=w,O.prototype.DM=(1<>>16)&&(t=e,i+=16),0!=(e=t>>8)&&(t=e,i+=8),0!=(e=t>>4)&&(t=e,i+=4),0!=(e=t>>2)&&(t=e,i+=2),0!=(e=t>>1)&&(t=e,i+=1),i}O.ZERO=F(0),O.ONE=F(1);var K=function(){function t(){this.i=0,this.j=0,this.S=[]}return t.prototype.init=function(t){var e,i,r;for(e=0;e<256;++e)this.S[e]=e;for(e=i=0;e<256;++e)i=i+this.S[e]+t[e%t.length]&255,r=this.S[e],this.S[e]=this.S[i],this.S[i]=r;this.i=0,this.j=0},t.prototype.next=function(){var t;return this.i=this.i+1&255,this.j=this.j+this.S[this.i]&255,t=this.S[this.i],this.S[this.i]=this.S[this.j],this.S[this.j]=t,this.S[t+this.S[this.i]&255]},t}();var k,_,z=256,Z=null;if(null==Z){Z=[];var G=void(_=0);if(window.crypto&&window.crypto.getRandomValues){var $=new Uint32Array(256);for(window.crypto.getRandomValues($),G=0;G<$.length;++G)Z[_++]=255&$[G]}var Y=function(t){if(this.count=this.count||0,256<=this.count||z<=_)window.removeEventListener?window.removeEventListener("mousemove",Y,!1):window.detachEvent&&window.detachEvent("onmousemove",Y);else try{var e=t.x+t.y;Z[_++]=255&e,this.count+=1}catch(t){}};window.addEventListener?window.addEventListener("mousemove",Y,!1):window.attachEvent&&window.attachEvent("onmousemove",Y)}function J(){if(null==k){for(k=new K;_>6|192):(i[--e]=63&n|128,i[--e]=n>>6&63|128,i[--e]=n>>12|224)}i[--e]=0;for(var s=new X,o=[];2>3);if(null==e)return null;var i=this.doPublic(e);if(null==i)return null;var r=i.toString(16);return 0==(1&r.length)?r:"0"+r},t.prototype.setPrivate=function(t,e,i){null!=t&&null!=e&&0>1;this.e=parseInt(e,16);for(var n=new O(e,16);;){for(;this.p=new O(t-r,1,i),0!=this.p.subtract(O.ONE).gcd(n).compareTo(O.ONE)||!this.p.isProbablePrime(10););for(;this.q=new O(r,1,i),0!=this.q.subtract(O.ONE).gcd(n).compareTo(O.ONE)||!this.q.isProbablePrime(10););if(this.p.compareTo(this.q)<=0){var s=this.p;this.p=this.q,this.q=s}var o=this.p.subtract(O.ONE),h=this.q.subtract(O.ONE),a=o.multiply(h);if(0==a.gcd(n).compareTo(O.ONE)){this.n=this.p.multiply(this.q),this.d=n.modInverse(a),this.dmp1=this.d.mod(o),this.dmq1=this.d.mod(h),this.coeff=this.q.modInverse(this.p);break}}},t.prototype.decrypt=function(t){var e=q(t,16),i=this.doPrivate(e);return null==i?null:function(t,e){var i=t.toByteArray(),r=0;for(;r=i.length)return null;var n="";for(;++r>3)},t.prototype.generateAsync=function(t,e,n){var s=new X,o=t>>1;this.e=parseInt(e,16);var h=new O(e,16),a=this,u=function(){var e=function(){if(a.p.compareTo(a.q)<=0){var t=a.p;a.p=a.q,a.q=t}var e=a.p.subtract(O.ONE),i=a.q.subtract(O.ONE),r=e.multiply(i);0==r.gcd(h).compareTo(O.ONE)?(a.n=a.p.multiply(a.q),a.d=h.modInverse(r),a.dmp1=a.d.mod(e),a.dmq1=a.d.mod(i),a.coeff=a.q.modInverse(a.p),setTimeout(function(){n()},0)):setTimeout(u,0)},i=function(){a.q=M(),a.q.fromNumberAsync(o,1,s,function(){a.q.subtract(O.ONE).gcda(h,function(t){0==t.compareTo(O.ONE)&&a.q.isProbablePrime(10)?setTimeout(e,0):setTimeout(i,0)})})},r=function(){a.p=M(),a.p.fromNumberAsync(t-o,1,s,function(){a.p.subtract(O.ONE).gcda(h,function(t){0==t.compareTo(O.ONE)&&a.p.isProbablePrime(10)?setTimeout(i,0):setTimeout(r,0)})})};setTimeout(r,0)};setTimeout(u,0)},t.prototype.sign=function(t,e,i){var r=function(t,e){if(e=e?t:new Array(e-t.length+1).join("0")+t},this.getString=function(){return this.s},this.setString=function(t){this.hTLV=null,this.isModified=!0,this.s=t,this.hV=stohex(t)},this.setByDateValue=function(t,e,i,r,n,s){var o=new Date(Date.UTC(t,e-1,i,r,n,s,0));this.setByDate(o)},this.getFreshValueHex=function(){return this.hV}},tt.lang.extend(et.asn1.DERAbstractTime,et.asn1.ASN1Object),et.asn1.DERAbstractStructured=function(t){et.asn1.DERAbstractString.superclass.constructor.call(this),this.setByASN1ObjectArray=function(t){this.hTLV=null,this.isModified=!0,this.asn1Array=t},this.appendASN1Object=function(t){this.hTLV=null,this.isModified=!0,this.asn1Array.push(t)},this.asn1Array=new Array,void 0!==t&&void 0!==t.array&&(this.asn1Array=t.array)},tt.lang.extend(et.asn1.DERAbstractStructured,et.asn1.ASN1Object),et.asn1.DERBoolean=function(){et.asn1.DERBoolean.superclass.constructor.call(this),this.hT="01",this.hTLV="0101ff"},tt.lang.extend(et.asn1.DERBoolean,et.asn1.ASN1Object),et.asn1.DERInteger=function(t){et.asn1.DERInteger.superclass.constructor.call(this),this.hT="02",this.setByBigInteger=function(t){this.hTLV=null,this.isModified=!0,this.hV=et.asn1.ASN1Util.bigIntToMinTwosComplementsHex(t)},this.setByInteger=function(t){var e=new O(String(t),10);this.setByBigInteger(e)},this.setValueHex=function(t){this.hV=t},this.getFreshValueHex=function(){return this.hV},void 0!==t&&(void 0!==t.bigint?this.setByBigInteger(t.bigint):void 0!==t.int?this.setByInteger(t.int):"number"==typeof t?this.setByInteger(t):void 0!==t.hex&&this.setValueHex(t.hex))},tt.lang.extend(et.asn1.DERInteger,et.asn1.ASN1Object),et.asn1.DERBitString=function(t){if(void 0!==t&&void 0!==t.obj){var e=et.asn1.ASN1Util.newObject(t.obj);t.hex="00"+e.getEncodedHex()}et.asn1.DERBitString.superclass.constructor.call(this),this.hT="03",this.setHexValueIncludingUnusedBits=function(t){this.hTLV=null,this.isModified=!0,this.hV=t},this.setUnusedBitsAndHexValue=function(t,e){if(t<0||7 + + + + 加密例子 + + + + + + + + + + + + + + +
+ + + + + + +
+ + + + \ No newline at end of file diff --git a/src/test/java/com/taoyuanx/securitydemo/CertTest.java b/src/test/java/com/taoyuanx/securitydemo/CertTest.java new file mode 100644 index 0000000..c6540fe --- /dev/null +++ b/src/test/java/com/taoyuanx/securitydemo/CertTest.java @@ -0,0 +1,44 @@ +package com.taoyuanx.securitydemo; + +import com.taoyuanx.securitydemo.utils.HashUtil; +import com.taoyuanx.securitydemo.utils.HelperUtil; +import com.taoyuanx.securitydemo.utils.RSAUtil; +import org.junit.Test; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.security.KeyStore; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; + +/** + * @author dushitaoyuan + * @date 2020/1/15 + */ +public class CertTest { + @Test + public void rsaTest() throws Exception { + + + KeyStore keyStore = RSAUtil.getKeyStore("d://client.p12", "123456"); + RSAPublicKey publicKey = RSAUtil.getPublicKey(keyStore); + RSAUtil.getPrivateKey(keyStore, "123456"); + + } + + @Test + public void rsaDecodeFileTest() throws Exception { + + KeyStore keyStore = RSAUtil.getKeyStore("d://client.p12", "123456"); + RSAPublicKey publicKey = RSAUtil.getPublicKey(keyStore); + RSAPrivateKey privateKey = RSAUtil.getPrivateKey(keyStore, "123456"); + String srcFile = "d://demo.pdf", encodeFile = "d://demo_encode.pdf", decodeFile = "d://demo_decode.pdf"; + String fileHash = HashUtil.hash(new FileInputStream(srcFile), HashUtil.MD5, HashUtil.HEX); + RSAUtil.encryptByPublicKey(new FileInputStream(srcFile), publicKey, new FileOutputStream(encodeFile)); + RSAUtil.decryptByPrivateKey(new FileInputStream(encodeFile), privateKey, new FileOutputStream(decodeFile)); + + String fileEncodeHash = HashUtil.hash(new FileInputStream(decodeFile), HashUtil.MD5, HashUtil.HEX); + System.out.println(fileHash.equals(fileEncodeHash)); + + } +}