Reduce code duplication
Some checks failed
Build SSHJ / Build with Java 11 (push) Has been cancelled
Build SSHJ / Integration test (push) Has been cancelled

Signed-off-by: Jeroen van Erp <jeroen@hierynomus.com>
This commit is contained in:
Jeroen van Erp
2025-04-22 14:36:09 +02:00
parent 8e9e644bb8
commit acad163e50
4 changed files with 102 additions and 128 deletions

View File

@@ -15,20 +15,11 @@
*/ */
package net.schmizz.sshj.transport.random; package net.schmizz.sshj.transport.random;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
/** /**
* BouncyCastle <code>Random</code>. This pseudo random number generator uses BouncyCastle fips. * BouncyCastle <code>Random</code>. This pseudo random number generator uses BouncyCastle fips.
* The JRE random will be used when creating a new generator to add some random data to the seed. * The JRE random will be used when creating a new generator to add some random data to the seed.
*/ */
public class BouncyCastleFipsRandom public class BouncyCastleFipsRandom extends SecureRandomProvider {
implements Random {
private static final Logger logger = LoggerFactory.getLogger(BouncyCastleFipsRandom.class);
/** Named factory for the BouncyCastle <code>Random</code> */ /** Named factory for the BouncyCastle <code>Random</code> */
public static class Factory public static class Factory
@@ -40,39 +31,9 @@ public class BouncyCastleFipsRandom
} }
} }
private byte[] tmp = new byte[16];
private final SecureRandom random;
public BouncyCastleFipsRandom() { public BouncyCastleFipsRandom() {
logger.info("Generating random seed from SecureRandom of BCFIPS."); super("DEFAULT", "BCFIPS");
long t = System.currentTimeMillis();
try {
// Use SecureRandom with the BCFIPS provider
random = SecureRandom.getInstance("DEFAULT", "BCFIPS");
} catch (NoSuchProviderException e) {
throw new RuntimeException("BCFIPS provider is not available", e);
} catch (Exception e) {
throw new RuntimeException("Failed to initialize SecureRandom with BCFIPS provider", e);
}
logger.debug("Creating random seed took {} ms", System.currentTimeMillis() - t);
} }
@Override
public synchronized void fill(byte[] bytes, int start, int len) {
if (start == 0 && len == bytes.length) {
random.nextBytes(bytes);
} else {
synchronized (this) {
if (len > tmp.length) tmp = new byte[len];
random.nextBytes(tmp);
System.arraycopy(tmp, 0, bytes, start, len);
}
}
}
@Override
public void fill(byte[] bytes) {
random.nextBytes(bytes);
}
} }

View File

@@ -13,26 +13,32 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/*
* Copyright (C)2009 - SSHJ Contributors
*
* 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 net.schmizz.sshj.transport.random; package net.schmizz.sshj.transport.random;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
/** /**
* BouncyCastle <code>Random</code>. This pseudo random number generator uses BouncyCastle non fips. * BouncyCastle <code>Random</code>. This pseudo random number generator uses BouncyCastle non fips.
* The JRE random will be used when creating a new generator to add some random data to the seed. * The JRE random will be used when creating a new generator to add some random data to the seed.
*/ */
public class BouncyCastleRandom public class BouncyCastleRandom extends SecureRandomProvider {
implements Random {
private static final Logger logger = LoggerFactory.getLogger(BouncyCastleRandom.class);
/** Named factory for the BouncyCastle <code>Random</code> */ /** Named factory for the BouncyCastle <code>Random</code> */
public static class Factory public static class Factory
implements net.schmizz.sshj.common.Factory<Random> { implements net.schmizz.sshj.common.Factory<Random> {
@Override @Override
public Random create() { public Random create() {
@@ -40,39 +46,8 @@ public class BouncyCastleRandom
} }
} }
private byte[] tmp = new byte[16];
private final SecureRandom random;
public BouncyCastleRandom() { public BouncyCastleRandom() {
logger.info("Generating random seed from SecureRandom of BC."); super("DEFAULT", "BC");
long t = System.currentTimeMillis();
try {
// Use SecureRandom with the BC provider
random = SecureRandom.getInstance("DEFAULT", "BC");
} catch (NoSuchProviderException e) {
throw new RuntimeException("BC provider is not in the classpath", e);
} catch (Exception e) {
throw new RuntimeException("Failed to initialize SecureRandom with BC provider", e);
} }
logger.debug("Creating random seed took {} ms", System.currentTimeMillis() - t);
}
@Override
public synchronized void fill(byte[] bytes, int start, int len) {
if (start == 0 && len == bytes.length) {
random.nextBytes(bytes);
} else {
synchronized (this) {
if (len > tmp.length) tmp = new byte[len];
random.nextBytes(tmp);
System.arraycopy(tmp, 0, bytes, start, len);
}
}
}
@Override
public void fill(byte[] bytes) {
random.nextBytes(bytes);
}
} }

