me.j360.dubbo.modules.util.text.HashUtil.java Source code

Java tutorial

Introduction

Here is the source code for me.j360.dubbo.modules.util.text.HashUtil.java

Source

/*******************************************************************************
 * 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();
    }
}