MATH-1608: Remove random string generator.

Functionality is out-of-scope (cf. "Commons Codec").
This commit is contained in:
Gilles Sadowski 2021-06-14 14:49:11 +02:00
parent bdc4a527fb
commit 24b1d86ffb
2 changed files with 0 additions and 173 deletions

View File

@ -62,120 +62,6 @@ public class RandomUtils {
this.rng = rng;
}
/**
* Generates a random string of hex characters of length {@code len}.
*
* <strong>Algorithm Description:</strong> how hexadecimal strings are
* generated depends on the value of the {@code useSha1} argument.
*
* <ul>
* <li>If {@code useSha1 == false}, a 2-step process is used:
* <ol>
* <li>
* {@code len / 2 + 1} binary bytes are generated using the underlying
* generator.
* </li>
* <li>
* Each binary byte is translated into 2 hex digits.
* </li>
* </ol>
* </li>
* <li>
* If {@code useSha1 == true}, hex strings are generated in 40-byte
* segments using a 3-step process:
* <ol>
* <li>
* 20 random bytes are generated using the underlying generator.
* </li>
* <li>
* SHA-1 hash is applied to yield a 20-byte binary digest.
* </li>
* <li>
* Each byte of the binary digest is converted to 2 hex digits.
* </li>
* </ol>
* </li>
* </ul>
*
* @param len Length of the generated string.
* @param useSha1 Whether to use a digest.
* If {@code true} (resp. {@code false}), the 3-step (resp. 2-step)
* process will be used.
* @return the random string.
* @throws NotStrictlyPositiveException if {@code len <= 0}.
*/
public String nextHexString(int len,
boolean useSha1) {
if (len <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.LENGTH, len);
}
// Initialize output buffer.
final StringBuilder outBuffer = new StringBuilder();
if (!useSha1) {
// Generate int(len/2)+1 random bytes.
final byte[] randomBytes = new byte[(len / 2) + 1];
rng.nextBytes(randomBytes);
// Convert each byte to 2 hex digits.
for (int i = 0; i < randomBytes.length; i++) {
final Integer c = Integer.valueOf(randomBytes[i]);
// Add 128 to byte value to make interval 0-255 before
// conversion to hex.
// This guarantees <= 2 hex digits from "toHexString".
// "toHexString" would otherwise add 2^32 to negative arguments.
String hex = Integer.toHexString(c.intValue() + 128);
// Make sure we add 2 hex digits for each byte.
if (hex.length() == 1) {
hex = "0" + hex;
}
outBuffer.append(hex);
}
} else {
MessageDigest alg = null;
try {
alg = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException ex) {
// Should never happen.
throw new MathInternalError(ex);
}
alg.reset();
// Compute number of iterations required (40 bytes each).
final int numIter = (len / 40) + 1;
for (int iter = 1; iter < numIter + 1; iter++) {
final byte[] randomBytes = new byte[40];
rng.nextBytes(randomBytes);
alg.update(randomBytes);
// Create 20-byte binary hash.
final byte[] hash = alg.digest();
// Loop over the hash, converting each byte to 2 hex digits
for (int i = 0; i < hash.length; i++) {
final Integer c = Integer.valueOf(hash[i]);
// Add 128 to byte value to make interval 0-255.
// This guarantees <= 2 hex digits from "toHexString".
// "toHexString" would otherwise add 2^32 to negative arguments.
String hex = Integer.toHexString(c.intValue() + 128);
// Keep strings uniform length: guarantees 40 bytes.
if (hex.length() == 1) {
hex = "0" + hex;
}
outBuffer.append(hex);
}
}
}
return outBuffer.toString().substring(0, len);
}
/**
* Generates a uniformly distributed random long integer between {@code lower}
* and {@code upper} (endpoints included).

View File

@ -136,65 +136,6 @@ public abstract class RandomUtilsDataGeneratorAbstractTest {
(((double) upper) - ((double) lower));
Assert.assertTrue(ratio > 0.99999);
}
/** Test dispersion and failure modes for "nextHex". */
@Test
public void testNextHexWithoutSha1() {
checkNextHex(false);
}
@Test
public void testNextHexWithSha1() {
checkNextHex(true);
}
/**
* @param useSha1 Alternative.
*/
private void checkNextHex(boolean useSha1) {
try {
randomData.nextHexString(-1, useSha1);
Assert.fail("negative length supplied -- MathIllegalArgumentException expected");
} catch (MathIllegalArgumentException ex) {
// ignored
}
try {
randomData.nextHexString(0, useSha1);
Assert.fail("zero length supplied -- MathIllegalArgumentException expected");
} catch (MathIllegalArgumentException ex) {
// ignored
}
String hexString = randomData.nextHexString(3, useSha1);
if (hexString.length() != 3) {
Assert.fail("incorrect length for generated string");
}
hexString = randomData.nextHexString(1, useSha1);
if (hexString.length() != 1) {
Assert.fail("incorrect length for generated string");
}
try {
hexString = randomData.nextHexString(0, useSha1);
Assert.fail("zero length requested -- expecting MathIllegalArgumentException");
} catch (MathIllegalArgumentException ex) {
// ignored
}
Frequency<String> f = new Frequency<>();
for (int i = 0; i < smallSampleSize; i++) {
hexString = randomData.nextHexString(100, useSha1);
if (hexString.length() != 100) {
Assert.fail("incorrect length for generated string");
}
for (int j = 0; j < hexString.length(); j++) {
f.addValue(hexString.substring(j, j + 1));
}
}
double[] expected = new double[16];
long[] observed = new long[16];
for (int i = 0; i < 16; i++) {
expected[i] = (double) smallSampleSize * 100 / 16;
observed[i] = f.getCount(hex[i]);
}
TestUtils.assertChiSquareAccept(expected, observed, 0.001);
}
@Test
public void testNextUniformIAE() {