JAVA-623: Moved 3 articles to core-java-security-2

This commit is contained in:
sampadawagde 2020-03-28 16:48:43 +05:30
parent c18d09cd33
commit e2b6b4bc92
17 changed files with 661 additions and 0 deletions

View File

@ -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)

View File

@ -16,4 +16,34 @@
<relativePath>../../parent-java</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>${commons-codec.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
<!-- test scoped -->
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj-core.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<!-- util -->
<bouncycastle.version>1.60</bouncycastle.version>
<commons-codec.version>1.11</commons-codec.version>
<!-- testing -->
<assertj-core.version>3.10.0</assertj-core.version>
</properties>
</project>

View File

@ -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";
}

View File

@ -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));
}
}

View File

@ -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;
}
}

View File

@ -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));
}
}

View File

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

View File

@ -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 <a href="http://stackoverflow.com/a/2861125/3474">StackOverflow</a>
*/
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}.
*
* <p>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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

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

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -0,0 +1 @@
hello world