diff --git a/CHANGELOG b/CHANGELOG index 7639078..6d3bdf6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,7 @@ * update various dependencies * update to github actions & sonaqube * add OWASP dependency checker +* fix lots of typos and minor bugs ## v1.6.0 * use better implementations of Base64 and Hex encoder diff --git a/README.md b/README.md index 70befdd..f0cb1ed 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ A cryptographically secure pseudo-random number generator [CLI](https://en.wikip * Supports all common byte encodings and more (hex, [base32](https://en.wikipedia.org/wiki/Base32), [base36](https://en.wikipedia.org/wiki/Base36), base64, [base85](https://en.wikipedia.org/wiki/Ascii85#RFC_1924_version), etc.) * Optional secure seeding of random generator with [random.org](https://www.random.org/) and [ANU Quantum Random Numbers Server](https://qrng.anu.edu.au/) - * Generates code for random byte arrays for many programming languages (java, c, c#, kotlin, phyton, swift, go,...) + * Generates code for random byte arrays for many programming languages (java, c, c#, kotlin, python, swift, go,...) * [NIST SP800-90Ar1 HMAC_DRBG](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf) tested with official [test vectors](https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program) * Output to command line or file with automatic column formatting with upper limit of 10GiB+ of random data (~20MiB/s) * Entropy warnings if seed is weak @@ -44,9 +44,9 @@ This should run on any Windows, Mac or Linux machine. ## Download -**[Grab jar from latest Release](https://github.com/patrickfav/dice/releases/latest)** +**[Grab jar from the latest Release](https://github.com/patrickfav/dice/releases/latest)** -_Using the *.exe Launcher: [Launch4J](http://launch4j.sourceforge.net/) is used to wrap the `.jar` into an Windows executable. It should automatically download the needed JRE if required._ +_Using the *.exe Launcher: [Launch4J](http://launch4j.sourceforge.net/) is used to wrap the `.jar` into a Windows executable. It should automatically download the needed JRE if required._ ## Demo @@ -75,7 +75,7 @@ Create a file 4MiB full of raw random bytes with this call: java -jar dice.jar 4096 -c 1024 -e "raw" -f "./rnd-outfile.txt" -This will create random chunks of 4Kib (the maximum allowed size per chunk) repeated 1024 times. Currently the tool is capped to 10 GiB of generated random data per call. Successive calls will append data, not overwrite it. +This will create random chunks of 4Kib (the maximum allowed size per chunk) repeated 1024 times. Currently, the tool is capped to 10 GiB of generated random data per call. Successive calls will append data, not overwrite it. ## Command Line Interface @@ -108,53 +108,53 @@ This will create random chunks of 4Kib (the maximum allowed size per chunk) repe ### Byte-to-Text Encodings -| Name | Example | Efficiency | Padding | Description | -| ------------- | ------------- | -------------: | :-------------: | ------------- | -| binary | `11101101 10101111 00011110 11111111 11111101 10010100 01001010` | 12.5 % | false | A simple binary representation with '0' and '1' divided into 8 bit groups. | -| octal | `1124517677707527755` | 37.5 % | true | The octal numeral system, is the base-8 number system, and uses the digits 0 to 7. | -| dec | `20992966904426477` | 41.5 % | true | Decimal positive sign-magnitude representation representation in big-endian byte-order. | -| base16 | `4a94fdff1eafed` | 50.0 % | false | Base16 or hex stores each byte as a pair of hexadecimal digits. Lowercase (a-f) letters are used for digits greater than 9. | -| BASE16 | `4A94FDFF1EAFED` | 50.0 % | false | Base16 or hex stores each byte as a pair of hexadecimal digits. Uppercase (A-F) letters are used for digits greater than 9. | -| base26 | `FSSLZZFNQZQZ` | 58.8 % | true | Base26 uses the twenty-six letters A-Z. | -| base32 | `JKKP37Y6V7WQ` | 62.5 % | true | Base32 uses a 32-character subset of the twenty-six letters A-Z and the digits 2-7. Uses the alphabet defined in RFC 4648. | -| base36 | `5qpdvuwjvu5` | 64.6 % | true | Base36 translating into a radix-36 (aka Hexatrigesimal) representation. | -| base58 | `3pvkeHJmHN` | 73.2 % | true | Base58 is similar to Base64 but has been modified to avoid both non-alphanumeric characters and letters which might look ambiguous when printed. This version uses the alphabet common for Bitcoin protocol. | -| base64 | `SpT9/x6v7Q` | 75.0 % | true | Base64 represent binary data in an ASCII string format by translating it into a radix-64 representation. | -| base64-url | `SpT9_x6v7Q` | 75.0 % | true | Base64 represent binary data in an ASCII string format by translating it into a radix-64 representation. Uses url safe mode | -| base85 | `8sK;S*j=r` | 80.1 % | true | Base85 uses an 85 character ASCII alphabet to encode. It's main use is with the PDF format and GIT. | +| Name | Example | Efficiency | Padding | Description | +|------------|------------------------------------------------------------------|-----------:|:-------:|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| binary | `11101101 10101111 00011110 11111111 11111101 10010100 01001010` | 12.5 % | false | A simple binary representation with '0' and '1' divided into 8 bit groups. | +| octal | `1124517677707527755` | 37.5 % | true | The octal numeral system, is the base-8 number system, and uses the digits 0 to 7. | +| dec | `20992966904426477` | 41.5 % | true | Decimal positive sign-magnitude representation representation in big-endian byte-order. | +| base16 | `4a94fdff1eafed` | 50.0 % | false | Base16 or hex stores each byte as a pair of hexadecimal digits. Lowercase (a-f) letters are used for digits greater than 9. | +| BASE16 | `4A94FDFF1EAFED` | 50.0 % | false | Base16 or hex stores each byte as a pair of hexadecimal digits. Uppercase (A-F) letters are used for digits greater than 9. | +| base26 | `FSSLZZFNQZQZ` | 58.8 % | true | Base26 uses the twenty-six letters A-Z. | +| base32 | `JKKP37Y6V7WQ` | 62.5 % | true | Base32 uses a 32-character subset of the twenty-six letters A-Z and the digits 2-7. Uses the alphabet defined in RFC 4648. | +| base36 | `5qpdvuwjvu5` | 64.6 % | true | Base36 translating into a radix-36 (aka Hexatrigesimal) representation. | +| base58 | `3pvkeHJmHN` | 73.2 % | true | Base58 is similar to Base64 but has been modified to avoid both non-alphanumeric characters and letters which might look ambiguous when printed. This version uses the alphabet common for Bitcoin protocol. | +| base64 | `SpT9/x6v7Q` | 75.0 % | true | Base64 represent binary data in an ASCII string format by translating it into a radix-64 representation. | +| base64-url | `SpT9_x6v7Q` | 75.0 % | true | Base64 represent binary data in an ASCII string format by translating it into a radix-64 representation. Uses url safe mode | +| base85 | `8sK;S*j=r` | 80.1 % | true | Base85 uses an 85 character ASCII alphabet to encode. It's main use is with the PDF format and GIT. | ### Programming Languages -| Name | Example | -| :-------------: | ------------- | -| c | `{0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11};` | -| c# | `new byte[]{0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11};` | -| java | `new byte[]{(byte) 0xD0, 0x3A, 0x4A, (byte) 0xEE, 0x64, 0x11};` | -| go | `[...]byte = {0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11}` | -| kotlin | `byteArrayOf(0xD0.toByte(), 0x3A, 0x4A, 0xEE.toByte(), 0x64, 0x11)` | -| node | `new Buffer([0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11]);` | -| javascript | `Uint8Array.from([0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11]);` | -| perl | `pack 0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11;` | -| php | `array(208, 58, 74, 238, 100, 17);` | -| python3 | `bytes([0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11])` | -| ruby | `[0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11]` | -| rust | `[u8; 6] = [0xd0, 0x3a, 0x4a, 0xee, 0x64, 0x11];` | -| swift | `[UInt8] = [0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11]` | +| Name | Example | +|:----------:|---------------------------------------------------------------------| +| c | `{0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11};` | +| c# | `new byte[]{0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11};` | +| java | `new byte[]{(byte) 0xD0, 0x3A, 0x4A, (byte) 0xEE, 0x64, 0x11};` | +| go | `[...]byte = {0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11}` | +| kotlin | `byteArrayOf(0xD0.toByte(), 0x3A, 0x4A, 0xEE.toByte(), 0x64, 0x11)` | +| node | `new Buffer([0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11]);` | +| javascript | `Uint8Array.from([0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11]);` | +| perl | `pack 0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11;` | +| php | `array(208, 58, 74, 238, 100, 17);` | +| python3 | `bytes([0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11])` | +| ruby | `[0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11]` | +| rust | `[u8; 6] = [0xd0, 0x3a, 0x4a, 0xee, 0x64, 0x11];` | +| swift | `[UInt8] = [0xD0, 0x3A, 0x4A, 0xEE, 0x64, 0x11]` | ### Other -| Name | Example | Description | -| ------------- | ------------- | ------------- | -| raw | `J”ýÿ¯í` | Prints the raw byte array encoded in ISO_8859_1 which does not change the byte output. Most useful with file output. | -| utf8 | `J�����` | Prints the byte array interpreted as UTF-8 encoded text. Only for testing purpose. | -| img | `▙▝▚░▓▃` | Prints a byte per character encoded in unicode block elements. | +| Name | Example | Description | +|------|-----------|----------------------------------------------------------------------------------------------------------------------| +| raw | `J”ýÿ¯í` | Prints the raw byte array encoded in ISO_8859_1 which does not change the byte output. Most useful with file output. | +| utf8 | `J�����` | Prints the byte array interpreted as UTF-8 encoded text. Only for testing purpose. | +| img | `▙▝▚░▓▃` | Prints a byte per character encoded in unicode block elements. | ## Digital Signatures ### Signed Jar -The provided JARs in the Github release page are signed with my private key: +The provided JARs in the GitHub release page are signed with my private key: CN=Patrick Favre-Bulle, OU=Private, O=PF Github Open Source, L=Vienna, ST=Vienna, C=AT Validity: Thu Sep 07 16:40:57 SGT 2017 to: Fri Feb 10 16:40:57 SGT 2034 @@ -172,7 +172,7 @@ All tags and commits by me are signed with git with my private key: ## Deterministic Random Bit Generation -As [cryptographically secure pseudorandom number generator](https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator), the [NIST SP800-90Ar1](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf) recommendation `HMAC-DRBG` is used in an implementation derived from the [google/rappor](https://github.com/google/rappor) project. HMAC-DRBG seems to be a [better choice than the also recommended HASH-DRBG approach](https://crypto.stackexchange.com/questions/1393/is-hmac-drbg-or-hash-drbg-stronger). [Java 9](http://openjdk.java.net/jeps/273) is expected to have it's own provider for it. There [is no known issue with Java's current SHA1-PRNG](https://security.stackexchange.com/questions/47871/how-securely-random-is-oracles-java-security-securerandom) implementation, but it is less studied thant the NIST recommendation. +As [cryptographically secure pseudorandom number generator](https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator), the [NIST SP800-90Ar1](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf) recommendation `HMAC-DRBG` is used in an implementation derived from the [google/rappor](https://github.com/google/rappor) project. HMAC-DRBG seems to be a [better choice than the also recommended HASH-DRBG approach](https://crypto.stackexchange.com/questions/1393/is-hmac-drbg-or-hash-drbg-stronger). [Java 9](http://openjdk.java.net/jeps/273) is expected to have its own provider for it. There [is no known issue with Java's current SHA1-PRNG](https://security.stackexchange.com/questions/47871/how-securely-random-is-oracles-java-security-securerandom) implementation, but it is less studied thant the NIST recommendation. This implementation uses HMAC-SHA512 internally and reseeds itself after 1 MiB of random data generation which is well below the maximum NIST @@ -181,7 +181,7 @@ recommendation. _References:_ * [Bruce Schneider: Proof that HMAC-DRBG has No Back Doors](https://www.schneier.com/blog/archives/2017/08/proof_that_hmac.html) -* [Formal Verficiation of the HMAC-DRBG Pseudo Random Number Generator](https://www.cs.cmu.edu/~kqy/resources/thesis.pdf) +* [Formal Verification of the HMAC-DRBG Pseudo Random Number Generator](https://www.cs.cmu.edu/~kqy/resources/thesis.pdf) * [Security Analysis of DRBG Using HMAC in NIST SP800-90Ar1](http://repo.flib.u-fukui.ac.jp/dspace/bitstream/10098/2126/1/art.pdf) ### Output Test Results @@ -193,14 +193,14 @@ The reports can be seen in `/misc/reports/*` in this repo. ### DRBG Seeding & Input Sources -A DRGB needs to be seeded by strong entropy sources so it can safely +A DRGB needs to be seeded by strong entropy sources, so it can safely be expanded to create unpredictable pseudo random output. SP800-90Ar1 defines different types of input for the DRGB. This implementation uses the following types: #### Entropy Input -This implementation uses multiple entropy sources to seed it's random +This implementation uses multiple entropy sources to seed its random bit generator. All these sources are combined and a weak source will not weaken the overall output. This ensures that even if one source fails the output is still cryptographically strong. Below is a detailed @@ -221,18 +221,18 @@ _Further reading:_ Per default the tool tries to fetch a seed from an external (supposedly true) random source. Because there are various opinions what technique delivers truly random data, this tool -incorporates 3 different services backed by different hardware RNG. Also to mitigate the fact -that if one ore more source is either compromised or produces predictable outcome, the other source +incorporates 3 different services backed by different hardware RNG. Also, to mitigate the fact +that if one or more source is either compromised or produces predictable outcome, the other source will mitigate that flaw. Using an external random might open a new attack vector if, for example, an attacker might read the seed send over the network. There are 2 measures against this: -* The connections is encrypted with TLS (ie. HTTPS) and the random +* The connections are encrypted with TLS (i.e. HTTPS) and the random is signed by the creator which will be verified by a local pinned certificate (only random.org). * The seed is only a part of the entropy source and the knowledge of it does not -make it possible to guess the random bits. Therefore there is no sole trust in +make it possible to guess the random bits. Therefore, there is no sole trust in an external service. Every generation of random data will see seeding from both local and external sources. @@ -255,7 +255,7 @@ _References:_ ###### ANU Quantum Random Numbers Server A quantum random number generator [offered by the Australian National University](https://qrng.anu.edu.au/). -The random numbers are generated in real-time by measuring the quantum fluctuations of the vacuum. The services provides +The random numbers are generated in real-time by measuring the quantum fluctuations of the vacuum. The services provide a TLS encrypted JSON/REST API. _References:_ @@ -269,7 +269,7 @@ be combined with the internal state of a strong `SecureRandom` instance. ##### Threaded Seed Generator -A port of SUN's threaded [seed generator](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/security/provider/SeedGenerator.java) by [Joshua Bloch](https://en.wikipedia.org/wiki/Joshua_Bloch). The seed is produced by counting the number of times the VM manages to loop in a given period. This number roughly reflects the machine load at that point in time. The samples are translated using a permutation (s-box) and then XORed together. This process is non linear and should prevent the samples from "averaging out". This implementation uses faster timings to produce values faster. +A port of SUN's threaded [seed generator](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/security/provider/SeedGenerator.java) by [Joshua Bloch](https://en.wikipedia.org/wiki/Joshua_Bloch). The seed is produced by counting the number of times the VM manages to loop in a given period. This number roughly reflects the machine load at that point in time. The samples are translated using a permutation (s-box) and then XORed together. This process is non-linear and should prevent the samples from "averaging out". This implementation uses faster timings to produce values faster. This generator is mainly used as a fallback if there is no external seed and the internal seeds fail. @@ -278,9 +278,9 @@ This generator is mainly used as a fallback if there is no external seed and the The nonce is composed of: * Monotonically increasing sequence number with a starting value of current JVM startup time -* System nano second time (which has arbitrary starting point) +* System nanosecond time (which has arbitrary starting point) * JVM uptime in milliseconds -* Current elapsed milliseconds since January 1, 1970 UTC. +* Current elapsed milliseconds since January 1, 1970, UTC. The four 8 byte values will be hashed with HKDF. @@ -327,10 +327,10 @@ Use maven (3.1+) to create a jar including all dependencies ### Checkstyle Config File This project uses my [`common-parent`](https://github.com/patrickfav/mvn-common-parent) which centralized a lot of -the plugin versions aswell as providing the checkstyle config rules. Specifically they are maintained in [`checkstyle-config`](https://github.com/patrickfav/checkstyle-config). Locally the files will be copied after you `mvnw install` into your `target` folder and is called +the plugin versions as well as providing the checkstyle config rules. Specifically they are maintained in [`checkstyle-config`](https://github.com/patrickfav/checkstyle-config). Locally the files will be copied after you `mvnw install` into your `target` folder and is called `target/checkstyle-checker.xml`. So if you use a plugin for your IDE, use this file as your local configuration. -## Tech Stack +## Tech-Stack * Java 8 * Maven diff --git a/src/main/java/at/favre/tools/dice/RndTool.java b/src/main/java/at/favre/tools/dice/RndTool.java index 4bf7ce1..819a464 100644 --- a/src/main/java/at/favre/tools/dice/RndTool.java +++ b/src/main/java/at/favre/tools/dice/RndTool.java @@ -88,9 +88,10 @@ static void execute(Arg arguments) throws AppException { throw new AppException("Count parameter must be greater than 0", 402); } - if ((arguments.count() != null && (arguments.count() * (long) arguments.length() > MAX_BYTE_PER_CALL)) - || (long) arguments.length() > MAX_BYTE_PER_CALL) { + if ((arguments.count() != null && (arguments.count() * (long) arguments.length() > MAX_BYTE_PER_CALL))) { throw new AppException("This PRNG can only generate " + MAX_BYTE_PER_CALL + " bytes at once.", 403); + } else { + arguments.length(); } if (arguments.outFile() != null && arguments.outFile().getParentFile() != null @@ -131,7 +132,7 @@ private static byte[] parseSeed(String seed) { } } - private static void wrapInErrorHandling(Arg arguments, Callable r) { + private static void wrapInErrorHandling(Arg arguments, Callable r) { try { r.call(); } catch (Exception e) { diff --git a/src/main/java/at/favre/tools/dice/rnd/DeterministicRandomBitGenerator.java b/src/main/java/at/favre/tools/dice/rnd/DeterministicRandomBitGenerator.java index 24e3c5d..dd17834 100644 --- a/src/main/java/at/favre/tools/dice/rnd/DeterministicRandomBitGenerator.java +++ b/src/main/java/at/favre/tools/dice/rnd/DeterministicRandomBitGenerator.java @@ -16,8 +16,6 @@ package at.favre.tools.dice.rnd; -import org.jetbrains.annotations.Nullable; - /** * A Deterministic Random Bit Generator as defined by NIST, will output * pseudo random data depending on a given seed. @@ -25,12 +23,12 @@ public interface DeterministicRandomBitGenerator { /** - * Requests a reseed of this DRBG. Uses the internal entropy sources, + * Requests a re-seed of this DRBG. Uses the internal entropy sources, * provided through {@link DrbgParameter} * * @param additionalInfo optional parameter to increase the security cushion see NIST SP 800-90Ar1 Section 8.7.2 */ - void requestReseed(@Nullable byte[] additionalInfo); + void requestReseed(byte[] additionalInfo); /** * Get the next pseudo random data @@ -47,5 +45,5 @@ public interface DeterministicRandomBitGenerator { * @param additionalInfo can be null, additional information that is used to increase the security cushion, * see NIST SP 800-90Ar1 Section 8.7.2 */ - void nextBytes(byte[] out, @Nullable byte[] additionalInfo); + void nextBytes(byte[] out, byte[] additionalInfo); } diff --git a/src/main/java/at/favre/tools/dice/rnd/DrbgParameter.java b/src/main/java/at/favre/tools/dice/rnd/DrbgParameter.java index 01cfeb1..ba50bba 100644 --- a/src/main/java/at/favre/tools/dice/rnd/DrbgParameter.java +++ b/src/main/java/at/favre/tools/dice/rnd/DrbgParameter.java @@ -17,7 +17,7 @@ package at.favre.tools.dice.rnd; public class DrbgParameter { - private static final int MAX_BYTES_PER_SEED = 1024 * 1024 * 1024; //1 MiB - increasing this value wont't enhance bandwidth + private static final int MAX_BYTES_PER_SEED = 1024 * 1024 * 1024; //1 MiB - increasing this value won't enhance bandwidth public final MacFactory macFactory; public final int securityStrengthBit; @@ -37,10 +37,6 @@ public DrbgParameter(MacFactory macFactory, ExpandableEntropySource entropySourc this.reseedIntervalByte = reseedIntervalByte; } - public DrbgParameter(MacFactory macFactory, ExpandableEntropySource entropySource, ExpandableEntropySource nonceSource, byte[] personalizationString, boolean reseedAllowed) { - this(macFactory, entropySource, nonceSource, personalizationString, reseedAllowed, MAX_BYTES_PER_SEED); - } - public DrbgParameter(MacFactory macFactory, ExpandableEntropySource entropySource, ExpandableEntropySource nonceSource, byte[] personalizationString) { this(macFactory, entropySource, nonceSource, personalizationString, true, MAX_BYTES_PER_SEED); } diff --git a/src/main/java/at/favre/tools/dice/rnd/EntropyPool.java b/src/main/java/at/favre/tools/dice/rnd/EntropyPool.java index bc28f6c..55a639a 100644 --- a/src/main/java/at/favre/tools/dice/rnd/EntropyPool.java +++ b/src/main/java/at/favre/tools/dice/rnd/EntropyPool.java @@ -25,7 +25,7 @@ public interface EntropyPool extends ExpandableEntropySource { /** * Add new entropy source to the pool * - * @param source + * @param source to add */ void add(ExpandableEntropySource source); } diff --git a/src/main/java/at/favre/tools/dice/rnd/ExpandableEntropySource.java b/src/main/java/at/favre/tools/dice/rnd/ExpandableEntropySource.java index f9927a2..06e2a4b 100644 --- a/src/main/java/at/favre/tools/dice/rnd/ExpandableEntropySource.java +++ b/src/main/java/at/favre/tools/dice/rnd/ExpandableEntropySource.java @@ -17,7 +17,7 @@ package at.favre.tools.dice.rnd; /** - * Interface for a entropy source with arbitrary length + * Interface for an entropy source with arbitrary length */ public interface ExpandableEntropySource { diff --git a/src/main/java/at/favre/tools/dice/rnd/HmacDrbg.java b/src/main/java/at/favre/tools/dice/rnd/HmacDrbg.java index ac58867..f8cb23e 100644 --- a/src/main/java/at/favre/tools/dice/rnd/HmacDrbg.java +++ b/src/main/java/at/favre/tools/dice/rnd/HmacDrbg.java @@ -17,7 +17,6 @@ package at.favre.tools.dice.rnd; import at.favre.lib.bytes.Bytes; -import org.jetbrains.annotations.Nullable; import javax.crypto.Mac; import java.util.Arrays; @@ -26,11 +25,11 @@ * Deterministic Random Bit Generator based on any HMAC implementation available to {@link Mac} *

