From c18d09cd33c44bfe7fbd739d98ba0fb341b569cc Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Sat, 28 Mar 2020 16:48:04 +0530 Subject: [PATCH 1/2] JAVA-623: Moved 3 articles from core-java-security to security-2 --- .../core-java-security/README.md | 5 +- core-java-modules/core-java-security/pom.xml | 15 -- .../baeldung/hashing/DigestAlgorithms.java | 9 -- .../baeldung/hashing/Keccak256Hashing.java | 30 ---- .../com/baeldung/hashing/SHA256Hashing.java | 39 ----- .../com/baeldung/hashing/SHA3Hashing.java | 45 ------ .../com/baeldung/hashing/SHACommonUtils.java | 16 -- .../passwordhashing/PBKDF2Hasher.java | 149 ------------------ .../passwordhashing/SHA512Hasher.java | 35 ---- .../passwordhashing/SimplePBKDF2Hasher.java | 18 --- .../hashing/Keccak256HashingUnitTest.java | 22 --- .../hashing/SHA256HashingUnitTest.java | 35 ---- .../baeldung/hashing/SHA3HashingUnitTest.java | 38 ----- .../baeldung/java/md5/JavaMD5UnitTest.java | 75 --------- .../passwordhashing/PBKDF2HasherUnitTest.java | 41 ----- .../passwordhashing/SHA512HasherUnitTest.java | 70 -------- .../src/test/resources/test_md5.txt | 1 - 17 files changed, 2 insertions(+), 641 deletions(-) delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java delete mode 100644 core-java-modules/core-java-security/src/test/resources/test_md5.txt diff --git a/core-java-modules/core-java-security/README.md b/core-java-modules/core-java-security/README.md index ff9b1eef14..83b12793b5 100644 --- a/core-java-modules/core-java-security/README.md +++ b/core-java-modules/core-java-security/README.md @@ -3,17 +3,16 @@ This module contains articles about core Java Security ### Relevant Articles: -- [MD5 Hashing in Java](http://www.baeldung.com/java-md5) + - [Guide to the Cipher Class](http://www.baeldung.com/java-cipher-class) - [Introduction to SSL in Java](http://www.baeldung.com/java-ssl) - [Java KeyStore API](http://www.baeldung.com/java-keystore) - [Encrypting and Decrypting Files in Java](http://www.baeldung.com/java-cipher-input-output-stream) -- [Hashing a Password in Java](https://www.baeldung.com/java-password-hashing) - [SSL Handshake Failures](https://www.baeldung.com/java-ssl-handshake-failures) -- [SHA-256 and SHA3-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java) - [Enabling TLS v1.2 in Java 7](https://www.baeldung.com/java-7-tls-v12) - [The Java SecureRandom Class](https://www.baeldung.com/java-secure-random) - [An Introduction to Java SASL](https://www.baeldung.com/java-sasl) - [A Guide to Java GSS API](https://www.baeldung.com/java-gss) - [Intro to the Java SecurityManager](https://www.baeldung.com/java-security-manager) +- More articles: [[next -->]](/core-java-modules/core-java-security-2) diff --git a/core-java-modules/core-java-security/pom.xml b/core-java-modules/core-java-security/pom.xml index a46c2e2d40..96024a73a1 100644 --- a/core-java-modules/core-java-security/pom.xml +++ b/core-java-modules/core-java-security/pom.xml @@ -24,24 +24,9 @@ ${assertj-core.version} test - - - commons-codec - commons-codec - ${commons-codec.version} - - - org.bouncycastle - bcprov-jdk15on - ${bouncycastle.version} - - - 1.60 - 1.11 - 3.10.0 diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java deleted file mode 100644 index 94dd22ff4b..0000000000 --- a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.baeldung.hashing; - -public class DigestAlgorithms { - - public static final String SHA3_256 = "SHA3-256"; - public static final String SHA_256 = "SHA-256"; - public static final String KECCAK_256 = "Keccak-256"; - -} diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java deleted file mode 100644 index 19fc4cf059..0000000000 --- a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.hashing; - -import org.bouncycastle.jcajce.provider.digest.Keccak; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.util.encoders.Hex; - -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.Security; - -import static com.baeldung.hashing.DigestAlgorithms.KECCAK_256; -import static com.baeldung.hashing.SHACommonUtils.bytesToHex; - -public class Keccak256Hashing { - - public static String hashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException { - Security.addProvider(new BouncyCastleProvider()); - final MessageDigest digest = MessageDigest.getInstance(KECCAK_256); - final byte[] encodedhash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); - return bytesToHex(encodedhash); - } - - public static String hashWithBouncyCastle(final String originalString) { - Keccak.Digest256 digest256 = new Keccak.Digest256(); - byte[] hashbytes = digest256.digest(originalString.getBytes(StandardCharsets.UTF_8)); - return new String(Hex.encode(hashbytes)); - } - -} diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java deleted file mode 100644 index ec008cebab..0000000000 --- a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.baeldung.hashing; - -import com.google.common.hash.Hashing; -import org.apache.commons.codec.digest.DigestUtils; -import org.bouncycastle.util.encoders.Hex; - -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -import static com.baeldung.hashing.DigestAlgorithms.SHA_256; -import static com.baeldung.hashing.SHACommonUtils.bytesToHex; - -public class SHA256Hashing { - - public static String HashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException { - final MessageDigest digest = MessageDigest.getInstance(SHA_256); - final byte[] encodedhash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); - return bytesToHex(encodedhash); - } - - public static String hashWithGuava(final String originalString) { - final String sha256hex = Hashing.sha256().hashString(originalString, StandardCharsets.UTF_8).toString(); - return sha256hex; - } - - public static String HashWithApacheCommons(final String originalString) { - final String sha256hex = DigestUtils.sha256Hex(originalString); - return sha256hex; - } - - public static String HashWithBouncyCastle(final String originalString) throws NoSuchAlgorithmException { - final MessageDigest digest = MessageDigest.getInstance(SHA_256); - final byte[] hash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); - final String sha256hex = new String(Hex.encode(hash)); - return sha256hex; - } - -} diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java deleted file mode 100644 index eb363205b1..0000000000 --- a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.baeldung.hashing; - -import com.google.common.hash.Hashing; -import org.apache.commons.codec.digest.DigestUtils; -import org.bouncycastle.crypto.digests.SHA3Digest; -import org.bouncycastle.jcajce.provider.digest.SHA3; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.util.encoders.Hex; - -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.Security; - -import static com.baeldung.hashing.DigestAlgorithms.SHA3_256; -import static com.baeldung.hashing.SHACommonUtils.bytesToHex; - -public class SHA3Hashing { - - /* works with JDK9+ only */ - public static String hashWithJavaMessageDigestJDK9(final String originalString) throws NoSuchAlgorithmException { - final MessageDigest digest = MessageDigest.getInstance(SHA3_256); - final byte[] hashbytes = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); - return bytesToHex(hashbytes); - } - - public static String hashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException { - Security.addProvider(new BouncyCastleProvider()); - final MessageDigest digest = MessageDigest.getInstance(SHA3_256); - final byte[] hashbytes = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); - return bytesToHex(hashbytes); - } - - /* works with JDK9+ only */ - public static String hashWithApacheCommonsJDK9(final String originalString) { - return new DigestUtils(SHA3_256).digestAsHex(originalString); - } - - public static String hashWithBouncyCastle(final String originalString) { - SHA3.Digest256 digest256 = new SHA3.Digest256(); - byte[] hashbytes = digest256.digest(originalString.getBytes(StandardCharsets.UTF_8)); - return new String(Hex.encode(hashbytes)); - } - -} diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java deleted file mode 100644 index 0f28408083..0000000000 --- a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.baeldung.hashing; - -class SHACommonUtils { - - public static String bytesToHex(byte[] hash) { - StringBuffer hexString = new StringBuffer(); - for (byte h : hash) { - String hex = Integer.toHexString(0xff & h); - if (hex.length() == 1) - hexString.append('0'); - hexString.append(hex); - } - return hexString.toString(); - } - -} diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java deleted file mode 100644 index e2259e4249..0000000000 --- a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.baeldung.passwordhashing; - -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.KeySpec; -import java.util.Arrays; -import java.util.Base64; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; - -/** - * Hash passwords for storage, and test passwords against password tokens. - * - * Instances of this class can be used concurrently by multiple threads. - * - * @author erickson - * @see StackOverflow - */ -public final class PBKDF2Hasher -{ - - /** - * Each token produced by this class uses this identifier as a prefix. - */ - public static final String ID = "$31$"; - - /** - * The minimum recommended cost, used by default - */ - public static final int DEFAULT_COST = 16; - - private static final String ALGORITHM = "PBKDF2WithHmacSHA1"; - - private static final int SIZE = 128; - - private static final Pattern layout = Pattern.compile("\\$31\\$(\\d\\d?)\\$(.{43})"); - - private final SecureRandom random; - - private final int cost; - - public PBKDF2Hasher() - { - this(DEFAULT_COST); - } - - /** - * Create a password manager with a specified cost - * - * @param cost the exponential computational cost of hashing a password, 0 to 30 - */ - public PBKDF2Hasher(int cost) - { - iterations(cost); /* Validate cost */ - this.cost = cost; - this.random = new SecureRandom(); - } - - private static int iterations(int cost) - { - if ((cost < 0) || (cost > 30)) - throw new IllegalArgumentException("cost: " + cost); - return 1 << cost; - } - - /** - * Hash a password for storage. - * - * @return a secure authentication token to be stored for later authentication - */ - public String hash(char[] password) - { - byte[] salt = new byte[SIZE / 8]; - random.nextBytes(salt); - byte[] dk = pbkdf2(password, salt, 1 << cost); - byte[] hash = new byte[salt.length + dk.length]; - System.arraycopy(salt, 0, hash, 0, salt.length); - System.arraycopy(dk, 0, hash, salt.length, dk.length); - Base64.Encoder enc = Base64.getUrlEncoder().withoutPadding(); - return ID + cost + '$' + enc.encodeToString(hash); - } - - /** - * Authenticate with a password and a stored password token. - * - * @return true if the password and token match - */ - public boolean checkPassword(char[] password, String token) - { - Matcher m = layout.matcher(token); - if (!m.matches()) - throw new IllegalArgumentException("Invalid token format"); - int iterations = iterations(Integer.parseInt(m.group(1))); - byte[] hash = Base64.getUrlDecoder().decode(m.group(2)); - byte[] salt = Arrays.copyOfRange(hash, 0, SIZE / 8); - byte[] check = pbkdf2(password, salt, iterations); - int zero = 0; - for (int idx = 0; idx < check.length; ++idx) - zero |= hash[salt.length + idx] ^ check[idx]; - return zero == 0; - } - - private static byte[] pbkdf2(char[] password, byte[] salt, int iterations) - { - KeySpec spec = new PBEKeySpec(password, salt, iterations, SIZE); - try { - SecretKeyFactory f = SecretKeyFactory.getInstance(ALGORITHM); - return f.generateSecret(spec).getEncoded(); - } - catch (NoSuchAlgorithmException ex) { - throw new IllegalStateException("Missing algorithm: " + ALGORITHM, ex); - } - catch (InvalidKeySpecException ex) { - throw new IllegalStateException("Invalid SecretKeyFactory", ex); - } - } - - /** - * Hash a password in an immutable {@code String}. - * - *

