Java 实现 SHA

作者: 又语 | 来源:发表于2020-04-09 19:09 被阅读0次

    本文介绍 Java 语言实现 SHA Hash 的多种方法。


    目录

    • SHA 简介
    • 实现方法
      • 基于 Java API
      • 基于 Apache Commons
      • 基于 Google Guava
      • 基于 Bouncy Castle
      • 单元测试

    SHA 简介

    SHA(Secure Hash Algorithm,安全散列算法),至今为止共出现过 4 代。

    • SHA-0,于 1993 年发布,称作安全散列标准(Secure Hash Standard),FIPS PUB 180。
    • SHA-1,于 1995 年发布,与 SHA-0 相比只在压缩函数的消息转换部分差了一个比特的循环位移,根据 NSA 的说法,这修正了一个在原始算法中会降低散列安全性的弱点。SHA-0 和 SHA-1 的弱点相继被攻破,已经不再安全。
    • SHA-2,于 2001 年发布,是 SHA-1 的后继者,其下又可再分为 6 个不同的算法标准,包括:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。
    • SHA-3,于 2015 年发布,之前名为 Keccak,是一个加密散列算法。SHA-3提供了一种不同的方法使得在某些硬件实现领域更加快速。SHA-3 的出现不是为了取代 SHA-2,因为在 SHA-3 发布时 SHA-2 并没有出现明显的弱点,尽管目前已有更加安全的算法。

    实现方法

    SHA 算法实现都比较相似,下面以 SHA-256 的实现为例,SHA-256 算法可以生成一个几乎唯一、固定 256 位(32 字节)的哈希值。
    需要注意的是,因为 SHA3 在 2015 年才发布,因此直至 JDK 9 版本后才内置了此算法实现,本文未给出此算法实现示例。

    基于 Java API
    package tutorial.java.util;
    
    import java.nio.charset.StandardCharsets;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    public class Sha256Utils {
    
        public static String sha256(String original) throws NoSuchAlgorithmException {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            byte[] hash = messageDigest.digest(original.getBytes(StandardCharsets.UTF_8));
            return bytesToHex(hash);
        }
    
        /**
         * 自定义字节到十六进制转换器来获取十六进制的哈希值
         */
        private static String bytesToHex(byte[] hash) {
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        }
    }
    
    基于 Apache Commons
    1. 添加 Apache Commons Codec 依赖
    <dependency>
        <groupId>commons-codec</groupId>
        <artifactId>commons-codec</artifactId>
        <version>1.14</version>
    </dependency>
    
    1. 使用 org.apache.commons.codec.digest.DigestUtils 实现 SHA-256 Hash
    package tutorial.java.util;
    
    import org.apache.commons.codec.digest.DigestUtils;
    
    public class Sha256Utils {
    
        public static String sha256(String original) {
            return DigestUtils.sha256Hex(original);
        }
    }
    
    基于 Google Guava
    1. 添加 Google Guava 依赖
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>28.2-jre</version>
    </dependency>
    

    使用 com.google.common.hash.Hashing 实现 SHA-256 Hash

    package tutorial.java.util;
    
    import com.google.common.hash.Hashing;
    
    import java.nio.charset.StandardCharsets;
    
    public class Sha256Utils {
    
        public static String sha256(String original) {
            return Hashing.sha256()
                    .hashString(original, StandardCharsets.UTF_8)
                    .toString();
        }
    }
    
    基于 Bouncy Castle
    1. 添加 Bouncy Castle 依赖
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.65</version>
    </dependency>
    
    1. 同 Java API 类似,只是最后一步将字节转换为十六进制使用了 org.bouncycastle.util.encoders.Hex 实现。
    package tutorial.java.util;
    
    import org.bouncycastle.util.encoders.Hex;
    
    import java.nio.charset.StandardCharsets;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    public class Sha256Utils {
    
        public static String sha256(String original) throws NoSuchAlgorithmException {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(original.getBytes(StandardCharsets.UTF_8));
            return new String(Hex.encode(hash));
        }
    }
    
    单元测试

    适用于以上所有示例代码。

    package tutorial.java.util;
    
    import org.junit.Assert;
    import org.junit.Test;
    
    import java.security.NoSuchAlgorithmException;
    
    public class Sha256UtilsTest {
    
        @Test
        public void testSha256() throws NoSuchAlgorithmException {
            String original = "ABCDEFG";
            String expected = "e9a92a2ed0d53732ac13b031a27b071814231c8633c9f41844ccba884d482b16";
            Assert.assertEquals(expected, Sha256Utils.sha256(original));
        }
    }
    

    相关文章

      网友评论

        本文标题:Java 实现 SHA

        本文链接:https://www.haomeiwen.com/subject/rrlhmhtx.html