* Also known as: HMAC_DRBG. - * See http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf for thorough specification. + * See NIST.SP.800-90Ar1 for thorough specification. *

* Reseeding and additional info is supported. *

- * See http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf Section 8.6.8. + * See NIST.SP.800-90Ar1 Section 8.6.8. */ public final class HmacDrbg implements DeterministicRandomBitGenerator { @@ -38,9 +37,9 @@ public final class HmacDrbg implements DeterministicRandomBitGenerator { private static final int MAX_BYTES_PER_REQUEST = 937; private static final byte[] BYTE_ARRAY_0 = {0}; private static final byte[] BYTE_ARRAY_1 = {1}; - private final DrbgParameter paramter; + private final DrbgParameter parameter; - // "V" from the the spec. + // "V" from the spec. private byte[] value; // An instance of HMAC configured with "Key" from the spec. private Mac hmac; @@ -59,7 +58,7 @@ public final class HmacDrbg implements DeterministicRandomBitGenerator { * @param drbgParameter parameter defining this DRBG */ public HmacDrbg(DrbgParameter drbgParameter) { - this.paramter = drbgParameter; + this.parameter = drbgParameter; // HMAC_DRBG Instantiate Process // See: http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf 10.1.1.2 @@ -87,16 +86,16 @@ private byte[] generateSeedMaterial() { // Note: We are using the 8.6.7 interpretation, where the entropy_input and // nonce are acquired at the same time from the same source. return Bytes.from( - paramter.entropySource.generateEntropy(getSecurityStrengthBytes()), - paramter.nonceSource.generateEntropy(getSecurityStrengthBytes() / 2), - paramter.personalizationString == null ? new byte[0] : paramter.personalizationString).array(); + parameter.entropySource.generateEntropy(getSecurityStrengthBytes()), + parameter.nonceSource.generateEntropy(getSecurityStrengthBytes() / 2), + parameter.personalizationString == null ? new byte[0] : parameter.personalizationString).array(); } /** * Set's the "Key" state from the spec. */ private void initHmac(byte[] key) { - hmac = paramter.macFactory.create(key); + hmac = parameter.macFactory.create(key); } /** @@ -125,8 +124,8 @@ private void hmacDrbgUpdate(byte[] providedData) { * This uses the provided entropy sources as well as an optional additionalInfo */ @Override - public void requestReseed(@Nullable byte[] additionalInfo) { - hmacDrbgReseed(paramter.entropySource.generateEntropy(getSecurityStrengthBytes()), paramter.nonceSource.generateEntropy(getSecurityStrengthBytes() / 2), additionalInfo); + public void requestReseed(byte[] additionalInfo) { + hmacDrbgReseed(parameter.entropySource.generateEntropy(getSecurityStrengthBytes()), parameter.nonceSource.generateEntropy(getSecurityStrengthBytes() / 2), additionalInfo); } /** @@ -180,10 +179,10 @@ private void hmacDrbgGenerate(byte[] out, int start, int count, byte[] additiona /** * Security Strength in Bits; depending on the used HMAC hash * - * @return bit length + * @return a bit length */ private int getSecurityStrengthBytes() { - return paramter.securityStrengthBit / 8; + return parameter.securityStrengthBit / 8; } /** @@ -220,7 +219,7 @@ private void generateBytesProcess(byte[] out, int start, int count, byte[] addit hmacDrbgUpdate(additionalInput); } - if (paramter.reseedAllowed && bytesGenerated + count > paramter.reseedIntervalByte) { + if (parameter.reseedAllowed && bytesGenerated + count > parameter.reseedIntervalByte) { requestReseed(null); } diff --git a/src/main/java/at/favre/tools/dice/rnd/MacFactory.java b/src/main/java/at/favre/tools/dice/rnd/MacFactory.java index 688ba8d..7eafc4c 100644 --- a/src/main/java/at/favre/tools/dice/rnd/MacFactory.java +++ b/src/main/java/at/favre/tools/dice/rnd/MacFactory.java @@ -64,7 +64,7 @@ public static MacFactory hmacSha512() { * Creates a factory creating HMAC with SHA-1 * * @return factory - * @deprecated sha1 with HMAC should be fine, but not recommended for new protocols; see https://crypto.stackexchange.com/questions/26510/why-is-hmac-sha1-still-considered-secure + * @deprecated sha1 with HMAC should be fine, but not recommended for new protocols; see why-is-hmac-sha1-still-considered-secure */ @Deprecated public static MacFactory hmacSha1() { diff --git a/src/main/java/at/favre/tools/dice/rnd/entropy/BCThreadedEntropySource.java b/src/main/java/at/favre/tools/dice/rnd/entropy/BCThreadedEntropySource.java index 26f410d..e9304ce 100644 --- a/src/main/java/at/favre/tools/dice/rnd/entropy/BCThreadedEntropySource.java +++ b/src/main/java/at/favre/tools/dice/rnd/entropy/BCThreadedEntropySource.java @@ -22,6 +22,7 @@ import java.nio.charset.StandardCharsets; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; +import java.util.concurrent.atomic.AtomicLong; /** * Threaded Seed Generator based on the one found in Bouncy Castle implementation diff --git a/src/main/java/at/favre/tools/dice/rnd/entropy/ExternalStrongSeedEntropySource.java b/src/main/java/at/favre/tools/dice/rnd/entropy/ExternalStrongSeedEntropySource.java index d38a02c..b0c60bd 100644 --- a/src/main/java/at/favre/tools/dice/rnd/entropy/ExternalStrongSeedEntropySource.java +++ b/src/main/java/at/favre/tools/dice/rnd/entropy/ExternalStrongSeedEntropySource.java @@ -24,8 +24,8 @@ /** * Used with external seeds that are estimated to be strong. The strong seed will - * used in quasi directly (only HKDF after each call will be preformed additional to - * adding an monotonic counter, to generate different outputs each call) + * be used in quasi directly (only HKDF after each call will be preformed additional to + * adding a monotonic counter, to generate different outputs each call) */ public final class ExternalStrongSeedEntropySource implements ExpandableEntropySource { private static final byte[] SALT = new byte[]{0x57, 0x58, 0x6E, (byte) 0x9A, 0x7C, (byte) 0xE4, 0x2E, 0x57, 0x61, 0x07, 0x18, (byte) 0xD9, (byte) 0x90, (byte) 0xFE, @@ -43,7 +43,7 @@ public ExternalStrongSeedEntropySource(byte[] seed) { } private void regenerateInternalSeed(byte[] seed) { - if (counter >= Long.MAX_VALUE) { + if (counter == Long.MAX_VALUE) { throw new IllegalStateException("counter reached max value (2^64)"); } diff --git a/src/main/java/at/favre/tools/dice/rnd/entropy/JDKThreadedEntropySource.java b/src/main/java/at/favre/tools/dice/rnd/entropy/JDKThreadedEntropySource.java index 28c6bec..ecf2faa 100644 --- a/src/main/java/at/favre/tools/dice/rnd/entropy/JDKThreadedEntropySource.java +++ b/src/main/java/at/favre/tools/dice/rnd/entropy/JDKThreadedEntropySource.java @@ -24,7 +24,7 @@ /** * This is a port of the Thread Seed Generator in SUN's SeedGenerator class. - * It use some faster timings which may make it less secure but the original + * It uses some faster timings which may make it less secure but the original * implementation is awfully slow (min 250 ms per byte). *

* This is the fallback if neither the personalization nor the secureRandom @@ -58,7 +58,7 @@ private static class ThreadedSeedGenerator implements Runnable { // data and using it to mix the trivial permutation. // It should be evenly distributed. The specific values // are not crucial to the security of this class. - private static byte[] rndTab = { + private static final byte[] rndTab = { 56, 30, -107, -6, -86, 25, -83, 75, -12, -64, 5, -128, 78, 21, 16, 32, 70, -81, 37, -51, -43, -46, -108, 87, 29, 17, -55, 22, -11, -111, @@ -89,7 +89,7 @@ private static class ThreadedSeedGenerator implements Runnable { // Thread group for our threads ThreadGroup seedGroup; // Queue is used to collect seed bytes - private byte[] pool; + private final byte[] pool; private int start, end, count; /** @@ -190,7 +190,7 @@ void getSeedBytes(byte[] result) { } byte getSeedByte() { - byte b = 0; + byte b; try { // Wait for it... diff --git a/src/main/java/at/favre/tools/dice/rnd/entropy/NonceEntropySource.java b/src/main/java/at/favre/tools/dice/rnd/entropy/NonceEntropySource.java index e9ca9e8..2345c44 100644 --- a/src/main/java/at/favre/tools/dice/rnd/entropy/NonceEntropySource.java +++ b/src/main/java/at/favre/tools/dice/rnd/entropy/NonceEntropySource.java @@ -26,9 +26,9 @@ /** * Nonce generate as described in SP800-90Ar1. This implementation uses a monotonic sequence number - * starting with the VM uptime time in millis and the current nano second timestamp + * starting with the VM uptime time in millis and the current nanosecond timestamp *

- * See http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf Section 8.6.7. + * See NIST.SP.800-90Ar1 Section 8.6.7. */ public final class NonceEntropySource implements ExpandableEntropySource { private static final byte[] SALT = new byte[]{0x48, (byte) 0xB8, (byte) 0x96, (byte) 0xC6, (byte) 0x87, 0x5C, (byte) 0xD0, (byte) 0xF9, (byte) 0x9D, @@ -44,7 +44,7 @@ public NonceEntropySource() { @Override public byte[] generateEntropy(int lengthByte) { - if (sequenceCounter >= Long.MAX_VALUE) { + if (sequenceCounter == Long.MAX_VALUE) { throw new IllegalStateException("sequence counter reached max value (2^64)"); } diff --git a/src/main/java/at/favre/tools/dice/rnd/entropy/PersonalizationSource.java b/src/main/java/at/favre/tools/dice/rnd/entropy/PersonalizationSource.java index e44247f..e305139 100644 --- a/src/main/java/at/favre/tools/dice/rnd/entropy/PersonalizationSource.java +++ b/src/main/java/at/favre/tools/dice/rnd/entropy/PersonalizationSource.java @@ -62,9 +62,9 @@ private byte[] readTempDirContent() { try (DirectoryStream stream = Files.newDirectoryStream(f.toPath())) { // We use a Random object to choose what file names - // should be used. Otherwise on a machine with too + // should be used. Otherwise, on a machine with too // many files, the same first 1024 files always get - // used. Any, We make sure the first 512 files are + // used. Anyway,we make sure the first 512 files are // always used. Random r = new Random(); for (Path entry : stream) { diff --git a/src/main/java/at/favre/tools/dice/service/ServiceHandler.java b/src/main/java/at/favre/tools/dice/service/ServiceHandler.java index c26c9e1..739e3e7 100644 --- a/src/main/java/at/favre/tools/dice/service/ServiceHandler.java +++ b/src/main/java/at/favre/tools/dice/service/ServiceHandler.java @@ -35,7 +35,7 @@ public interface ServiceHandler { Single> asObservable(); /** - * Get the user friendly and readable name for this service + * Get the user-friendly and readable name for this service * * @return name */ diff --git a/src/main/java/at/favre/tools/dice/service/anuquantum/AnuQuantumServiceHandler.java b/src/main/java/at/favre/tools/dice/service/anuquantum/AnuQuantumServiceHandler.java index 32633f3..b70d6d9 100644 --- a/src/main/java/at/favre/tools/dice/service/anuquantum/AnuQuantumServiceHandler.java +++ b/src/main/java/at/favre/tools/dice/service/anuquantum/AnuQuantumServiceHandler.java @@ -31,7 +31,7 @@ * ANU Quantum Random Numbers Server * Quantum true random number generator from Australian university *

- * See https://qrng.anu.edu.au/ + * See qrng.anu.edu.au */ public final class AnuQuantumServiceHandler extends AServiceHandler { static final int ENTROPY_SEED_LENGTH_BYTE = 24; @@ -58,7 +58,7 @@ public Result getRandom() { try { Response response = service.getRandom(createHeaderMap(), ENTROPY_SEED_LENGTH_BYTE).execute(); - if (response != null && response.isSuccessful() && response.body() != null) { + if (response.isSuccessful() && response.body() != null) { byte[] rawResponse = Bytes.parseHex(response.body().data.get(0)).array(); return new Result<>(getName(), rawResponse, response.body(), Duration.between(startTime, Instant.now()).toNanos()); } diff --git a/src/main/java/at/favre/tools/dice/service/randomorg/RandomOrgServiceHandler.java b/src/main/java/at/favre/tools/dice/service/randomorg/RandomOrgServiceHandler.java index b9c9446..a42707b 100644 --- a/src/main/java/at/favre/tools/dice/service/randomorg/RandomOrgServiceHandler.java +++ b/src/main/java/at/favre/tools/dice/service/randomorg/RandomOrgServiceHandler.java @@ -68,7 +68,7 @@ public Result getRandom() { final RandomOrgBlobRequest randomOrgBlobRequest = new RandomOrgBlobRequest(new RandomOrgBlobRequest.Params(k, 1, ENTROPY_SEED_LENGTH_BIT)); Response response = service.getRandom(createHeaderMap(), randomOrgBlobRequest).execute(); - if (response != null && response.isSuccessful() && response.body() != null) { + if (response.isSuccessful() && response.body() != null) { String rawResponse = response.body(); RandomOrgBlobResponse orgBlobResponse = new Gson().fromJson(rawResponse, RandomOrgBlobResponse.class); diff --git a/src/main/java/at/favre/tools/dice/service/randomorg/RandomOrgUtil.java b/src/main/java/at/favre/tools/dice/service/randomorg/RandomOrgUtil.java index f9c697b..bc14fd4 100644 --- a/src/main/java/at/favre/tools/dice/service/randomorg/RandomOrgUtil.java +++ b/src/main/java/at/favre/tools/dice/service/randomorg/RandomOrgUtil.java @@ -33,7 +33,7 @@ /** * Util for verifying the signature format of random.org's signed request *

- * See https://api.random.org/verify/manual + * See api.random.org */ final class RandomOrgUtil { static final String RANDOM_ORG_PUB_KEY = diff --git a/src/main/java/at/favre/tools/dice/ui/CLIParser.java b/src/main/java/at/favre/tools/dice/ui/CLIParser.java index 05a8c66..d46b328 100644 --- a/src/main/java/at/favre/tools/dice/ui/CLIParser.java +++ b/src/main/java/at/favre/tools/dice/ui/CLIParser.java @@ -119,7 +119,7 @@ private static Options setupOptions() { Options options = new Options(); Option count = Option.builder(ARG_COUNT).longOpt("count").argName("number").desc("How many randoms should be generated. Automatically chosen if this argument is omitted.").hasArgs().build(); - Option encodeing = Option.builder(ARG_ENCODING).longOpt("encoding").argName("string").hasArgs().desc("Output byte-to-text encoding. Available encodings include:\n" + new EncoderHandler().getSupportedEncodingList()).build(); + Option encoding = Option.builder(ARG_ENCODING).longOpt("encoding").argName("string").hasArgs().desc("Output byte-to-text encoding. Available encodings include:\n" + new EncoderHandler().getSupportedEncodingList()).build(); Option seed = Option.builder(ARG_SEED).longOpt("seed").argName("string|number").hasArgs().desc("Uses either the 64-bit integer interpretation or the utf-8 byte representation of given parameter to seed the internal random generator. Warns if entropy is low.").build(); Option debugOpt = Option.builder(ARG_DEBUG).longOpt("debug").hasArg(false).desc("Prints additional info for debugging.").build(); Option onlineOpt = Option.builder(ARG_ONLINE).longOpt("offline").hasArg(false).desc("Skips request to external random generators (random.org) for seeding (use when offline).").build(); @@ -136,7 +136,7 @@ private static Options setupOptions() { OptionGroup mainArgs = new OptionGroup(); options.addOptionGroup(mainArgs); - options.addOption(count).addOption(encodeing) + options.addOption(count).addOption(encoding) .addOption(seed).addOption(onlineOpt) .addOption(anuQuantumOpt) .addOption(urlencodeOpt).addOption(paddingOpt) diff --git a/src/main/java/at/favre/tools/dice/ui/ColumnRenderer.java b/src/main/java/at/favre/tools/dice/ui/ColumnRenderer.java index 1853f5f..4e57b01 100644 --- a/src/main/java/at/favre/tools/dice/ui/ColumnRenderer.java +++ b/src/main/java/at/favre/tools/dice/ui/ColumnRenderer.java @@ -43,7 +43,7 @@ public ColumnRenderer(EncoderFormat encoderFormat, RandomGenerator randomGenerat /** * Will take a list and a target count and tries to create even columns * - * @param targetCount approximate count you want to render (may be filled by the auto algorithm) + * @param targetCount approximate count you want to render (maybe filled by the auto algorithm) * @param outStream to write the output to * @return the actual used count */ @@ -128,7 +128,7 @@ public long render(long count, PrintStream outStream, boolean toFile) { } } else { - outStream.write(encoderFormat.asBytes(toFile ? encoderFormat.separatorFile() : encoderFormat.separatorFile())); + outStream.write(encoderFormat.asBytes(encoderFormat.separatorFile())); } } catch (Exception e) { throw new IllegalStateException("could not write random to output stream", e); diff --git a/src/test/java/at/favre/tools/dice/service/randomorg/RandomOrgServiceHandlerTest.java b/src/test/java/at/favre/tools/dice/service/randomorg/RandomOrgServiceHandlerTest.java index 6a22c0a..bb80f46 100644 --- a/src/test/java/at/favre/tools/dice/service/randomorg/RandomOrgServiceHandlerTest.java +++ b/src/test/java/at/favre/tools/dice/service/randomorg/RandomOrgServiceHandlerTest.java @@ -23,7 +23,7 @@ public void getRandom() throws Exception { response.throwable.printStackTrace(); } - if (response.throwable != null && response.throwable instanceof UnknownHostException) { + if (response.throwable instanceof UnknownHostException) { System.out.printf(response.errorMsg); } else { assertNotNull(response.seed); @@ -34,7 +34,7 @@ public void getRandom() throws Exception { assertNotEquals(-1, response.durationNanos); assertNotEquals(1, response.response); assertNotEquals(0, response.response.hashCode()); - assertEquals(response.seed.length, ENTROPY_SEED_LENGTH_BIT / 8); + assertEquals(ENTROPY_SEED_LENGTH_BIT / 8, response.seed.length); } } @@ -47,7 +47,6 @@ public void testResponseModel() { assertNotNull(response.toString()); assertNotEquals(0, response.hashCode()); - assertEquals(response, response); assertNotEquals("muh", response); }