Skip to content

Commit

Permalink
ELY-2731 Use SecureRandom instead of ThreadLocalRandom
Browse files Browse the repository at this point in the history
  • Loading branch information
darranl committed Sep 17, 2024
2 parents f73a02b + 6917c62 commit 7251485
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -72,19 +71,19 @@ 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 {
this(password, getSaltValue(spec.getSalt()), spec.getIterationCount(), hashCharset);
}

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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/
package org.wildfly.security.password.impl;

import java.util.concurrent.ThreadLocalRandom;
import org.wildfly.common.Assert;

/**
* Helper utility methods for operations on passwords.
Expand All @@ -27,6 +27,8 @@
*/
final class PasswordUtil {

private static final ThreadLocalSecureRandom THREAD_LOCAL_SECURE_RANDOM = new ThreadLocalSecureRandom();

/**
* Generate a random salt as byte array.
*
Expand All @@ -35,7 +37,22 @@ final class PasswordUtil {
*/
public static byte[] generateRandomSalt(int saltSize) {
byte[] randomSalt = new byte[saltSize];
ThreadLocalRandom.current().nextBytes(randomSalt);
THREAD_LOCAL_SECURE_RANDOM.get().nextBytes(randomSalt);
return randomSalt;
}

/**
* Generate a random salt as int.
*
* @return a byte array representing the random salt
*/
static int generateRandomSaltInt() {
byte[] saltBytes = generateRandomSalt(4);
return convertBytesToInt(saltBytes);
}

static int convertBytesToInt(byte[] saltBytes) {
Assert.assertTrue(saltBytes.length == 4);
return (saltBytes[0] & 0xff) << 24 | (saltBytes[1] & 0xff) << 16 | (saltBytes[2] & 0xff) << 8 | saltBytes[3] & 0xff;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* JBoss, Home of Professional Open Source
*
* Copyright 2024 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.wildfly.security.password.impl;

import java.security.SecureRandom;
import java.util.function.Supplier;

class ThreadLocalSecureRandom implements Supplier<SecureRandom> {
final ThreadLocal<SecureRandom> localInstance = new ThreadLocal<>();

public SecureRandom get() {
if (localInstance.get() == null) {
localInstance.set(new SecureRandom());
}
return localInstance.get();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* JBoss, Home of Professional Open Source
*
* Copyright 2024 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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}));
}
}

0 comments on commit 7251485

Please sign in to comment.