View File

@@ -15,16 +15,11 @@
*/ */
package net.schmizz.sshj.transport.random; package net.schmizz.sshj.transport.random;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.SecureRandom; import java.security.SecureRandom;
/** A {@link Random} implementation using the built-in {@link SecureRandom} PRNG. */ /** A {@link Random} implementation using the built-in {@link SecureRandom} PRNG. */
public class JCERandom public class JCERandom extends SecureRandomProvider {
implements Random {
private static final Logger logger = LoggerFactory.getLogger(JCERandom.class);
/** Named factory for the JCE {@link Random} */ /** Named factory for the JCE {@link Random} */
public static class Factory public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Random> { implements net.schmizz.sshj.common.Factory.Named<Random> {
@@ -41,39 +36,7 @@ public class JCERandom
} }
private byte[] tmp = new byte[16];
private final SecureRandom random;
JCERandom() { JCERandom() {
logger.info("Creating new SecureRandom."); super();
long t = System.currentTimeMillis();
random = new SecureRandom();
logger.debug("Random creation took {} ms", System.currentTimeMillis() - t);
}
/**
* Fill the given byte-array with random bytes from this PRNG.
*
* @param foo the byte-array
* @param start the offset to start at
* @param len the number of bytes to fill
*/
@Override
public synchronized void fill(byte[] foo, int start, int len) {
if (start == 0 && len == foo.length) {
random.nextBytes(foo);
} else {
synchronized (this) {
if (len > tmp.length)
tmp = new byte[len];
random.nextBytes(tmp);
System.arraycopy(tmp, 0, foo, start, len);
}
}
}
@Override
public void fill(final byte[] bytes) {
random.nextBytes(bytes);
} }
} }

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C)2009 - SSHJ Contributors
*
* 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 net.schmizz.sshj.transport.random;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SecureRandomProvider implements Random{
private static final Logger logger = LoggerFactory.getLogger(SecureRandomProvider.class);
private byte[] tmp = new byte[16];
private SecureRandom random;
protected SecureRandomProvider() {
this.random = newRandom();
}
protected SecureRandomProvider(String algorithm, String provider) {
this.random = newRandom(algorithm, provider);
}
private static SecureRandom newRandom() {
return new SecureRandom();
}
private static SecureRandom newRandom(String algorithm, String provider) {
logger.info("Generating random seed from SecureRandom of {}.", provider);
long t = System.currentTimeMillis();
try {
// Use SecureRandom with the provider
return SecureRandom.getInstance(algorithm, provider);
} catch (NoSuchProviderException e) {
throw new RuntimeException(String.format("%s provider is not in the classpath", provider), e);
} catch (Exception e) {
throw new RuntimeException(String.format("Failed to initialize SecureRandom with %s provider", provider), e);
} finally {
logger.debug("Creating random seed took {} ms", System.currentTimeMillis() - t);
}
}
@Override
public synchronized void fill(byte[] bytes, int start, int len) {
if (start == 0 && len == bytes.length) {
random.nextBytes(bytes);
} else {
synchronized (this) {
if (len > tmp.length) tmp = new byte[len];
random.nextBytes(tmp);
System.arraycopy(tmp, 0, bytes, start, len);
}
}
}
@Override
public void fill(byte[] bytes) {
random.nextBytes(bytes);
}
}