Passwords should be stored in a {@code char[]} so that it can be filled - * with zeros after use instead of lingering on the heap and elsewhere. - * - * @deprecated Use {@link #hash(char[])} instead - */ - @Deprecated - public String hash(String password) - { - return hash(password.toCharArray()); - } - - /** - * Authenticate with a password in an immutable {@code String} and a stored - * password token. - * - * @deprecated Use {@link #checkPassword(char[],String)} instead. - * @see #hash(String) - */ - @Deprecated - public boolean checkPassword(String password, String token) - { - return checkPassword(password.toCharArray(), token); - } - -} diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java deleted file mode 100644 index 4f5337f963..0000000000 --- a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.baeldung.passwordhashing; - -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - - -/** A really simple SHA_512 Encryption example. - * - */ -public class SHA512Hasher { - - public String hash(String passwordToHash, byte[] salt){ - String generatedPassword = null; - try { - MessageDigest md = MessageDigest.getInstance("SHA-512"); - md.update(salt); - byte[] bytes = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8)); - StringBuilder sb = new StringBuilder(); - for(int i=0; i< bytes.length ;i++){ - sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1)); - } - generatedPassword = sb.toString(); - } - catch (NoSuchAlgorithmException e){ - e.printStackTrace(); - } - return generatedPassword; - } - - public boolean checkPassword(String hash, String attempt, byte[] salt){ - String generatedHash = hash(attempt, salt); - return hash.equals(generatedHash); - } -} diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java deleted file mode 100644 index 36c9b65070..0000000000 --- a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.baeldung.passwordhashing; - -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; -import java.security.spec.KeySpec; - -/** A really simple SimplePBKDF2 Encryption example. - * - */ -public class SimplePBKDF2Hasher { - - public static String hashSimple(String password, byte[] salt) throws Exception{ - KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128); - SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); - byte[] hash = f.generateSecret(spec).getEncoded(); - return String.valueOf(hash); - } -} diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java deleted file mode 100644 index 9ed35c8834..0000000000 --- a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.hashing; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class Keccak256HashingUnitTest { - - private static String originalValue = "abc123"; - private static String hashedValue = "719accc61a9cc126830e5906f9d672d06eab6f8597287095a2c55a8b775e7016"; - - @Test public void testHashWithJavaMessageDigest() throws Exception { - final String currentHashedValue = Keccak256Hashing.hashWithJavaMessageDigest(originalValue); - assertEquals(hashedValue, currentHashedValue); - } - - @Test public void testHashWithBouncyCastle() { - final String currentHashedValue = Keccak256Hashing.hashWithBouncyCastle(originalValue); - assertEquals(hashedValue, currentHashedValue); - } - -} diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java deleted file mode 100644 index 6bc9ad2cc6..0000000000 --- a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.baeldung.hashing; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class SHA256HashingUnitTest { - - private static String originalValue = "abc123"; - private static String hashedValue = "6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090"; - - @Test - public void testHashWithJavaMessageDigest() throws Exception { - final String currentHashedValue = SHA256Hashing.HashWithJavaMessageDigest(originalValue); - assertEquals(hashedValue, currentHashedValue); - } - - @Test - public void testHashWithGuava() throws Exception { - final String currentHashedValue = SHA256Hashing.hashWithGuava(originalValue); - assertEquals(hashedValue, currentHashedValue); - } - - @Test - public void testHashWithApacheCommans() throws Exception { - final String currentHashedValue = SHA256Hashing.HashWithApacheCommons(originalValue); - assertEquals(hashedValue, currentHashedValue); - } - - @Test - public void testHashWithBouncyCastle() throws Exception { - final String currentHashedValue = SHA256Hashing.HashWithBouncyCastle(originalValue); - assertEquals(hashedValue, currentHashedValue); - } -} \ No newline at end of file diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java deleted file mode 100644 index fffab96405..0000000000 --- a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.baeldung.hashing; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class SHA3HashingUnitTest { - - private static String originalValue = "abc123"; - private static String hashedValue = "f58fa3df820114f56e1544354379820cff464c9c41cb3ca0ad0b0843c9bb67ee"; - - /* works with JDK9+ only */ - //@Test - public void testHashWithJavaMessageDigestJDK9() throws Exception { - final String currentHashedValue = SHA3Hashing.hashWithJavaMessageDigestJDK9(originalValue); - assertEquals(hashedValue, currentHashedValue); - } - - @Test - public void testHashWithJavaMessageDigest() throws Exception { - final String currentHashedValue = SHA3Hashing.hashWithJavaMessageDigest(originalValue); - assertEquals(hashedValue, currentHashedValue); - } - - /* works with JDK9+ only */ - //@Test - public void testHashWithApacheCommonsJDK9() { - final String currentHashedValue = SHA3Hashing.hashWithApacheCommonsJDK9(originalValue); - assertEquals(hashedValue, currentHashedValue); - } - - @Test - public void testHashWithBouncyCastle() { - final String currentHashedValue = SHA3Hashing.hashWithBouncyCastle(originalValue); - assertEquals(hashedValue, currentHashedValue); - } - -} diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java deleted file mode 100644 index 67d6918c09..0000000000 --- a/core-java-modules/core-java-security/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.baeldung.java.md5; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -import javax.xml.bind.DatatypeConverter; - -import org.apache.commons.codec.digest.DigestUtils; -import org.junit.Test; - -import com.google.common.hash.HashCode; -import com.google.common.hash.Hashing; - -public class JavaMD5UnitTest { - - String filename = "src/test/resources/test_md5.txt"; - String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3"; - - String hash = "35454B055CC325EA1AF2126E27707052"; - String password = "ILoveJava"; - - @Test - public void givenPassword_whenHashing_thenVerifying() throws NoSuchAlgorithmException { - String hash = "35454B055CC325EA1AF2126E27707052"; - String password = "ILoveJava"; - - MessageDigest md = MessageDigest.getInstance("MD5"); - md.update(password.getBytes()); - byte[] digest = md.digest(); - String myHash = DatatypeConverter.printHexBinary(digest).toUpperCase(); - - assertThat(myHash.equals(hash)).isTrue(); - } - - @Test - public void givenFile_generatingChecksum_thenVerifying() throws NoSuchAlgorithmException, IOException { - String filename = "src/test/resources/test_md5.txt"; - String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3"; - - MessageDigest md = MessageDigest.getInstance("MD5"); - md.update(Files.readAllBytes(Paths.get(filename))); - byte[] digest = md.digest(); - String myChecksum = DatatypeConverter.printHexBinary(digest).toUpperCase(); - - assertThat(myChecksum.equals(checksum)).isTrue(); - } - - @Test - public void givenPassword_whenHashingUsingCommons_thenVerifying() { - String hash = "35454B055CC325EA1AF2126E27707052"; - String password = "ILoveJava"; - - String md5Hex = DigestUtils.md5Hex(password).toUpperCase(); - - assertThat(md5Hex.equals(hash)).isTrue(); - } - - @Test - public void givenFile_whenChecksumUsingGuava_thenVerifying() throws IOException { - String filename = "src/test/resources/test_md5.txt"; - String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3"; - - HashCode hash = com.google.common.io.Files.hash(new File(filename), Hashing.md5()); - String myChecksum = hash.toString().toUpperCase(); - - assertThat(myChecksum.equals(checksum)).isTrue(); - } - -} diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java deleted file mode 100644 index 8e90725c77..0000000000 --- a/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.baeldung.passwordhashing; - -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.*; - - -public class PBKDF2HasherUnitTest { - - private PBKDF2Hasher mPBKDF2Hasher; - - @Before - public void setUp() throws Exception { - mPBKDF2Hasher = new PBKDF2Hasher(); - } - - @Test - public void givenCorrectMessageAndHash_whenAuthenticated_checkAuthenticationSucceeds() throws Exception { - String message1 = "password123"; - - String hash1 = mPBKDF2Hasher.hash(message1.toCharArray()); - - assertTrue(mPBKDF2Hasher.checkPassword(message1.toCharArray(), hash1)); - - } - - @Test - public void givenWrongMessage_whenAuthenticated_checkAuthenticationFails() throws Exception { - String message1 = "password123"; - - String hash1 = mPBKDF2Hasher.hash(message1.toCharArray()); - - String wrongPasswordAttempt = "IamWrong"; - - assertFalse(mPBKDF2Hasher.checkPassword(wrongPasswordAttempt.toCharArray(), hash1)); - - } - - -} \ No newline at end of file diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java deleted file mode 100644 index 3acfb0ba9d..0000000000 --- a/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.baeldung.passwordhashing; - -import org.junit.Before; -import org.junit.Test; - -import java.security.SecureRandom; - -import static org.junit.Assert.*; - -/** - * Created by PhysicsSam on 06-Sep-18. - */ -public class SHA512HasherUnitTest { - - private SHA512Hasher hasher; - private SecureRandom secureRandom; - - @Before - public void setUp() throws Exception { - hasher = new SHA512Hasher(); - secureRandom = new SecureRandom(); - } - - @Test - public void givenSamePasswordAndSalt_whenHashed_checkResultingHashesAreEqual() throws Exception { - - byte[] salt = new byte[16]; - secureRandom.nextBytes(salt); - - String hash1 = hasher.hash("password", salt); - String hash2 = hasher.hash("password", salt); - - assertEquals(hash1, hash2); - - } - - @Test - public void givenSamePasswordAndDifferentSalt_whenHashed_checkResultingHashesNotEqual() throws Exception { - - byte[] salt = new byte[16]; - secureRandom.nextBytes(salt); - String hash1 = hasher.hash("password", salt); - //generate a second salt - byte[] secondSalt = new byte[16]; - String hash2 = hasher.hash("password", secondSalt); - - assertNotEquals(hash1, hash2); - - } - - @Test - public void givenPredefinedHash_whenCorrectAttemptGiven_checkAuthenticationSucceeds() throws Exception { - byte[] salt = new byte[16]; - secureRandom.nextBytes(salt); - - String originalHash = hasher.hash("password123", salt); - - assertTrue(hasher.checkPassword(originalHash, "password123", salt)); - } - - @Test - public void givenPredefinedHash_whenIncorrectAttemptGiven_checkAuthenticationFails() throws Exception { - byte[] salt = new byte[16]; - secureRandom.nextBytes(salt); - - String originalHash = hasher.hash("password123", salt); - - assertFalse(hasher.checkPassword(originalHash, "password124", salt)); - } -} \ No newline at end of file diff --git a/core-java-modules/core-java-security/src/test/resources/test_md5.txt b/core-java-modules/core-java-security/src/test/resources/test_md5.txt deleted file mode 100644 index 95d09f2b10..0000000000 --- a/core-java-modules/core-java-security/src/test/resources/test_md5.txt +++ /dev/null @@ -1 +0,0 @@ -hello world \ No newline at end of file From e2b6b4bc924f860cd2ab7d77ed17ad8e2d969b15 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Sat, 28 Mar 2020 16:48:43 +0530 Subject: [PATCH 2/2] JAVA-623: Moved 3 articles to core-java-security-2 --- .../core-java-security-2/README.md | 8 + .../core-java-security-2/pom.xml | 30 ++++ .../baeldung/hashing/DigestAlgorithms.java | 9 ++ .../baeldung/hashing/Keccak256Hashing.java | 30 ++++ .../com/baeldung/hashing/SHA256Hashing.java | 39 +++++ .../com/baeldung/hashing/SHA3Hashing.java | 45 ++++++ .../com/baeldung/hashing/SHACommonUtils.java | 16 ++ .../passwordhashing/PBKDF2Hasher.java | 149 ++++++++++++++++++ .../passwordhashing/SHA512Hasher.java | 35 ++++ .../passwordhashing/SimplePBKDF2Hasher.java | 18 +++ .../hashing/Keccak256HashingUnitTest.java | 22 +++ .../hashing/SHA256HashingUnitTest.java | 35 ++++ .../baeldung/hashing/SHA3HashingUnitTest.java | 38 +++++ .../baeldung/java/md5/JavaMD5UnitTest.java | 75 +++++++++ .../passwordhashing/PBKDF2HasherUnitTest.java | 41 +++++ .../passwordhashing/SHA512HasherUnitTest.java | 70 ++++++++ .../src/test/resources/test_md5.txt | 1 + 17 files changed, 661 insertions(+) create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/DigestAlgorithms.java create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/Keccak256Hashing.java create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA256Hashing.java create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA3Hashing.java create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHACommonUtils.java create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java create mode 100644 core-java-modules/core-java-security-2/src/test/resources/test_md5.txt diff --git a/core-java-modules/core-java-security-2/README.md b/core-java-modules/core-java-security-2/README.md index c250e24078..2eb21fb77e 100644 --- a/core-java-modules/core-java-security-2/README.md +++ b/core-java-modules/core-java-security-2/README.md @@ -1,3 +1,11 @@ +## Core Java Security + +This module contains articles about core Java Security + ### Relevant Articles: - [Guide To The Java Authentication And Authorization Service (JAAS)](https://www.baeldung.com/java-authentication-authorization-service) +- [MD5 Hashing in Java](http://www.baeldung.com/java-md5) +- [Hashing a Password in Java](https://www.baeldung.com/java-password-hashing) +- [SHA-256 and SHA3-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java) +- More articles: [[<-- prev]](/core-java-modules/core-java-security) diff --git a/core-java-modules/core-java-security-2/pom.xml b/core-java-modules/core-java-security-2/pom.xml index 23f0c5aab9..9315ab4af2 100644 --- a/core-java-modules/core-java-security-2/pom.xml +++ b/core-java-modules/core-java-security-2/pom.xml @@ -16,4 +16,34 @@ ../../parent-java + + + commons-codec + commons-codec + ${commons-codec.version} + + + + org.bouncycastle + bcprov-jdk15on + ${bouncycastle.version} + + + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + + + + 1.60 + 1.11 + + + 3.10.0 + diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/DigestAlgorithms.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/DigestAlgorithms.java new file mode 100644 index 0000000000..94dd22ff4b --- /dev/null +++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/DigestAlgorithms.java @@ -0,0 +1,9 @@ +package com.baeldung.hashing; + +public class DigestAlgorithms { + + public static final String SHA3_256 = "SHA3-256"; + public static final String SHA_256 = "SHA-256"; + public static final String KECCAK_256 = "Keccak-256"; + +} diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/Keccak256Hashing.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/Keccak256Hashing.java new file mode 100644 index 0000000000..19fc4cf059 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/Keccak256Hashing.java @@ -0,0 +1,30 @@ +package com.baeldung.hashing; + +import org.bouncycastle.jcajce.provider.digest.Keccak; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.util.encoders.Hex; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.Security; + +import static com.baeldung.hashing.DigestAlgorithms.KECCAK_256; +import static com.baeldung.hashing.SHACommonUtils.bytesToHex; + +public class Keccak256Hashing { + + public static String hashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException { + Security.addProvider(new BouncyCastleProvider()); + final MessageDigest digest = MessageDigest.getInstance(KECCAK_256); + final byte[] encodedhash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); + return bytesToHex(encodedhash); + } + + public static String hashWithBouncyCastle(final String originalString) { + Keccak.Digest256 digest256 = new Keccak.Digest256(); + byte[] hashbytes = digest256.digest(originalString.getBytes(StandardCharsets.UTF_8)); + return new String(Hex.encode(hashbytes)); + } + +} diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA256Hashing.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA256Hashing.java new file mode 100644 index 0000000000..ec008cebab --- /dev/null +++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA256Hashing.java @@ -0,0 +1,39 @@ +package com.baeldung.hashing; + +import com.google.common.hash.Hashing; +import org.apache.commons.codec.digest.DigestUtils; +import org.bouncycastle.util.encoders.Hex; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import static com.baeldung.hashing.DigestAlgorithms.SHA_256; +import static com.baeldung.hashing.SHACommonUtils.bytesToHex; + +public class SHA256Hashing { + + public static String HashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException { + final MessageDigest digest = MessageDigest.getInstance(SHA_256); + final byte[] encodedhash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); + return bytesToHex(encodedhash); + } + + public static String hashWithGuava(final String originalString) { + final String sha256hex = Hashing.sha256().hashString(originalString, StandardCharsets.UTF_8).toString(); + return sha256hex; + } + + public static String HashWithApacheCommons(final String originalString) { + final String sha256hex = DigestUtils.sha256Hex(originalString); + return sha256hex; + } + + public static String HashWithBouncyCastle(final String originalString) throws NoSuchAlgorithmException { + final MessageDigest digest = MessageDigest.getInstance(SHA_256); + final byte[] hash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); + final String sha256hex = new String(Hex.encode(hash)); + return sha256hex; + } + +} diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA3Hashing.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA3Hashing.java new file mode 100644 index 0000000000..eb363205b1 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA3Hashing.java @@ -0,0 +1,45 @@ +package com.baeldung.hashing; + +import com.google.common.hash.Hashing; +import org.apache.commons.codec.digest.DigestUtils; +import org.bouncycastle.crypto.digests.SHA3Digest; +import org.bouncycastle.jcajce.provider.digest.SHA3; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.util.encoders.Hex; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.Security; + +import static com.baeldung.hashing.DigestAlgorithms.SHA3_256; +import static com.baeldung.hashing.SHACommonUtils.bytesToHex; + +public class SHA3Hashing { + + /* works with JDK9+ only */ + public static String hashWithJavaMessageDigestJDK9(final String originalString) throws NoSuchAlgorithmException { + final MessageDigest digest = MessageDigest.getInstance(SHA3_256); + final byte[] hashbytes = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); + return bytesToHex(hashbytes); + } + + public static String hashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException { + Security.addProvider(new BouncyCastleProvider()); + final MessageDigest digest = MessageDigest.getInstance(SHA3_256); + final byte[] hashbytes = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); + return bytesToHex(hashbytes); + } + + /* works with JDK9+ only */ + public static String hashWithApacheCommonsJDK9(final String originalString) { + return new DigestUtils(SHA3_256).digestAsHex(originalString); + } + + public static String hashWithBouncyCastle(final String originalString) { + SHA3.Digest256 digest256 = new SHA3.Digest256(); + byte[] hashbytes = digest256.digest(originalString.getBytes(StandardCharsets.UTF_8)); + return new String(Hex.encode(hashbytes)); + } + +} diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHACommonUtils.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHACommonUtils.java new file mode 100644 index 0000000000..0f28408083 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHACommonUtils.java @@ -0,0 +1,16 @@ +package com.baeldung.hashing; + +class SHACommonUtils { + + public static String bytesToHex(byte[] hash) { + StringBuffer hexString = new StringBuffer(); + for (byte h : hash) { + String hex = Integer.toHexString(0xff & h); + if (hex.length() == 1) + hexString.append('0'); + hexString.append(hex); + } + return hexString.toString(); + } + +} diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java new file mode 100644 index 0000000000..e2259e4249 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java @@ -0,0 +1,149 @@ +package com.baeldung.passwordhashing; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.util.Arrays; +import java.util.Base64; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; + +/** + * Hash passwords for storage, and test passwords against password tokens. + * + * Instances of this class can be used concurrently by multiple threads. + * + * @author erickson + * @see StackOverflow + */ +public final class PBKDF2Hasher +{ + + /** + * Each token produced by this class uses this identifier as a prefix. + */ + public static final String ID = "$31$"; + + /** + * The minimum recommended cost, used by default + */ + public static final int DEFAULT_COST = 16; + + private static final String ALGORITHM = "PBKDF2WithHmacSHA1"; + + private static final int SIZE = 128; + + private static final Pattern layout = Pattern.compile("\\$31\\$(\\d\\d?)\\$(.{43})"); + + private final SecureRandom random; + + private final int cost; + + public PBKDF2Hasher() + { + this(DEFAULT_COST); + } + + /** + * Create a password manager with a specified cost + * + * @param cost the exponential computational cost of hashing a password, 0 to 30 + */ + public PBKDF2Hasher(int cost) + { + iterations(cost); /* Validate cost */ + this.cost = cost; + this.random = new SecureRandom(); + } + + private static int iterations(int cost) + { + if ((cost < 0) || (cost > 30)) + throw new IllegalArgumentException("cost: " + cost); + return 1 << cost; + } + + /** + * Hash a password for storage. + * + * @return a secure authentication token to be stored for later authentication + */ + public String hash(char[] password) + { + byte[] salt = new byte[SIZE / 8]; + random.nextBytes(salt); + byte[] dk = pbkdf2(password, salt, 1 << cost); + byte[] hash = new byte[salt.length + dk.length]; + System.arraycopy(salt, 0, hash, 0, salt.length); + System.arraycopy(dk, 0, hash, salt.length, dk.length); + Base64.Encoder enc = Base64.getUrlEncoder().withoutPadding(); + return ID + cost + '$' + enc.encodeToString(hash); + } + + /** + * Authenticate with a password and a stored password token. + * + * @return true if the password and token match + */ + public boolean checkPassword(char[] password, String token) + { + Matcher m = layout.matcher(token); + if (!m.matches()) + throw new IllegalArgumentException("Invalid token format"); + int iterations = iterations(Integer.parseInt(m.group(1))); + byte[] hash = Base64.getUrlDecoder().decode(m.group(2)); + byte[] salt = Arrays.copyOfRange(hash, 0, SIZE / 8); + byte[] check = pbkdf2(password, salt, iterations); + int zero = 0; + for (int idx = 0; idx < check.length; ++idx) + zero |= hash[salt.length + idx] ^ check[idx]; + return zero == 0; + } + + private static byte[] pbkdf2(char[] password, byte[] salt, int iterations) + { + KeySpec spec = new PBEKeySpec(password, salt, iterations, SIZE); + try { + SecretKeyFactory f = SecretKeyFactory.getInstance(ALGORITHM); + return f.generateSecret(spec).getEncoded(); + } + catch (NoSuchAlgorithmException ex) { + throw new IllegalStateException("Missing algorithm: " + ALGORITHM, ex); + } + catch (InvalidKeySpecException ex) { + throw new IllegalStateException("Invalid SecretKeyFactory", ex); + } + } + + /** + * Hash a password in an immutable {@code String}. + * + *

Passwords should be stored in a {@code char[]} so that it can be filled + * with zeros after use instead of lingering on the heap and elsewhere. + * + * @deprecated Use {@link #hash(char[])} instead + */ + @Deprecated + public String hash(String password) + { + return hash(password.toCharArray()); + } + + /** + * Authenticate with a password in an immutable {@code String} and a stored + * password token. + * + * @deprecated Use {@link #checkPassword(char[],String)} instead. + * @see #hash(String) + */ + @Deprecated + public boolean checkPassword(String password, String token) + { + return checkPassword(password.toCharArray(), token); + } + +} diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java new file mode 100644 index 0000000000..4f5337f963 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java @@ -0,0 +1,35 @@ +package com.baeldung.passwordhashing; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + + +/** A really simple SHA_512 Encryption example. + * + */ +public class SHA512Hasher { + + public String hash(String passwordToHash, byte[] salt){ + String generatedPassword = null; + try { + MessageDigest md = MessageDigest.getInstance("SHA-512"); + md.update(salt); + byte[] bytes = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8)); + StringBuilder sb = new StringBuilder(); + for(int i=0; i< bytes.length ;i++){ + sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1)); + } + generatedPassword = sb.toString(); + } + catch (NoSuchAlgorithmException e){ + e.printStackTrace(); + } + return generatedPassword; + } + + public boolean checkPassword(String hash, String attempt, byte[] salt){ + String generatedHash = hash(attempt, salt); + return hash.equals(generatedHash); + } +} diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java new file mode 100644 index 0000000000..36c9b65070 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java @@ -0,0 +1,18 @@ +package com.baeldung.passwordhashing; + +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import java.security.spec.KeySpec; + +/** A really simple SimplePBKDF2 Encryption example. + * + */ +public class SimplePBKDF2Hasher { + + public static String hashSimple(String password, byte[] salt) throws Exception{ + KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128); + SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); + byte[] hash = f.generateSecret(spec).getEncoded(); + return String.valueOf(hash); + } +} diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java new file mode 100644 index 0000000000..9ed35c8834 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java @@ -0,0 +1,22 @@ +package com.baeldung.hashing; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class Keccak256HashingUnitTest { + + private static String originalValue = "abc123"; + private static String hashedValue = "719accc61a9cc126830e5906f9d672d06eab6f8597287095a2c55a8b775e7016"; + + @Test public void testHashWithJavaMessageDigest() throws Exception { + final String currentHashedValue = Keccak256Hashing.hashWithJavaMessageDigest(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + + @Test public void testHashWithBouncyCastle() { + final String currentHashedValue = Keccak256Hashing.hashWithBouncyCastle(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + +} diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java new file mode 100644 index 0000000000..6bc9ad2cc6 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java @@ -0,0 +1,35 @@ +package com.baeldung.hashing; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class SHA256HashingUnitTest { + + private static String originalValue = "abc123"; + private static String hashedValue = "6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090"; + + @Test + public void testHashWithJavaMessageDigest() throws Exception { + final String currentHashedValue = SHA256Hashing.HashWithJavaMessageDigest(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + + @Test + public void testHashWithGuava() throws Exception { + final String currentHashedValue = SHA256Hashing.hashWithGuava(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + + @Test + public void testHashWithApacheCommans() throws Exception { + final String currentHashedValue = SHA256Hashing.HashWithApacheCommons(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + + @Test + public void testHashWithBouncyCastle() throws Exception { + final String currentHashedValue = SHA256Hashing.HashWithBouncyCastle(originalValue); + assertEquals(hashedValue, currentHashedValue); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java new file mode 100644 index 0000000000..fffab96405 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java @@ -0,0 +1,38 @@ +package com.baeldung.hashing; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class SHA3HashingUnitTest { + + private static String originalValue = "abc123"; + private static String hashedValue = "f58fa3df820114f56e1544354379820cff464c9c41cb3ca0ad0b0843c9bb67ee"; + + /* works with JDK9+ only */ + //@Test + public void testHashWithJavaMessageDigestJDK9() throws Exception { + final String currentHashedValue = SHA3Hashing.hashWithJavaMessageDigestJDK9(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + + @Test + public void testHashWithJavaMessageDigest() throws Exception { + final String currentHashedValue = SHA3Hashing.hashWithJavaMessageDigest(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + + /* works with JDK9+ only */ + //@Test + public void testHashWithApacheCommonsJDK9() { + final String currentHashedValue = SHA3Hashing.hashWithApacheCommonsJDK9(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + + @Test + public void testHashWithBouncyCastle() { + final String currentHashedValue = SHA3Hashing.hashWithBouncyCastle(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + +} diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java new file mode 100644 index 0000000000..67d6918c09 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java @@ -0,0 +1,75 @@ +package com.baeldung.java.md5; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import javax.xml.bind.DatatypeConverter; + +import org.apache.commons.codec.digest.DigestUtils; +import org.junit.Test; + +import com.google.common.hash.HashCode; +import com.google.common.hash.Hashing; + +public class JavaMD5UnitTest { + + String filename = "src/test/resources/test_md5.txt"; + String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3"; + + String hash = "35454B055CC325EA1AF2126E27707052"; + String password = "ILoveJava"; + + @Test + public void givenPassword_whenHashing_thenVerifying() throws NoSuchAlgorithmException { + String hash = "35454B055CC325EA1AF2126E27707052"; + String password = "ILoveJava"; + + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(password.getBytes()); + byte[] digest = md.digest(); + String myHash = DatatypeConverter.printHexBinary(digest).toUpperCase(); + + assertThat(myHash.equals(hash)).isTrue(); + } + + @Test + public void givenFile_generatingChecksum_thenVerifying() throws NoSuchAlgorithmException, IOException { + String filename = "src/test/resources/test_md5.txt"; + String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3"; + + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(Files.readAllBytes(Paths.get(filename))); + byte[] digest = md.digest(); + String myChecksum = DatatypeConverter.printHexBinary(digest).toUpperCase(); + + assertThat(myChecksum.equals(checksum)).isTrue(); + } + + @Test + public void givenPassword_whenHashingUsingCommons_thenVerifying() { + String hash = "35454B055CC325EA1AF2126E27707052"; + String password = "ILoveJava"; + + String md5Hex = DigestUtils.md5Hex(password).toUpperCase(); + + assertThat(md5Hex.equals(hash)).isTrue(); + } + + @Test + public void givenFile_whenChecksumUsingGuava_thenVerifying() throws IOException { + String filename = "src/test/resources/test_md5.txt"; + String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3"; + + HashCode hash = com.google.common.io.Files.hash(new File(filename), Hashing.md5()); + String myChecksum = hash.toString().toUpperCase(); + + assertThat(myChecksum.equals(checksum)).isTrue(); + } + +} diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java new file mode 100644 index 0000000000..8e90725c77 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java @@ -0,0 +1,41 @@ +package com.baeldung.passwordhashing; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + + +public class PBKDF2HasherUnitTest { + + private PBKDF2Hasher mPBKDF2Hasher; + + @Before + public void setUp() throws Exception { + mPBKDF2Hasher = new PBKDF2Hasher(); + } + + @Test + public void givenCorrectMessageAndHash_whenAuthenticated_checkAuthenticationSucceeds() throws Exception { + String message1 = "password123"; + + String hash1 = mPBKDF2Hasher.hash(message1.toCharArray()); + + assertTrue(mPBKDF2Hasher.checkPassword(message1.toCharArray(), hash1)); + + } + + @Test + public void givenWrongMessage_whenAuthenticated_checkAuthenticationFails() throws Exception { + String message1 = "password123"; + + String hash1 = mPBKDF2Hasher.hash(message1.toCharArray()); + + String wrongPasswordAttempt = "IamWrong"; + + assertFalse(mPBKDF2Hasher.checkPassword(wrongPasswordAttempt.toCharArray(), hash1)); + + } + + +} \ No newline at end of file diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java new file mode 100644 index 0000000000..3acfb0ba9d --- /dev/null +++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java @@ -0,0 +1,70 @@ +package com.baeldung.passwordhashing; + +import org.junit.Before; +import org.junit.Test; + +import java.security.SecureRandom; + +import static org.junit.Assert.*; + +/** + * Created by PhysicsSam on 06-Sep-18. + */ +public class SHA512HasherUnitTest { + + private SHA512Hasher hasher; + private SecureRandom secureRandom; + + @Before + public void setUp() throws Exception { + hasher = new SHA512Hasher(); + secureRandom = new SecureRandom(); + } + + @Test + public void givenSamePasswordAndSalt_whenHashed_checkResultingHashesAreEqual() throws Exception { + + byte[] salt = new byte[16]; + secureRandom.nextBytes(salt); + + String hash1 = hasher.hash("password", salt); + String hash2 = hasher.hash("password", salt); + + assertEquals(hash1, hash2); + + } + + @Test + public void givenSamePasswordAndDifferentSalt_whenHashed_checkResultingHashesNotEqual() throws Exception { + + byte[] salt = new byte[16]; + secureRandom.nextBytes(salt); + String hash1 = hasher.hash("password", salt); + //generate a second salt + byte[] secondSalt = new byte[16]; + String hash2 = hasher.hash("password", secondSalt); + + assertNotEquals(hash1, hash2); + + } + + @Test + public void givenPredefinedHash_whenCorrectAttemptGiven_checkAuthenticationSucceeds() throws Exception { + byte[] salt = new byte[16]; + secureRandom.nextBytes(salt); + + String originalHash = hasher.hash("password123", salt); + + assertTrue(hasher.checkPassword(originalHash, "password123", salt)); + } + + @Test + public void givenPredefinedHash_whenIncorrectAttemptGiven_checkAuthenticationFails() throws Exception { + byte[] salt = new byte[16]; + secureRandom.nextBytes(salt); + + String originalHash = hasher.hash("password123", salt); + + assertFalse(hasher.checkPassword(originalHash, "password124", salt)); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-security-2/src/test/resources/test_md5.txt b/core-java-modules/core-java-security-2/src/test/resources/test_md5.txt new file mode 100644 index 0000000000..95d09f2b10 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/test/resources/test_md5.txt @@ -0,0 +1 @@ +hello world \ No newline at end of file