diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 3fb237a..0000000 --- a/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,5 +0,0 @@ -eclipse.preferences.version=1 -encoding//src/main/java=UTF-8 -encoding//src/main/resources=UTF-8 -encoding//src/main/resources/msg/zh-CN/MessageResources.properties=UTF-8 -encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 71df522..772e9c1 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,9 +1,5 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +#Sun Jan 12 10:00:36 CST 2020 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore -org.eclipse.jdt.core.compiler.release=disabled +eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f..0000000 --- a/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/pom.xml b/pom.xml index 1057e51..17a2ec2 100644 --- a/pom.xml +++ b/pom.xml @@ -27,21 +27,21 @@ + + cn.hutool + hutool-all + 5.1.0 + org.tmatesoft.svnkit svnkit - 1.7.6 + 1.10.1 org.nutz nutz-plugins-slog ${nutz.version} - - com.restfb - restfb - 1.6.14 - ch.ethz.ganymed ganymed-ssh2 @@ -58,7 +58,7 @@ org.json json - 20090211 + 20190722 org.nutz @@ -99,7 +99,7 @@ commons-logging commons-logging - 1.1.3 + 1.2 org.nutz @@ -121,21 +121,6 @@ org.nutz nutzboot-starter-jetty - - org.brickred - socialauth - 4.5 - - - org.json - json - - - org.openid4java - openid4java-consumer - - - mysql mysql-connector-java diff --git a/src/main/java/com/rekoe/service/RepositoryService.java b/src/main/java/com/rekoe/service/RepositoryService.java index ba3002e..708beaa 100644 --- a/src/main/java/com/rekoe/service/RepositoryService.java +++ b/src/main/java/com/rekoe/service/RepositoryService.java @@ -61,11 +61,9 @@ public class RepositoryService { /** * 获取svn仓库 * - * @param pjId - * 项目ID + * @param pjId 项目ID * @return svn仓库 - * @throws SVNException - * svn异常,例如没有权限等 + * @throws SVNException svn异常,例如没有权限等 */ public SVNRepository getRepository(String pjId) throws SVNException { Pj pj = projectService.fetch(Cnd.where("pj", "=", pjId)); @@ -79,8 +77,7 @@ public class RepositoryService { /** * 从项目的url中获取svn的url * - * @param url - * 项目url + * @param url 项目url * @return svn url */ public static String parseURL(String url) { @@ -106,11 +103,9 @@ public class RepositoryService { /** * 获取svn仓库 * - * @param pj - * 项目 + * @param pj 项目 * @return svn仓库 - * @throws SVNException - * svn异常,例如没有权限等 + * @throws SVNException svn异常,例如没有权限等 */ @SuppressWarnings("deprecation") public SVNRepository getRepository(Pj pj) throws SVNException { @@ -185,28 +180,28 @@ public class RepositoryService { return true; } - public static void main(String[] args) { - DAVRepositoryFactory.setup(); - SVNRepositoryFactoryImpl.setup(); - FSRepositoryFactory.setup(); + public static void main(String[] args) throws SVNException { ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager("admin", "123456"); - SVNClientManager manager = SVNClientManager.newInstance(); - manager.setAuthenticationManager(authManager); - SVNCommitClient commitClient = SVNClientManager.newInstance().getCommitClient(); + SVNClientManager manager = SVNClientManager.newInstance(SVNWCUtil.createDefaultOptions(true), authManager); + SVNCommitClient commitClient = manager.getCommitClient(); + commitClient.getDebugLog(); try { - SVNCommitInfo info = commitClient.doMkDir(new SVNURL[] { SVNURL.parseURIEncoded("http://127.0.0.1:3380/svn/hunnit") }, "commitMessage", null, true); + SVNCommitInfo info = commitClient.doMkDir(new SVNURL[] { SVNURL.parseURIEncoded("http://svn.test.com/svn/hunnit/test") }, "commitMessage", null, true); long newRevision = info.getNewRevision(); System.out.println(newRevision); - } catch (SVNException e) { + } catch (Exception e) { e.printStackTrace(); } + SVNRepository repository = SVNRepositoryFactory.create(SVNURL.parseURIDecoded("http://svn.test.com/svn/hunnit")); + repository.setAuthenticationManager(authManager); + long lastVersion = repository.getLatestRevision(); + System.out.println(lastVersion); } /** * 返回项目仓库的根 * - * @param pj - * 项目 + * @param pj 项目 * @return 仓库根 */ public String getRepositoryRoot(Pj pj) { @@ -230,10 +225,8 @@ public class RepositoryService { /** * 获取项目指定路径的svn仓库文件系统 * - * @param pj - * 项目 - * @param path - * 相对仓库根目录的路径 + * @param pj 项目 + * @param path 相对仓库根目录的路径 * @return 目录或文件系统 */ @SuppressWarnings({ "unchecked", "rawtypes" }) @@ -268,8 +261,7 @@ public class RepositoryService { * createLocalRepository(path, null, enableRevisionProperties, force) * . * - * @param respository - * a repository root location + * @param respository a repository root location * @return a local URL (file:///) of a newly created repository */ public static SVNURL createLocalRepository(File respository) { diff --git a/src/main/java/com/rekoe/service/SvnService.java b/src/main/java/com/rekoe/service/SvnService.java index 72db988..e65b96b 100644 --- a/src/main/java/com/rekoe/service/SvnService.java +++ b/src/main/java/com/rekoe/service/SvnService.java @@ -17,6 +17,7 @@ import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.log.Log; import org.nutz.log.Logs; +import org.nutz.repo.Base64; import com.rekoe.domain.Pj; import com.rekoe.domain.PjAuth; @@ -25,6 +26,9 @@ import com.rekoe.domain.Usr; import com.rekoe.utils.Constants; import com.rekoe.utils.EncryptUtil; +import cn.hutool.crypto.digest.DigestAlgorithm; +import cn.hutool.crypto.digest.DigestUtil; + /** * 导出svn配置信息服务层 * @@ -62,8 +66,7 @@ public class SvnService { /** * 导出到配置文件 * - * @param pj - * 项目id + * @param pj 项目id */ public synchronized void exportConfig(String pj) { this.exportConfig(projectService.fetch(Cnd.where("pj", "=", pj))); @@ -72,8 +75,7 @@ public class SvnService { /** * 导出到配置文件 * - * @param pj - * 项目 + * @param pj 项目 */ public synchronized void exportConfig(Pj pj) { if (pj == null) { @@ -100,8 +102,7 @@ public class SvnService { /** * 导出svn协议的配置信息 * - * @param pj - * 项目 + * @param pj 项目 */ private void exportSVN(Pj pj) { // 项目的用户 @@ -118,8 +119,7 @@ public class SvnService { /** * 导出http(单库)的配置信息 * - * @param pj - * 项目 + * @param pj 项目 */ private void exportHTTP(Pj pj) { // 项目的用户 @@ -136,8 +136,7 @@ public class SvnService { /** * 导出http(多库)的配置信息 * - * @param root - * svn root + * @param root svn root */ private void exportHTTPMutil(File root) { String svnRoot = StringUtils.replace(root.getAbsolutePath(), "\\", "/"); @@ -158,8 +157,7 @@ public class SvnService { /** * 获取有相同svn root的项目的权限列表 * - * @param rootPath - * svn root + * @param rootPath svn root * @return 有相同svn root的项目的权限列表 */ private Map> getPjAuthsByRootPath(String rootPath) { @@ -180,8 +178,7 @@ public class SvnService { /** * 获取项目的权限列表 * - * @param pj - * 项目 + * @param pj 项目 * @return 项目的权限列表 */ private Map> getPjAuths(String pj) { @@ -203,8 +200,7 @@ public class SvnService { /** * 获取项目的组列表 * - * @param pj - * 项目 + * @param pj 项目 * @return 项目的组列表 */ private Map> getPjGrUsrs(String pj) { @@ -225,8 +221,7 @@ public class SvnService { /** * 获取有相同svn root的项目的权限列表 * - * @param rootPath - * svn root + * @param rootPath svn root * @return 有相同svn root的项目的权限列表 */ private Map> getPjGrUsrsByRootPath(String rootPath) { @@ -250,10 +245,8 @@ public class SvnService { /** * 输出http多库方式的密码文件 * - * @param root - * svn root - * @param usrList - * 所有用户列表 + * @param root svn root + * @param usrList 所有用户列表 */ private void exportPasswdHTTPMutil(File root, List usrList) { File outFile = new File(root, "passwd.http"); @@ -270,10 +263,8 @@ public class SvnService { /** * 输出http单库方式的密码文件 * - * @param pj - * 项目 - * @param usrList - * 项目用户列表 + * @param pj 项目 + * @param usrList 项目用户列表 */ private void exportPasswdHTTP(Pj pj, List usrList) { String path = projectConfigService.getRepoPath(pj); @@ -291,10 +282,8 @@ public class SvnService { /** * 输出svn方式的密码文件 * - * @param pj - * 项目 - * @param usrList - * 项目用户列表 + * @param pj 项目 + * @param usrList 项目用户列表 */ private void exportPasswdSVN(Pj pj, List usrList) { String path = projectConfigService.getRepoPath(pj); @@ -310,12 +299,9 @@ public class SvnService { /** * 输出http多库方式的权限文件 * - * @param root - * svn root - * @param pjGrUsrMap - * 所有的项目组用户列表 - * @param resMap - * 所有的权限列表 + * @param root svn root + * @param pjGrUsrMap 所有的项目组用户列表 + * @param resMap 所有的权限列表 */ private void exportAuthzHTTPMutil(File root, Map> pjGrUsrMap, Map> resMap) { if (root == null) { @@ -362,20 +348,17 @@ public class SvnService { /** * 输出权限配置文件 * - * @param pj - * 项目 - * @param pjGrUsrMap - * 项目的组列表 - * @param resMap - * 项目的权限列表 + * @param pj 项目 + * @param pjGrUsrMap 项目的组列表 + * @param resMap 项目的权限列表 */ private void exportAuthz(Pj pj, Map> pjGrUsrMap, Map> resMap) { if (pj == null || StringUtils.isBlank(pj.getPj())) { return; } /* - * if(pjGrList == null || pjGrList.size() == 0){ return; } if(pjAuthMap - * == null || pjAuthMap.size() == 0){ return; } + * if(pjGrList == null || pjGrList.size() == 0){ return; } if(pjAuthMap == null + * || pjAuthMap.size() == 0){ return; } */ String path = projectConfigService.getRepoPath(pj); File outFile = new File(path, "/conf/authz"); @@ -418,8 +401,7 @@ public class SvnService { /** * 输出svn方式的svnserve.conf * - * @param pj - * 项目 + * @param pj 项目 */ private void exportSvnConf(Pj pj) { if (pj == null || StringUtils.isBlank(pj.getPj())) { @@ -440,8 +422,7 @@ public class SvnService { /** * 输出http单库方式的httpd.conf文件 * - * @param pj - * 项目 + * @param pj 项目 */ private void exportSVNPathConf(Pj pj) { if (pj == null || StringUtils.isBlank(pj.getPj())) { @@ -474,8 +455,7 @@ public class SvnService { /** * 输出http多库方式的httpd.conf文件 * - * @param root - * svn root + * @param root svn root */ private void exportSVNParentPathConf(File root) { String svnRoot = StringUtils.replace(root.getAbsolutePath(), "\\", "/"); @@ -500,10 +480,8 @@ public class SvnService { /** * 写文件流 * - * @param outFile - * 输出文件 - * @param contents - * 内容 + * @param outFile 输出文件 + * @param contents 内容 */ private void write(File outFile, String contents) { BufferedWriter writer = null; @@ -535,4 +513,13 @@ public class SvnService { } } } + + public static void main(String[] args) { + String key = "admin" + ":{SHA}" + Base64.encodeToString(DigestUtil.digester(DigestAlgorithm.SHA1).digest("123456"), false); + System.out.println(key); + String key2 = "admin" + ":{SHA}" + EncryptUtil.encriptSHA1("123456"); + System.out.println(key2); + String decode = EncryptUtil.decrypt("fEqNCco3Yq9h5ZUglD3CZJT4lBs="); + System.out.println(decode); + } } diff --git a/src/main/java/com/rekoe/utils/CryptTest.java b/src/main/java/com/rekoe/utils/CryptTest.java new file mode 100644 index 0000000..1e55f7f --- /dev/null +++ b/src/main/java/com/rekoe/utils/CryptTest.java @@ -0,0 +1,325 @@ +package com.rekoe.utils; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.HashMap; +import java.util.Map; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.commons.lang3.ArrayUtils; +import org.nutz.repo.Base64; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * AES对称加密 RSA非对称加密 Hex加密 私钥签名,公钥验证 + */ +public class CryptTest { + + private static final String UTF8 = "UTF-8"; + + public static void main(String[] args) throws Exception { + String data = "123456"; + + /** + * AES对称加密 + */ + String key = "$i%2i9343kl3#df5"; // AES 16位的密钥 + String aesEncoded = AesUtils.AESEncrypt(key, data); + String aesDecoded = AesUtils.AESDecrypt(key, aesEncoded); + System.out.println("\naesEncoded: " + aesEncoded + "\naesDecoded: " + aesDecoded); + + /** + * RSA非对称加密 + */ + Map keys = RSAUtils.generateKey("appKey"); + String publicKey = keys.get("publicKey"); + String privateKey = keys.get("privateKey"); + + String rsaEncoded = RSAUtils.publicEncrypt(publicKey, data); + String rsaDecoded = RSAUtils.privateDecrypt(privateKey, rsaEncoded); + System.out.println("\nrsaEncoded: " + rsaEncoded + "\nrsaDecoded: " + rsaDecoded); + + String rsaEncodedBySegment = RSAUtils.publicEncryptBySegment(publicKey, data); + String rsaDecodedBySegment = RSAUtils.privateDecryptBySegment(privateKey, rsaEncodedBySegment); + System.out.println("\nrsaEncodedBySegment: " + rsaEncodedBySegment + "\nrsaDecodedBySegment: " + rsaDecodedBySegment); + + /** + * Hex加密 + */ + String hexEncoded = HexUtils.byte2hex(data.getBytes(UTF8)); + String hexDecoded = new String(HexUtils.hex2byte(hexEncoded), UTF8); + System.out.println("\nhexEncoded: " + hexEncoded + "\nhexDecoded: " + hexDecoded); + + /** + * 数字签名 + */ + String signature = SignUtils.sign(data, privateKey); + boolean result = SignUtils.verify(data, signature, publicKey); + System.out.println("\nsignature: " + signature + "\nresult: " + result); + } + +} + +/** + * AES对称加密 + */ +class AesUtils { + + private static Logger log = LoggerFactory.getLogger(AesUtils.class); + + private static final String AESTYPE = "AES/ECB/PKCS5Padding"; + + public static String AESEncrypt(String keyStr, String plainText) { + byte[] encrypt = null; + try { + SecretKeySpec keySpec = new SecretKeySpec(keyStr.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance(AESTYPE); + cipher.init(Cipher.ENCRYPT_MODE, keySpec); + encrypt = cipher.doFinal(plainText.getBytes()); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + return new String(Base64.encodeToString(encrypt, false)); + } + + public static String AESDecrypt(String keyStr, String encryptData) { + byte[] decrypt = null; + try { + SecretKeySpec key = new SecretKeySpec(keyStr.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance(AESTYPE); + cipher.init(Cipher.DECRYPT_MODE, key); + decrypt = cipher.doFinal(Base64.decode(encryptData)); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + return new String(decrypt); + } +} + +/** + * RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行。 + * 由于非对称加密速度极其缓慢,一般数据量较大时不使用它来加密而是使用对称加密,非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全 + */ +class RSAUtils { + + // RSA最大加密明文大小 + private static final int MAX_ENCRYPT_BLOCK = 117; + // RSA最大解密密文大小,分段时不是最大会报错 Caused by: javax.crypto.IllegalBlockSizeException: + // Data must not be longer than 117 bytes + private static final int MAX_DECRYPT_BLOCK = 128; + + private static final String UTF8 = "UTF-8"; + + private static final String RSA_ALGORITHM = "RSA"; + + private static Logger log = LoggerFactory.getLogger(AesUtils.class); + + public static String publicEncrypt(String strPublicKey, String content) throws IOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException { + byte[] keyBytes = base64Decode(strPublicKey); + byte[] encryptData = publicEncrypt(getPublicKey(keyBytes), content.getBytes(UTF8)); + return base64Encode(encryptData); + } + + public static byte[] publicEncrypt(PublicKey publicKey, byte[] content) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { + if (publicKey == null) { + throw new IllegalArgumentException("加密公钥为空"); + } + Cipher cipher = Cipher.getInstance(RSA_ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + return cipher.doFinal(content); + } + + public static String privateDecrypt(String strPrivateKey, String encryptData) throws IOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException { + byte[] keyBytes = base64Decode(strPrivateKey); + byte[] content = privateDecrypt(getPrivateKey(keyBytes), base64Decode(encryptData)); + return new String(content, UTF8); + } + + public static byte[] privateDecrypt(PrivateKey privateKey, byte[] encryptData) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { + if (privateKey == null) { + throw new IllegalArgumentException("解密私钥为空"); + } + Cipher cipher = Cipher.getInstance(RSA_ALGORITHM); + cipher.init(Cipher.DECRYPT_MODE, privateKey); + return cipher.doFinal(encryptData); + } + + // 生成appkey对应的公钥,私钥 + public static Map generateKey(String appKey) { + try { + KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM); + kpg.initialize(1024); + KeyPair keyPair = kpg.genKeyPair(); + String publicKey = base64Encode(keyPair.getPublic().getEncoded()); + String privateKey = base64Encode(keyPair.getPrivate().getEncoded()); + Map map = new HashMap(); + map.put("publicKey", publicKey); + map.put("privateKey", privateKey); + System.out.println(map); + return map; + } catch (Exception e) { + log.error(appKey + "生成加密异常!"); + } + return null; + } + + public static PublicKey getPublicKey(byte[] keyBytes) throws InvalidKeySpecException, NoSuchAlgorithmException { + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); + KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); + return keyFactory.generatePublic(keySpec); + } + + public static PrivateKey getPrivateKey(byte[] keyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException { + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); + KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); + return keyFactory.generatePrivate(keySpec); + } + + private static String base64Encode(byte[] data) { + if (data == null) + return ""; + return Base64.encodeToString(data, false); + } + + private static byte[] base64Decode(String base64String) throws IOException { + if (base64String == null) + return new byte[] {}; + return Base64.decode(base64String); + } + + // 公钥加密,加密参数过长,采用分段方式 + public static String publicEncryptBySegment(String strPublicKey, String content) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, IOException, InvalidKeySpecException { + byte[] keyBytes = base64Decode(strPublicKey); + PublicKey publicKey = getPublicKey(keyBytes); + if (publicKey == null) { + throw new IllegalArgumentException("加密公钥为空"); + } + Cipher cipher = Cipher.getInstance(RSA_ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + return base64Encode(doFinalBySegment(cipher, content.getBytes(UTF8), MAX_ENCRYPT_BLOCK)); + } + + // 私钥解密,解密参数过长,采用分段方式 + public static String privateDecryptBySegment(String strPrivateKey, String content) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException, IOException, InvalidKeyException { + byte[] keyBytes = base64Decode(strPrivateKey); + PrivateKey privateKey = getPrivateKey(keyBytes); + if (privateKey == null) { + throw new IllegalArgumentException("解密私钥为空"); + } + Cipher cipher = Cipher.getInstance(RSA_ALGORITHM); + cipher.init(Cipher.DECRYPT_MODE, privateKey); + return new String(doFinalBySegment(cipher, base64Decode(content), MAX_DECRYPT_BLOCK), UTF8); + } + + public static byte[] doFinalBySegment(Cipher cipher, byte[] data, int segmentSize) throws BadPaddingException, IllegalBlockSizeException, IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (int i = 0; i < data.length; i += segmentSize) { + byte[] result = cipher.doFinal(ArrayUtils.subarray(data, i, i + segmentSize)); + out.write(result); + } + return out.toByteArray(); + } +} + +/** + * 数字摘要:采用单项Hash函数将需要加密的明文“摘要”成一串固定长度(128位)的密文,又称数字指纹 + * 数字签名:对传送数据生成摘要并使用私钥进行加密,遵循私钥签名,公钥验证的方式 + * 1.为了保证http请求数据的安全性和防篡改性。我们通常要对请求参数进行一些加密。 http请求参数: + * (1)appkey:合作方平台标识,接口协议中通常会提供一个appKey作为唯一的标识。 (2)appSecret:作为接入密钥。 + * (3)time:Unix时间戳(10位) 2.对请求参数生成签名 sign = md5(待签名字符串) 待签名字符串为: + * 将参数按参数名排序,拼接成键值对,如appKey=test_id&appSecret=A272ADAA3637&time=1423212323&username=lily + * 3.将明文参数和签名一起发送给对方 + * appKey=test_id&appSecret=A272ADAA3637&time=1423212323&username=lily&sign=签名串 + */ +class SignUtils { + + private static final String MD5_ALGORITHM = "MD5"; + private static final String SIGNATURE_ALGORITHM = "SHA1WithRSA"; + private static final String UTF8 = "UTF-8"; + + public static String sign(String data, String privateKey) throws UnsupportedEncodingException, NoSuchAlgorithmException, SignatureException, InvalidKeySpecException, InvalidKeyException { + byte[] content = data.getBytes(UTF8); + // 先做摘要 + MessageDigest md = MessageDigest.getInstance(MD5_ALGORITHM); + md.update(content); + byte[] digest = md.digest(); + // 进行签名 + Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); + signature.initSign(RSAUtils.getPrivateKey(Base64.decode(privateKey.getBytes()))); + signature.update(digest); + byte[] signByte = signature.sign(); + String signText = Base64.encodeToString(signByte, false); + System.out.println(signText); + return signText; + } + + public static boolean verify(String data, String signText, String publicKey) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { + byte[] content = data.getBytes(UTF8); + // 先做摘要 + MessageDigest md = MessageDigest.getInstance(MD5_ALGORITHM); + md.update(content); + byte[] digest = md.digest(); + // 进行验签 + Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); + signature.initVerify(RSAUtils.getPublicKey(Base64.decode(publicKey.getBytes()))); + signature.update(digest); + boolean result = signature.verify(Base64.decode(signText)); + return result; + } +} + +/** + * Hex加密,hex十六进制和acsii码之间的转换,可用在url参数解决特殊字符的问题,将加密数据再加密成16进制 + */ +class HexUtils { + private static final int INT_VALUE_2 = 2; + private static char[] c = "0123456789ABCDEF".toCharArray(); + + public static String byte2hex(byte[] b) { + if (b == null) { + return null; + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < b.length; i++) { + int v = b[i] & 0xff; + sb.append(c[v / 0x10]).append(c[v % 0x10]); + } + return sb.toString(); + } + + public static byte[] hex2byte(String s) { + if (s == null) { + return null; + } + byte[] b = s.getBytes(); + if ((b.length % INT_VALUE_2) != 0) { + throw new IllegalArgumentException(); + } + byte[] b2 = new byte[b.length / INT_VALUE_2]; + for (int n = 0; n < b.length; n += INT_VALUE_2) { + String item = new String(b, n, INT_VALUE_2); + b2[n / INT_VALUE_2] = (byte) Integer.parseInt(item, 16); + } + return b2; + } +} \ No newline at end of file diff --git a/src/main/java/com/rekoe/utils/EncryptUtil.java b/src/main/java/com/rekoe/utils/EncryptUtil.java index 9a400e0..6261b9c 100644 --- a/src/main/java/com/rekoe/utils/EncryptUtil.java +++ b/src/main/java/com/rekoe/utils/EncryptUtil.java @@ -1,21 +1,15 @@ package com.rekoe.utils; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -import org.nutz.log.Log; -import org.nutz.log.Logs; import org.nutz.repo.Base64; +import cn.hutool.crypto.digest.DigestAlgorithm; +import cn.hutool.crypto.digest.DigestUtil; + /** * 加密工具 */ public class EncryptUtil { - private final static Log log = Logs.get(); - /** - * - */ private static final String cvt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz0123456789#@$"; /** @@ -26,8 +20,7 @@ public class EncryptUtil { /** * 加密 * - * @param str - * 明文 + * @param str 明文 * @return 密文 */ public static String encrypt(String str) { @@ -63,16 +56,10 @@ public class EncryptUtil { return ret.toString(); } - public static void main(String[] args) { - String str = "abc"; - System.out.println(encrypt(str)); - System.out.println(decrypt(encrypt(str))); - } /** * 解密 * - * @param str - * 密文 + * @param str 密文 * @return 明文 */ public static String decrypt(String str) { @@ -111,17 +98,11 @@ public class EncryptUtil { /** * apache SHA1 加密 * - * @param str - * 明文 + * @param str 明文 * @return 密文 */ public static String encriptSHA1(String str) { - try { - return Base64.encodeToString(MessageDigest.getInstance("SHA1").digest(str.getBytes()), false); - } catch (NoSuchAlgorithmException e) { - log.error(e); - throw new RuntimeException(e); - } + return Base64.encodeToString(DigestUtil.digester(DigestAlgorithm.SHA1).digest(str), false); } }