Java 操作 SHA1 加密和解密
一、引入依赖包
Maven
<dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.11</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.8.1</version> </dependency>
Gradle
compile('org.apache.commons:commons-lang3:3.8.1') compile('commons-codec:commons-codec:1.11')
二、编写 Java 代码实战
新建 secrity 包放入 Digests.java
、Encodes.java
和 Exceptions.java
工具类
Digests.java
package com.example.utils.secrity; import org.apache.commons.lang3.Validate; import java.io.IOException; import java.io.InputStream; import java.security.GeneralSecurityException; import java.security.MessageDigest; import java.security.SecureRandom; public class Digests { private static final String SHA1 = "SHA-1"; private static final String MD5 = "MD5"; private static SecureRandom random = new SecureRandom(); public Digests() { } public static byte[] sha1(byte[] input) { return digest(input, "SHA-1", (byte[])null, 1); } public static byte[] sha1(byte[] input, byte[] salt) { return digest(input, "SHA-1", salt, 1); } public static byte[] sha1(byte[] input, byte[] salt, int iterations) { return digest(input, "SHA-1", salt, iterations); } private static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) { try { MessageDigest digest = MessageDigest.getInstance(algorithm); if (salt != null) { digest.update(salt); } byte[] result = digest.digest(input); for(int i = 1; i < iterations; ++i) { digest.reset(); result = digest.digest(result); } return result; } catch (GeneralSecurityException var7) { throw Exceptions.unchecked(var7); } } public static byte[] generateSalt(int numBytes) { Validate.isTrue(numBytes > 0, "numBytes argument must be a positive integer (1 or larger)", (long)numBytes); byte[] bytes = new byte[numBytes]; random.nextBytes(bytes); return bytes; } public static byte[] md5(InputStream input) throws IOException { return digest(input, "MD5"); } public static byte[] sha1(InputStream input) throws IOException { return digest(input, "SHA-1"); } private static byte[] digest(InputStream input, String algorithm) throws IOException { try { MessageDigest messageDigest = MessageDigest.getInstance(algorithm); int bufferLength = 8192; byte[] buffer = new byte[bufferLength]; for(int read = input.read(buffer, 0, bufferLength); read > -1; read = input.read(buffer, 0, bufferLength)) { messageDigest.update(buffer, 0, read); } return messageDigest.digest(); } catch (GeneralSecurityException var6) { throw Exceptions.unchecked(var6); } } }
Encodes.java
package com.example.utils.secrity; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.tomcat.util.codec.binary.Base64; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; public class Encodes { private static final String DEFAULT_URL_ENCODING = "UTF-8"; private static final char[] BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray(); public Encodes() { } public static String encodeHex(byte[] input) { return Hex.encodeHexString(input); } public static byte[] decodeHex(String input) { try { return Hex.decodeHex(input.toCharArray()); } catch (DecoderException var2) { throw Exceptions.unchecked(var2); } } public static String encodeBase64(byte[] input) { return Base64.encodeBase64String(input); } public static String encodeUrlSafeBase64(byte[] input) { return Base64.encodeBase64URLSafeString(input); } public static byte[] decodeBase64(String input) { return Base64.decodeBase64(input); } public static String encodeBase62(byte[] input) { char[] chars = new char[input.length]; for (int i = 0; i < input.length; ++i) { chars[i] = BASE62[(input[i] & 255) % BASE62.length]; } return new String(chars); } public static String escapeHtml(String html) { return StringEscapeUtils.escapeHtml4(html); } public static String unescapeHtml(String htmlEscaped) { return StringEscapeUtils.unescapeHtml4(htmlEscaped); } public static String escapeXml(String xml) { return StringEscapeUtils.escapeXml(xml); } public static String unescapeXml(String xmlEscaped) { return StringEscapeUtils.unescapeXml(xmlEscaped); } public static String urlEncode(String part) { try { return URLEncoder.encode(part, "UTF-8"); } catch (UnsupportedEncodingException var2) { throw Exceptions.unchecked(var2); } } public static String urlDecode(String part) { try { return URLDecoder.decode(part, "UTF-8"); } catch (UnsupportedEncodingException var2) { throw Exceptions.unchecked(var2); } } }
Exceptions.java
package com.example.utils.secrity; import java.io.PrintWriter; import java.io.StringWriter; public class Exceptions { public Exceptions() { } public static RuntimeException unchecked(Throwable ex) { return ex instanceof RuntimeException ? (RuntimeException) ex : new RuntimeException(ex); } public static String getStackTraceAsString(Throwable ex) { StringWriter stringWriter = new StringWriter(); ex.printStackTrace(new PrintWriter(stringWriter)); return stringWriter.toString(); } public static String getErrorMessageWithNestedException(Throwable ex) { Throwable nestedException = ex.getCause(); return ex.getMessage() + " nested exception is " + nestedException.getClass().getName() + ":" + nestedException.getMessage(); } public static Throwable getRootCause(Throwable ex) { Throwable cause; while ((cause = ex.getCause()) != null) { ex = cause; } return ex; } public static boolean isCausedBy(Exception ex, Class... causeExceptionClasses) { for (Object cause = ex; cause != null; cause = ((Throwable) cause).getCause()) { Class[] arr$ = causeExceptionClasses; int len$ = causeExceptionClasses.length; for (int i$ = 0; i$ < len$; ++i$) { Class<? extends Exception> causeClass = arr$[i$]; if (causeClass.isInstance(cause)) { return true; } } } return false; } }
三、测试
新建 EncryptSha1Util.java
package com.example.utils; import com.example.utils.secrity.Digests; import com.example.utils.secrity.Encodes; /** * HexSHA1 散列加密解密(不可逆) * * 此处演示的盐值为 加密密码的前16位字符 */ public class EncryptSha1Util { public static final String HASH_ALGORITHM = "SHA-1"; public static final int HASH_INTERATIONS = 1024; public static final int SALT_SIZE = 8; /** * @param plainPassword * @return password 加密密码(生成安全的密码,生成随机的16位salt并经过1024次 sha-1 hash) */ public static String entryptPassword(String plainPassword) { byte[] salt = Digests.generateSalt(SALT_SIZE); byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS); return Encodes.encodeHex(salt) + Encodes.encodeHex(hashPassword); } /** * @param plainPassword * @param password * @return boolean 解密判断密码是否正确 */ public static boolean validatePassword(String plainPassword, String password) { byte[] salt = Encodes.decodeHex(password.substring(0, 16)); byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS); return password.equals(Encodes.encodeHex(salt) + Encodes.encodeHex(hashPassword)); } public static void main(String[] args) { String pwd = entryptPassword("Chengxumiao"); System.out.println(pwd); System.out.println(validatePassword("Chengxumiao", pwd)); } }
四、小结
如果你的项目中引用到了,如下两个包,那么上面的创建 Digests.java、Encodes.java 和 Exceptions.java 步骤即可省略了。
这是因为,这三个java类的内容,就是在下面的两个包中,拷贝出来的。
<dependency> <groupId>io.springside</groupId> <artifactId>springside-core</artifactId> <version>4.3.0-RELEASE</version> </dependency> <dependency> <groupId>io.springside</groupId> <artifactId>springside-utils</artifactId> <version>4.3.0-RELEASE</version> </dependency>