This is an automated email from the ASF dual-hosted git repository.
alopresto pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/master by this push:
new 4d25b63 NIFI-1474 Added method to check p boundary. Added a unit
test. NIFI-1474 Added unit test for constructor p boundaries. Added p boundary
conditions. NIFI-1474 Updated documentation regarding p boundary. NIFI-1474
Added r validation and unit tests. Added Javadoc for new methods.
4d25b63 is described below
commit 4d25b6341ccba0ee24da15198d030d8132972e7c
Author: mtien <[email protected]>
AuthorDate: Wed Oct 23 17:34:37 2019 -0700
NIFI-1474 Added method to check p boundary. Added a unit test.
NIFI-1474 Added unit test for constructor p boundaries. Added p boundary
conditions.
NIFI-1474 Updated documentation regarding p boundary.
NIFI-1474 Added r validation and unit tests. Added Javadoc for new methods.
This closes #3844.
Signed-off-by: Andy LoPresto <[email protected]>
---
.../security/util/crypto/ScryptCipherProvider.java | 33 ++++++-
.../crypto/ScryptCipherProviderGroovyTest.groovy | 105 +++++++++++++++++++++
.../src/main/asciidoc/administration-guide.adoc | 2 +-
3 files changed, 138 insertions(+), 2 deletions(-)
diff --git
a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/crypto/ScryptCipherProvider.java
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/crypto/ScryptCipherProvider.java
index b532d8e..7bc1882 100644
---
a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/crypto/ScryptCipherProvider.java
+++
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/crypto/ScryptCipherProvider.java
@@ -25,6 +25,7 @@ import java.util.regex.Pattern;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
+
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
@@ -78,6 +79,36 @@ public class ScryptCipherProvider extends
RandomIVPBECipherProvider {
if (p < DEFAULT_P) {
logger.warn("The provided parallelization factor {} is below the
recommended minimum {}", p, DEFAULT_P);
}
+ if (!isPValid(r, p)) {
+ logger.warn("Based on the provided block size {}, the provided
parallelization factor {} is out of bounds", r, p);
+ throw new IllegalArgumentException("Invalid p value exceeds p
boundary");
+ }
+ }
+
+ /**
+ * Returns whether the provided parallelization factor (p value) is within
boundaries. The lower bound > 0 and the
+ * upper bound is calculated based on the provided block size (r value).
+ * @param r the block size in bytes
+ * @param p the parallelization factor
+ * @return true if p is within boundaries
+ */
+ public static boolean isPValid(int r, int p) {
+ if (!isRValid(r)){
+ logger.warn("The provided block size {} must be greater than 0",
r);
+ throw new IllegalArgumentException("Invalid r value; must be
greater than 0");
+ }
+ // Calculate p boundary
+ double pBoundary = ((Math.pow(2, 32)) - 1) * (32.0 / (r * 128));
+ return p <= pBoundary && p > 0;
+ }
+
+ /**
+ * Returns whether the provided block size (r value) is a positive integer
or not.
+ * @param r the block size in bytes
+ * @return true if r is a positive integer
+ */
+ public static boolean isRValid(int r) {
+ return r > 0;
}
/**
@@ -112,7 +143,7 @@ public class ScryptCipherProvider extends
RandomIVPBECipherProvider {
/**
* Returns an initialized cipher for the specified algorithm. The key (and
IV if necessary) are derived by the KDF of the implementation.
- *
+ * <p>
* The IV can be retrieved by the calling method using {@link
Cipher#getIV()}.
*
* @param encryptionMethod the {@link EncryptionMethod}
diff --git
a/nifi-commons/nifi-security-utils/src/test/groovy/org/apache/nifi/security/util/crypto/ScryptCipherProviderGroovyTest.groovy
b/nifi-commons/nifi-security-utils/src/test/groovy/org/apache/nifi/security/util/crypto/ScryptCipherProviderGroovyTest.groovy
index 0e469ab..7b912da 100644
---
a/nifi-commons/nifi-security-utils/src/test/groovy/org/apache/nifi/security/util/crypto/ScryptCipherProviderGroovyTest.groovy
+++
b/nifi-commons/nifi-security-utils/src/test/groovy/org/apache/nifi/security/util/crypto/ScryptCipherProviderGroovyTest.groovy
@@ -513,6 +513,111 @@ class ScryptCipherProviderGroovyTest {
assert params[2] == EXPECTED_P
}
+ @Test
+ void testShouldVerifyPBoundary() throws Exception {
+ // Arrange
+ final int r = 8;
+ final int p = 1;
+
+ // Act
+ boolean valid = ScryptCipherProvider.isPValid(r, p)
+
+ // Assert
+ assert valid
+ }
+
+ @Test
+ void testShouldFailPBoundary() throws Exception {
+ // Arrange
+ // The p upper bound is calculated with the formula below, when r = 8:
+ // pBoundary = ((Math.pow(2,32))-1) * (32.0/(r * 128)), where
pBoundary = 134217727.96875;
+ Map costParameters = [8:134217729, 128:8388608, 4096: 0]
+
+ // Act
+ def results = costParameters.collectEntries { r, p ->
+ def isValid = ScryptCipherProvider.isPValid(r, p)
+ [r, isValid]
+ }
+
+ // Assert
+ results.each { r, isPValid ->
+ logger.info("For r ${r}, p is ${isPValid}")
+ assert !isPValid
+ }
+ }
+
+ @Test
+ void testShouldVerifyRValue() throws Exception {
+ // Arrange
+ final int r = 8;
+
+ // Act
+ boolean valid = ScryptCipherProvider.isRValid(r)
+
+ // Assert
+ assert valid
+ }
+
+ @Test
+ void testShouldFailRValue() throws Exception {
+ // Arrange
+ final int r = 0;
+
+ // Act
+ boolean valid = ScryptCipherProvider.isRValid(r)
+
+ // Assert
+ assert !valid
+ }
+
+ @Test
+ void testShouldValidateScryptCipherProviderPBoundary() throws Exception {
+ // Arrange
+ final int n = 64;
+ final int r = 8;
+ final int p = 1;
+
+ // Act
+ ScryptCipherProvider testCipherProvider = new ScryptCipherProvider(n,
r, p)
+
+ // Assert
+ assert testCipherProvider
+ }
+
+ @Test
+ void testShouldCatchInvalidP() throws Exception {
+ // Arrange
+ final int n = 64;
+ final int r = 8;
+ final int p = 0;
+
+ // Act
+ def msg = shouldFail(IllegalArgumentException) {
+ ScryptCipherProvider testCipherProvider = new
ScryptCipherProvider(n, r, p)
+ }
+ logger.expected(msg)
+
+ // Assert
+ assert msg =~ "Invalid p value exceeds p boundary"
+ }
+
+ @Test
+ void testShouldCatchInvalidR() throws Exception {
+ // Arrange
+ final int n = 64;
+ final int r = 0;
+ final int p = 0;
+
+ // Act
+ def msg = shouldFail(IllegalArgumentException) {
+ ScryptCipherProvider testCipherProvider = new
ScryptCipherProvider(n, r, p)
+ }
+ logger.expected(msg)
+
+ // Assert
+ assert msg =~ "Invalid r value; must be greater than 0"
+ }
+
@Ignore("This test can be run on a specific machine to evaluate if the
default parameters are sufficient")
@Test
void testDefaultConstructorShouldProvideStrongParameters() {
diff --git a/nifi-docs/src/main/asciidoc/administration-guide.adoc
b/nifi-docs/src/main/asciidoc/administration-guide.adoc
index 81fb811..07b0a46 100644
--- a/nifi-docs/src/main/asciidoc/administration-guide.adoc
+++ b/nifi-docs/src/main/asciidoc/administration-guide.adoc
@@ -1392,7 +1392,7 @@ Here are the KDFs currently supported by NiFi (primarily
in the `EncryptContent`
* Scrypt
** This KDF was added in v0.5.0.
** link:https://en.wikipedia.org/wiki/Scrypt[Scrypt^] is an adaptive function
designed in response to `bcrypt`. This KDF is recommended as it requires
relatively large amounts of memory for each derivation, making it resistant to
hardware brute-force attacks.
-** The recommended minimum cost is `N`=2^14^, `r`=8, `p`=1 (as of 2/1/2016 on
commodity hardware) and should be increased to the threshold at which
legitimate systems will encounter detrimental delays (see schedule below or use
`ScryptCipherProviderGroovyTest#testDefaultConstructorShouldProvideStrongParameters()`
to calculate safe minimums).
+** The recommended minimum cost is `N`=2^14^, `r`=8, `p`=1 (as of 2/1/2016 on
commodity hardware). `p` must be a positive integer and less than `(2^32 − 1) *
(Hlen/MFlen)` where `Hlen` is the length in octets of the digest function
output (32 for SHA-256) and `MFlen` is the length in octets of the mixing
function output, defined as `r * 128`. These parameters should be increased to
the threshold at which legitimate systems will encounter detrimental delays
(see schedule below or use `Scr [...]
** The salt format is `$s0$e0101$ABCDEFGHIJKLMNOPQRSTUV`. The salt is
delimited by `$` and the three sections are as follows:
*** `s0` - the version of the format. NiFi currently uses `s0` for all salts
generated internally.
*** `e0101` - the cost parameters. This is actually a hexadecimal encoding of
`N`, `r`, `p` using shifts. This can be formed/parsed using
`Scrypt#encodeParams()` and `Scrypt#parseParameters()`.