Java tutorial
/******************************************************************************* * Copyright (c) 2005, 2014 springside.github.io * * Licensed under the Apache License, Version 2.0 (the "License"); *******************************************************************************/ package me.j360.dubbo.modules.util.text; import com.google.common.hash.Hashing; import me.j360.dubbo.modules.util.base.annotation.NotNull; import me.j360.dubbo.modules.util.base.annotation.Nullable; import org.apache.commons.lang3.Validate; import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.zip.CRC32; /** * ???Hash * * 1.SHA-1, , byte[](?Encodes?Hex, Base64) * * ThreadLocalMessageDigest(from ElasticSearch) * * ?salt. * * MD5, ?Checksum?. * * 2.crc32, murmur32?, , int. * * crc32JDK, murmurhashguava * * @author calvin */ public class HashUtil { public static final int MURMUR_SEED = 1318007700; // ThreadLocal?MessageDigest private static ThreadLocal<MessageDigest> createThreadLocalMessageDigest(final String digest) { return new ThreadLocal<MessageDigest>() { @Override protected MessageDigest initialValue() { try { return MessageDigest.getInstance(digest); } catch (NoSuchAlgorithmException e) { throw new RuntimeException( "unexpected exception creating MessageDigest instance for [" + digest + "]", e); } } }; } private static final ThreadLocal<MessageDigest> MD5_DIGEST = createThreadLocalMessageDigest("MD5"); private static final ThreadLocal<MessageDigest> SHA_1_DIGEST = createThreadLocalMessageDigest("SHA-1"); private static SecureRandom random = new SecureRandom(); ////////////////// SHA1 /////////////////// /** * sha1. */ public static byte[] sha1(@NotNull byte[] input) { return digest(input, get(SHA_1_DIGEST), null, 1); } /** * sha1, ?UTF8. */ public static byte[] sha1(@NotNull String input) { return digest(input.getBytes(Charsets.UTF_8), get(SHA_1_DIGEST), null, 1); } /** * sha1salt. */ public static byte[] sha1(@NotNull byte[] input, @Nullable byte[] salt) { return digest(input, get(SHA_1_DIGEST), salt, 1); } /** * sha1salt. */ public static byte[] sha1(@NotNull String input, @Nullable byte[] salt) { return digest(input.getBytes(Charsets.UTF_8), get(SHA_1_DIGEST), salt, 1); } /** * sha1salt. * * @see #generateSalt(int) */ public static byte[] sha1(@NotNull byte[] input, @Nullable byte[] salt, int iterations) { return digest(input, get(SHA_1_DIGEST), salt, iterations); } /** * sha1salt. * * @see #generateSalt(int) */ public static byte[] sha1(@NotNull String input, @Nullable byte[] salt, int iterations) { return digest(input.getBytes(Charsets.UTF_8), get(SHA_1_DIGEST), salt, iterations); } private static MessageDigest get(ThreadLocal<MessageDigest> messageDigest) { MessageDigest instance = messageDigest.get(); instance.reset(); return instance; } /** * , ?md5sha1. */ private static byte[] digest(@NotNull byte[] input, MessageDigest digest, byte[] salt, int iterations) { // ? if (salt != null) { digest.update(salt); } // byte[] result = digest.digest(input); // >1 for (int i = 1; i < iterations; i++) { digest.reset(); result = digest.digest(result); } return result; } /** * SecureRandom??byte[]salt. * * @param numBytes salt? */ public static byte[] generateSalt(int numBytes) { Validate.isTrue(numBytes > 0, "numBytes argument must be a positive integer (1 or larger)", numBytes); byte[] bytes = new byte[numBytes]; random.nextBytes(bytes); return bytes; } /** * sha1. */ public static byte[] sha1File(InputStream input) throws IOException { return digestFile(input, get(SHA_1_DIGEST)); } /** * md5?MD5. */ public static byte[] md5File(InputStream input) throws IOException { return digestFile(input, get(MD5_DIGEST)); } private static byte[] digestFile(InputStream input, MessageDigest messageDigest) throws IOException { int bufferLength = 8 * 1024; byte[] buffer = new byte[bufferLength]; int read = input.read(buffer, 0, bufferLength); while (read > -1) { messageDigest.update(buffer, 0, read); read = input.read(buffer, 0, bufferLength); } return messageDigest.digest(); } ////////////////// JDKCRC32 /////////////////// /** * crc32int, ?. * * Guavacrc32, longJDK */ public static int crc32AsInt(@NotNull String input) { return crc32AsInt(input.getBytes(Charsets.UTF_8)); } /** * crc32int, ?. * * Guavacrc32, longJDK */ public static int crc32AsInt(@NotNull byte[] input) { CRC32 crc32 = new CRC32(); crc32.update(input); // CRC32 ? 32bit intCheckSum??long?? return (int) crc32.getValue(); } /** * crc32php64bitlong * * Guavacrc32, longJDK */ public static long crc32AsLong(@NotNull String input) { return crc32AsLong(input.getBytes(Charsets.UTF_8)); } /** * crc32php64bitlong * * Guavacrc32, longJDK */ public static long crc32AsLong(@NotNull byte[] input) { CRC32 crc32 = new CRC32(); crc32.update(input); return crc32.getValue(); } ////////////////// GuavaMurMurHash /////////////////// /** * murmur32, ? */ public static int murmur32AsInt(@NotNull byte[] input) { return Hashing.murmur3_32(MURMUR_SEED).hashBytes(input).asInt(); } /** * murmur32, ? */ public static int murmur32AsInt(@NotNull String input) { return Hashing.murmur3_32(MURMUR_SEED).hashString(input, Charsets.UTF_8).asInt(); } /** * murmur128, ? */ public static long murmur128AsLong(@NotNull byte[] input) { return Hashing.murmur3_128(MURMUR_SEED).hashBytes(input).asLong(); } /** * murmur128, ? */ public static long murmur128AsLong(@NotNull String input) { return Hashing.murmur3_128(MURMUR_SEED).hashString(input, Charsets.UTF_8).asLong(); } }