diff --git a/password/impl/src/main/java/org/wildfly/security/password/impl/BSDUnixDESCryptPasswordImpl.java b/password/impl/src/main/java/org/wildfly/security/password/impl/BSDUnixDESCryptPasswordImpl.java index cb918d2ebe6..c7fb6a44b5b 100644 --- a/password/impl/src/main/java/org/wildfly/security/password/impl/BSDUnixDESCryptPasswordImpl.java +++ b/password/impl/src/main/java/org/wildfly/security/password/impl/BSDUnixDESCryptPasswordImpl.java @@ -30,7 +30,6 @@ import java.security.spec.InvalidParameterSpecException; import java.security.spec.KeySpec; import java.util.Arrays; -import java.util.concurrent.ThreadLocalRandom; import org.wildfly.security.password.interfaces.BSDUnixDESCryptPassword; import org.wildfly.security.password.spec.ClearPasswordSpec; @@ -72,11 +71,11 @@ class BSDUnixDESCryptPasswordImpl extends AbstractPasswordImpl implements BSDUni } BSDUnixDESCryptPasswordImpl(final ClearPasswordSpec passwordSpec) throws InvalidKeySpecException { - this(passwordSpec.getEncodedPassword(), ThreadLocalRandom.current().nextInt() & 0xffffff, DEFAULT_ITERATION_COUNT); + this(passwordSpec.getEncodedPassword(), PasswordUtil.generateRandomSaltInt() & 0xffffff, DEFAULT_ITERATION_COUNT); } BSDUnixDESCryptPasswordImpl(final char[] password, final Charset hashCharset) throws InvalidKeySpecException, InvalidParameterSpecException { - this(password, ThreadLocalRandom.current().nextInt() & 0xffffff, DEFAULT_ITERATION_COUNT, hashCharset); + this(password, PasswordUtil.generateRandomSaltInt() & 0xffffff, DEFAULT_ITERATION_COUNT, hashCharset); } BSDUnixDESCryptPasswordImpl(final char[] password, final IteratedSaltedPasswordAlgorithmSpec spec, final Charset hashCharset) throws InvalidKeySpecException, InvalidParameterSpecException { @@ -84,7 +83,7 @@ class BSDUnixDESCryptPasswordImpl extends AbstractPasswordImpl implements BSDUni } BSDUnixDESCryptPasswordImpl(final char[] password, final IteratedPasswordAlgorithmSpec spec, final Charset hashCharset) throws InvalidKeySpecException, InvalidParameterSpecException { - this(password, ThreadLocalRandom.current().nextInt() & 0xffffff, spec.getIterationCount(), hashCharset); + this(password, PasswordUtil.generateRandomSaltInt() & 0xffffff, spec.getIterationCount(), hashCharset); } BSDUnixDESCryptPasswordImpl(final char[] password, final SaltedPasswordAlgorithmSpec spec, final Charset hashCharset) throws InvalidKeySpecException, InvalidParameterSpecException { diff --git a/password/impl/src/main/java/org/wildfly/security/password/impl/PasswordUtil.java b/password/impl/src/main/java/org/wildfly/security/password/impl/PasswordUtil.java index 21e1f8a58f1..0568d746159 100644 --- a/password/impl/src/main/java/org/wildfly/security/password/impl/PasswordUtil.java +++ b/password/impl/src/main/java/org/wildfly/security/password/impl/PasswordUtil.java @@ -17,7 +17,7 @@ */ package org.wildfly.security.password.impl; -import java.util.concurrent.ThreadLocalRandom; +import java.security.SecureRandom; /** * Helper utility methods for operations on passwords. @@ -27,6 +27,8 @@ */ final class PasswordUtil { + private static final SecureRandom RANDOM = new SecureRandom(); + /** * Generate a random salt as byte array. * @@ -35,7 +37,24 @@ final class PasswordUtil { */ public static byte[] generateRandomSalt(int saltSize) { byte[] randomSalt = new byte[saltSize]; - ThreadLocalRandom.current().nextBytes(randomSalt); + RANDOM.nextBytes(randomSalt); return randomSalt; } + + /** + * Generate a random salt as int. + * + * @return a byte array representing the random salt + */ + public static int generateRandomSaltInt() { + byte[] saltBytes = generateRandomSalt(4); + return convertBytesToInt(saltBytes); + } + + static int convertBytesToInt(byte[] saltBytes) { + if (saltBytes.length != 4) { + throw new IllegalArgumentException("4 bytes are needed for conversion to int, bytes given: " + saltBytes.length); + } + return (saltBytes[0] & 0xff) << 24 | (saltBytes[1] & 0xff) << 16 | (saltBytes[2] & 0xff) << 8 | saltBytes[3] & 0xff; + } } diff --git a/password/impl/src/main/java/org/wildfly/security/password/impl/UnixDESCryptPasswordImpl.java b/password/impl/src/main/java/org/wildfly/security/password/impl/UnixDESCryptPasswordImpl.java index 00ad94110da..267dfd70200 100644 --- a/password/impl/src/main/java/org/wildfly/security/password/impl/UnixDESCryptPasswordImpl.java +++ b/password/impl/src/main/java/org/wildfly/security/password/impl/UnixDESCryptPasswordImpl.java @@ -31,7 +31,6 @@ import java.security.spec.InvalidParameterSpecException; import java.security.spec.KeySpec; import java.util.Arrays; -import java.util.concurrent.ThreadLocalRandom; import org.wildfly.security.password.interfaces.UnixDESCryptPassword; import org.wildfly.security.password.spec.ClearPasswordSpec; @@ -68,11 +67,11 @@ class UnixDESCryptPasswordImpl extends AbstractPasswordImpl implements UnixDESCr } UnixDESCryptPasswordImpl(final ClearPasswordSpec spec) throws InvalidKeySpecException, InvalidKeyException { - this((short) (ThreadLocalRandom.current().nextInt() & 0xfff), spec.getEncodedPassword()); + this((short) (PasswordUtil.generateRandomSaltInt() & 0xfff), spec.getEncodedPassword()); } UnixDESCryptPasswordImpl(final char[] passwordChars, final Charset hashCharset) throws InvalidKeyException { - this((short) (ThreadLocalRandom.current().nextInt() & 0xfff), passwordChars, hashCharset); + this((short) (PasswordUtil.generateRandomSaltInt() & 0xfff), passwordChars, hashCharset); } UnixDESCryptPasswordImpl(final char[] passwordChars, SaltedPasswordAlgorithmSpec algorithmSpec, final Charset hashCharset) throws InvalidParameterSpecException, InvalidKeyException { diff --git a/password/impl/src/test/java/org/wildfly/security/password/impl/PasswordUtilTest.java b/password/impl/src/test/java/org/wildfly/security/password/impl/PasswordUtilTest.java new file mode 100644 index 00000000000..3e61a3a3712 --- /dev/null +++ b/password/impl/src/test/java/org/wildfly/security/password/impl/PasswordUtilTest.java @@ -0,0 +1,15 @@ +package org.wildfly.security.password.impl; + +import org.junit.Assert; +import org.junit.Test; + +public class PasswordUtilTest { + + @Test + public void testConvertBytesToInt() { + Assert.assertEquals(0, PasswordUtil.convertBytesToInt(new byte[] {(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00})); + Assert.assertEquals(Integer.MAX_VALUE, PasswordUtil.convertBytesToInt(new byte[] {(byte) 0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xff})); + Assert.assertEquals(Integer.MIN_VALUE, PasswordUtil.convertBytesToInt(new byte[] {(byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00})); + Assert.assertEquals(-1, PasswordUtil.convertBytesToInt(new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff})); + } +}