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