mirror of https://github.com/apache/nifi.git
NIFI-8319 Added AES/CBC/NoPadding for decryption in EncryptContent Processor
Signed-off-by: Pierre Villard <pierre.villard.fr@gmail.com> This closes #4894.
This commit is contained in:
parent
8202bffc98
commit
a7ba5bb4f8
|
@ -49,7 +49,8 @@ public enum EncryptionMethod {
|
|||
SHA_TWOFISH("PBEWITHSHAANDTWOFISH-CBC", "BC", false, false),
|
||||
PGP("PGP", "BC", false, false),
|
||||
PGP_ASCII_ARMOR("PGP-ASCII-ARMOR", "BC", false, false),
|
||||
// New encryption methods which used keyed encryption
|
||||
// AES/CBC/NoPadding supported for decryption
|
||||
AES_CBC_NO_PADDING("AES/CBC/NoPadding", "BC", false, true),
|
||||
AES_CBC("AES/CBC/PKCS7Padding", "BC", false, true),
|
||||
AES_CTR("AES/CTR/NoPadding", "BC", false, true),
|
||||
AES_GCM("AES/GCM/NoPadding", "BC", false, true);
|
||||
|
|
|
@ -43,6 +43,8 @@ class AESKeyedCipherProviderGroovyTest {
|
|||
|
||||
private static final String KEY_HEX = "0123456789ABCDEFFEDCBA9876543210"
|
||||
|
||||
private static final String PLAINTEXT = "ExactBlockSizeRequiredForProcess"
|
||||
|
||||
private static final List<EncryptionMethod> keyedEncryptionMethods = EncryptionMethod.values().findAll { it.keyedCipher }
|
||||
|
||||
private static final SecretKey key = new SecretKeySpec(Hex.decodeHex(KEY_HEX as char[]), "AES")
|
||||
|
@ -73,8 +75,6 @@ class AESKeyedCipherProviderGroovyTest {
|
|||
// Arrange
|
||||
KeyedCipherProvider cipherProvider = new AESKeyedCipherProvider()
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : keyedEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -84,7 +84,7 @@ class AESKeyedCipherProviderGroovyTest {
|
|||
byte[] iv = cipher.getIV()
|
||||
logger.info("IV: ${Hex.encodeHexString(iv)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(em, key, iv, false)
|
||||
|
@ -93,7 +93,7 @@ class AESKeyedCipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,8 +102,6 @@ class AESKeyedCipherProviderGroovyTest {
|
|||
// Arrange
|
||||
KeyedCipherProvider cipherProvider = new AESKeyedCipherProvider()
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
keyedEncryptionMethods.each { EncryptionMethod em ->
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -113,7 +111,7 @@ class AESKeyedCipherProviderGroovyTest {
|
|||
// Initialize a cipher for encryption
|
||||
Cipher cipher = cipherProvider.getCipher(em, key, iv, true)
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(em, key, iv, false)
|
||||
|
@ -122,7 +120,7 @@ class AESKeyedCipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,8 +132,6 @@ class AESKeyedCipherProviderGroovyTest {
|
|||
KeyedCipherProvider cipherProvider = new AESKeyedCipherProvider()
|
||||
final List<Integer> LONG_KEY_LENGTHS = [192, 256]
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
SecureRandom secureRandom = new SecureRandom()
|
||||
|
||||
// Act
|
||||
|
@ -156,7 +152,7 @@ class AESKeyedCipherProviderGroovyTest {
|
|||
// Initialize a cipher for encryption
|
||||
Cipher cipher = cipherProvider.getCipher(em, localKey, iv, true)
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(em, localKey, iv, false)
|
||||
|
@ -165,7 +161,7 @@ class AESKeyedCipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -240,7 +236,7 @@ class AESKeyedCipherProviderGroovyTest {
|
|||
// Arrange
|
||||
KeyedCipherProvider cipherProvider = new AESKeyedCipherProvider()
|
||||
|
||||
final String PLAINTEXT = "This is a plaintext message."
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// These values can be generated by running `$ ./openssl_aes.rb` in the terminal
|
||||
final byte[] IV = Hex.decodeHex("e0bc8cc7fbc0bdfdc184dc22ce2fcb5b" as char[])
|
||||
|
@ -261,7 +257,7 @@ class AESKeyedCipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
assert plaintext.equals(recovered)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -269,8 +265,6 @@ class AESKeyedCipherProviderGroovyTest {
|
|||
// Arrange
|
||||
KeyedCipherProvider cipherProvider = new AESKeyedCipherProvider()
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
keyedEncryptionMethods.each { EncryptionMethod em ->
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -280,7 +274,7 @@ class AESKeyedCipherProviderGroovyTest {
|
|||
// Initialize a cipher for encryption
|
||||
Cipher cipher = cipherProvider.getCipher(em, key, iv, true)
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
def msg = shouldFail(IllegalArgumentException) {
|
||||
|
|
|
@ -42,6 +42,8 @@ import static groovy.test.GroovyAssert.shouldFail
|
|||
class Argon2CipherProviderGroovyTest extends GroovyTestCase {
|
||||
private static final Logger logger = LoggerFactory.getLogger(Argon2CipherProviderGroovyTest.class)
|
||||
|
||||
private static final String PLAINTEXT = "ExactBlockSizeRequiredForProcess"
|
||||
|
||||
private static List<EncryptionMethod> strongKDFEncryptionMethods
|
||||
|
||||
private static final int DEFAULT_KEY_LENGTH = 128
|
||||
|
@ -85,8 +87,6 @@ class Argon2CipherProviderGroovyTest extends GroovyTestCase {
|
|||
final String PASSWORD = "shortPassword"
|
||||
final byte[] SALT = cipherProvider.generateSalt()
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -96,7 +96,7 @@ class Argon2CipherProviderGroovyTest extends GroovyTestCase {
|
|||
byte[] iv = cipher.getIV()
|
||||
logger.info("IV: ${Hex.encodeHexString(iv)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(em, PASSWORD, SALT, iv, DEFAULT_KEY_LENGTH, false)
|
||||
|
@ -105,7 +105,7 @@ class Argon2CipherProviderGroovyTest extends GroovyTestCase {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,8 +210,6 @@ class Argon2CipherProviderGroovyTest extends GroovyTestCase {
|
|||
final byte[] SALT = cipherProvider.generateSalt()
|
||||
final byte[] IV = Hex.decodeHex("01" * 16 as char[])
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -220,7 +218,7 @@ class Argon2CipherProviderGroovyTest extends GroovyTestCase {
|
|||
Cipher cipher = cipherProvider.getCipher(em, PASSWORD, SALT, IV, DEFAULT_KEY_LENGTH, true)
|
||||
logger.info("IV: ${Hex.encodeHexString(IV)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(em, PASSWORD, SALT, IV, DEFAULT_KEY_LENGTH, false)
|
||||
|
@ -229,7 +227,7 @@ class Argon2CipherProviderGroovyTest extends GroovyTestCase {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,8 +242,6 @@ class Argon2CipherProviderGroovyTest extends GroovyTestCase {
|
|||
|
||||
final int LONG_KEY_LENGTH = 256
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -255,7 +251,7 @@ class Argon2CipherProviderGroovyTest extends GroovyTestCase {
|
|||
byte[] iv = cipher.getIV()
|
||||
logger.info("IV: ${Hex.encodeHexString(iv)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(em, PASSWORD, SALT, iv, LONG_KEY_LENGTH, false)
|
||||
|
@ -264,7 +260,7 @@ class Argon2CipherProviderGroovyTest extends GroovyTestCase {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -369,8 +365,6 @@ class Argon2CipherProviderGroovyTest extends GroovyTestCase {
|
|||
final byte[] SALT = cipherProvider.generateSalt()
|
||||
final byte[] IV = Hex.decodeHex("00" * 16 as char[])
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -379,7 +373,7 @@ class Argon2CipherProviderGroovyTest extends GroovyTestCase {
|
|||
Cipher cipher = cipherProvider.getCipher(em, PASSWORD, SALT, IV, DEFAULT_KEY_LENGTH, true)
|
||||
logger.info("IV: ${Hex.encodeHexString(IV)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
def msg = shouldFail(IllegalArgumentException) {
|
||||
|
@ -399,8 +393,6 @@ class Argon2CipherProviderGroovyTest extends GroovyTestCase {
|
|||
final byte[] SALT = cipherProvider.generateSalt()
|
||||
final byte[] IV = Hex.decodeHex("01" * 16 as char[])
|
||||
|
||||
final String PLAINTEXT = "This is a plaintext message."
|
||||
|
||||
final def VALID_KEY_LENGTHS = AES_KEY_LENGTHS
|
||||
EncryptionMethod encryptionMethod = EncryptionMethod.AES_CBC
|
||||
|
||||
|
@ -432,8 +424,6 @@ class Argon2CipherProviderGroovyTest extends GroovyTestCase {
|
|||
final byte[] SALT = cipherProvider.generateSalt()
|
||||
final byte[] IV = Hex.decodeHex("00" * 16 as char[])
|
||||
|
||||
final String PLAINTEXT = "This is a plaintext message."
|
||||
|
||||
final def INVALID_KEY_LENGTHS = [-1, 40, 64, 112, 512]
|
||||
EncryptionMethod encryptionMethod = EncryptionMethod.AES_CBC
|
||||
|
||||
|
|
|
@ -46,6 +46,8 @@ import static org.junit.Assert.assertTrue
|
|||
class BcryptCipherProviderGroovyTest {
|
||||
private static final Logger logger = LoggerFactory.getLogger(BcryptCipherProviderGroovyTest.class)
|
||||
|
||||
private static final String PLAINTEXT = "ExactBlockSizeRequiredForProcess"
|
||||
|
||||
private static List<EncryptionMethod> strongKDFEncryptionMethods
|
||||
|
||||
private static final int DEFAULT_KEY_LENGTH = 128
|
||||
|
@ -86,8 +88,6 @@ class BcryptCipherProviderGroovyTest {
|
|||
final String PASSWORD = "shortPassword"
|
||||
final byte[] SALT = cipherProvider.generateSalt()
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -97,7 +97,7 @@ class BcryptCipherProviderGroovyTest {
|
|||
byte[] iv = cipher.getIV()
|
||||
logger.info("IV: ${Hex.encodeHexString(iv)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(em, PASSWORD, SALT, iv, DEFAULT_KEY_LENGTH, false)
|
||||
|
@ -106,7 +106,7 @@ class BcryptCipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,8 +119,6 @@ class BcryptCipherProviderGroovyTest {
|
|||
final byte[] SALT = cipherProvider.generateSalt()
|
||||
final byte[] IV = Hex.decodeHex("01" * 16 as char[])
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -129,7 +127,7 @@ class BcryptCipherProviderGroovyTest {
|
|||
Cipher cipher = cipherProvider.getCipher(em, PASSWORD, SALT, IV, DEFAULT_KEY_LENGTH, true)
|
||||
logger.info("IV: ${Hex.encodeHexString(IV)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(em, PASSWORD, SALT, IV, DEFAULT_KEY_LENGTH, false)
|
||||
|
@ -138,7 +136,7 @@ class BcryptCipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,8 +153,6 @@ class BcryptCipherProviderGroovyTest {
|
|||
|
||||
final int LONG_KEY_LENGTH = 256
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -166,7 +162,7 @@ class BcryptCipherProviderGroovyTest {
|
|||
byte[] iv = cipher.getIV()
|
||||
logger.info("IV: ${Hex.encodeHexString(iv)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(em, PASSWORD, SALT, iv, LONG_KEY_LENGTH, false)
|
||||
|
@ -175,7 +171,7 @@ class BcryptCipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -389,8 +385,6 @@ class BcryptCipherProviderGroovyTest {
|
|||
final byte[] SALT = cipherProvider.generateSalt()
|
||||
final byte[] IV = Hex.decodeHex("00" * 16 as char[])
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -399,7 +393,7 @@ class BcryptCipherProviderGroovyTest {
|
|||
Cipher cipher = cipherProvider.getCipher(em, PASSWORD, SALT, IV, DEFAULT_KEY_LENGTH, true)
|
||||
logger.info("IV: ${Hex.encodeHexString(IV)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
def msg = shouldFail(IllegalArgumentException) {
|
||||
|
@ -420,8 +414,6 @@ class BcryptCipherProviderGroovyTest {
|
|||
final byte[] SALT = cipherProvider.generateSalt()
|
||||
final byte[] IV = Hex.decodeHex("01" * 16 as char[])
|
||||
|
||||
final String PLAINTEXT = "This is a plaintext message."
|
||||
|
||||
// Currently only AES ciphers are compatible with Bcrypt, so redundant to test all algorithms
|
||||
final def VALID_KEY_LENGTHS = AES_KEY_LENGTHS
|
||||
EncryptionMethod encryptionMethod = EncryptionMethod.AES_CBC
|
||||
|
@ -456,8 +448,6 @@ class BcryptCipherProviderGroovyTest {
|
|||
final byte[] SALT = cipherProvider.generateSalt()
|
||||
final byte[] IV = Hex.decodeHex("00" * 16 as char[])
|
||||
|
||||
final String PLAINTEXT = "This is a plaintext message."
|
||||
|
||||
// Currently only AES ciphers are compatible with Bcrypt, so redundant to test all algorithms
|
||||
final def INVALID_KEY_LENGTHS = [-1, 40, 64, 112, 512]
|
||||
EncryptionMethod encryptionMethod = EncryptionMethod.AES_CBC
|
||||
|
@ -520,8 +510,6 @@ class BcryptCipherProviderGroovyTest {
|
|||
byte[] keyDigestBytes = sha512.digest(hashOutputBytes[-31..-1] as byte[])
|
||||
logger.info("Key digest (${keyDigestBytes.length}): ${Hex.encodeHexString(keyDigestBytes)}")
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -531,7 +519,7 @@ class BcryptCipherProviderGroovyTest {
|
|||
byte[] iv = cipher.getIV()
|
||||
logger.info("IV: ${Hex.encodeHexString(iv)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(em, PASSWORD, SALT, iv, DEFAULT_KEY_LENGTH, false)
|
||||
|
@ -551,8 +539,8 @@ class BcryptCipherProviderGroovyTest {
|
|||
logger.info("Verified: ${verificationRecovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext == recovered
|
||||
assert plaintext == verificationRecovered
|
||||
assert PLAINTEXT == recovered
|
||||
assert PLAINTEXT == verificationRecovered
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -564,8 +552,6 @@ class BcryptCipherProviderGroovyTest {
|
|||
final String PASSWORD = "shortPassword"
|
||||
final byte[] SALT = cipherProvider.generateSalt()
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -575,7 +561,7 @@ class BcryptCipherProviderGroovyTest {
|
|||
byte[] iv = cipher.getIV()
|
||||
logger.info("IV: ${Hex.encodeHexString(iv)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getLegacyDecryptCipher(em, PASSWORD, SALT, iv, DEFAULT_KEY_LENGTH)
|
||||
|
@ -584,7 +570,7 @@ class BcryptCipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext == recovered
|
||||
assert PLAINTEXT == recovered
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -597,8 +583,6 @@ class BcryptCipherProviderGroovyTest {
|
|||
final byte[] SALT = null
|
||||
final EncryptionMethod em = EncryptionMethod.AES_CBC
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
||||
|
@ -610,7 +594,7 @@ class BcryptCipherProviderGroovyTest {
|
|||
}
|
||||
logger.expected("Encrypt error: ${encryptMsg}")
|
||||
|
||||
byte[] cipherBytes = plaintext.reverse().getBytes(StandardCharsets.UTF_8)
|
||||
byte[] cipherBytes = PLAINTEXT.reverse().getBytes(StandardCharsets.UTF_8)
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
def decryptMsg = shouldFail(IllegalArgumentException) {
|
||||
|
|
|
@ -40,7 +40,7 @@ class CipherUtilityGroovyTest extends GroovyTestCase {
|
|||
private static final List<String> SYMMETRIC_ALGORITHMS = EncryptionMethod.values().findAll { it.algorithm.startsWith("PBE") || it.algorithm.startsWith("AES") }*.algorithm
|
||||
private static final Map<String, List<String>> ALGORITHMS_MAPPED_BY_CIPHER = SYMMETRIC_ALGORITHMS.groupBy { String algorithm -> CIPHERS.find { algorithm.contains(it) } }
|
||||
|
||||
// Manually mapped as of 01/19/16 0.5.0
|
||||
// Manually mapped as of 03/21/21 1.13.0
|
||||
private static final Map<Integer, List<String>> ALGORITHMS_MAPPED_BY_KEY_LENGTH = [
|
||||
(40) : ["PBEWITHSHAAND40BITRC2-CBC",
|
||||
"PBEWITHSHAAND40BITRC4"],
|
||||
|
@ -56,18 +56,21 @@ class CipherUtilityGroovyTest extends GroovyTestCase {
|
|||
"PBEWITHSHAAND128BITRC2-CBC",
|
||||
"PBEWITHSHAAND128BITRC4",
|
||||
"PBEWITHSHAANDTWOFISH-CBC",
|
||||
"AES/CBC/NoPadding",
|
||||
"AES/CBC/PKCS7Padding",
|
||||
"AES/CTR/NoPadding",
|
||||
"AES/GCM/NoPadding"],
|
||||
(192): ["PBEWITHMD5AND192BITAES-CBC-OPENSSL",
|
||||
"PBEWITHSHA256AND192BITAES-CBC-BC",
|
||||
"PBEWITHSHAAND192BITAES-CBC-BC",
|
||||
"AES/CBC/NoPadding",
|
||||
"AES/CBC/PKCS7Padding",
|
||||
"AES/CTR/NoPadding",
|
||||
"AES/GCM/NoPadding"],
|
||||
(256): ["PBEWITHMD5AND256BITAES-CBC-OPENSSL",
|
||||
"PBEWITHSHA256AND256BITAES-CBC-BC",
|
||||
"PBEWITHSHAAND256BITAES-CBC-BC",
|
||||
"AES/CBC/NoPadding",
|
||||
"AES/CBC/PKCS7Padding",
|
||||
"AES/CTR/NoPadding",
|
||||
"AES/GCM/NoPadding"]
|
||||
|
|
|
@ -35,6 +35,8 @@ import static org.junit.Assert.assertTrue
|
|||
class PBKDF2CipherProviderGroovyTest {
|
||||
private static final Logger logger = LoggerFactory.getLogger(PBKDF2CipherProviderGroovyTest.class)
|
||||
|
||||
private static final String PLAINTEXT = "ExactBlockSizeRequiredForProcess"
|
||||
|
||||
private static List<EncryptionMethod> strongKDFEncryptionMethods
|
||||
|
||||
public static final String MICROBENCHMARK = "microbenchmark"
|
||||
|
@ -79,8 +81,6 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
final String PASSWORD = "shortPassword"
|
||||
final byte[] SALT = Hex.decodeHex(SALT_HEX as char[])
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -90,7 +90,7 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
byte[] iv = cipher.getIV()
|
||||
logger.info("IV: ${Hex.encodeHexString(iv)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(em, PASSWORD, SALT, iv, DEFAULT_KEY_LENGTH, false)
|
||||
|
@ -99,7 +99,7 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,8 +140,6 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
final byte[] SALT = Hex.decodeHex(SALT_HEX as char[])
|
||||
final byte[] IV = Hex.decodeHex(IV_HEX as char[])
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -150,7 +148,7 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
Cipher cipher = cipherProvider.getCipher(em, PASSWORD, SALT, IV, DEFAULT_KEY_LENGTH, true)
|
||||
logger.info("IV: ${Hex.encodeHexString(IV)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(em, PASSWORD, SALT, IV, DEFAULT_KEY_LENGTH, false)
|
||||
|
@ -159,7 +157,7 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,8 +174,6 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
|
||||
final int LONG_KEY_LENGTH = 256
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -187,7 +183,7 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
byte[] iv = cipher.getIV()
|
||||
logger.info("IV: ${Hex.encodeHexString(iv)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(em, PASSWORD, SALT, iv, LONG_KEY_LENGTH, false)
|
||||
|
@ -196,7 +192,7 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,7 +205,6 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
final byte[] SALT = Hex.decodeHex(SALT_HEX as char[])
|
||||
final byte[] IV = Hex.decodeHex(IV_HEX as char[])
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
final EncryptionMethod encryptionMethod = EncryptionMethod.AES_CBC
|
||||
String prf = ""
|
||||
|
||||
|
@ -232,7 +227,6 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
final byte[] SALT = Hex.decodeHex(SALT_HEX as char[])
|
||||
final byte[] IV = Hex.decodeHex(IV_HEX as char[])
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
final EncryptionMethod encryptionMethod = EncryptionMethod.AES_CBC
|
||||
|
||||
final PBKDF2CipherProvider SHA512_PROVIDER = new PBKDF2CipherProvider(DEFAULT_PRF, TEST_ITERATION_COUNT)
|
||||
|
@ -249,7 +243,7 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
Cipher cipher = cipherProvider.getCipher(encryptionMethod, PASSWORD, SALT, IV, DEFAULT_KEY_LENGTH, true)
|
||||
logger.info("IV: ${Hex.encodeHexString(IV)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = SHA512_PROVIDER.getCipher(encryptionMethod, PASSWORD, SALT, IV, DEFAULT_KEY_LENGTH, false)
|
||||
|
@ -258,7 +252,7 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -271,7 +265,6 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
final byte[] SALT = Hex.decodeHex(SALT_HEX as char[])
|
||||
final byte[] IV = Hex.decodeHex(IV_HEX as char[])
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
final EncryptionMethod encryptionMethod = EncryptionMethod.AES_CBC
|
||||
|
||||
// Act
|
||||
|
@ -286,7 +279,7 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
Cipher cipher = cipherProvider.getCipher(encryptionMethod, PASSWORD, SALT, IV, DEFAULT_KEY_LENGTH, true)
|
||||
logger.info("IV: ${Hex.encodeHexString(IV)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(encryptionMethod, PASSWORD, SALT, IV, DEFAULT_KEY_LENGTH, false)
|
||||
|
@ -295,7 +288,7 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,7 +327,6 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
RandomIVPBECipherProvider sha256CP = new PBKDF2CipherProvider("SHA-256", TEST_ITERATION_COUNT)
|
||||
RandomIVPBECipherProvider sha512CP = new PBKDF2CipherProvider("SHA-512", TEST_ITERATION_COUNT)
|
||||
|
||||
final String PLAINTEXT = "This is a plaintext message."
|
||||
final String PASSWORD = "thisIsABadPassword"
|
||||
final byte[] SALT = [0x11] * 16
|
||||
final byte[] IV = [0x22] * 16
|
||||
|
@ -370,8 +362,6 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
final byte[] SALT = Hex.decodeHex(SALT_HEX as char[])
|
||||
final byte[] IV = Hex.decodeHex(IV_HEX as char[])
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -380,7 +370,7 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
Cipher cipher = cipherProvider.getCipher(em, PASSWORD, SALT, IV, DEFAULT_KEY_LENGTH, true)
|
||||
logger.info("IV: ${Hex.encodeHexString(IV)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
def msg = shouldFail(IllegalArgumentException) {
|
||||
|
@ -426,8 +416,6 @@ class PBKDF2CipherProviderGroovyTest {
|
|||
final byte[] SALT = Hex.decodeHex(SALT_HEX as char[])
|
||||
final byte[] IV = Hex.decodeHex(IV_HEX as char[])
|
||||
|
||||
final String PLAINTEXT = "This is a plaintext message."
|
||||
|
||||
// Currently only AES ciphers are compatible with PBKDF2, so redundant to test all algorithms
|
||||
final def VALID_KEY_LENGTHS = AES_KEY_LENGTHS
|
||||
EncryptionMethod encryptionMethod = EncryptionMethod.AES_CBC
|
||||
|
|
|
@ -46,6 +46,8 @@ import static org.junit.Assert.assertTrue
|
|||
class ScryptCipherProviderGroovyTest {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ScryptCipherProviderGroovyTest.class)
|
||||
|
||||
private static final String PLAINTEXT = "ExactBlockSizeRequiredForProcess"
|
||||
|
||||
private static List<EncryptionMethod> strongKDFEncryptionMethods
|
||||
|
||||
private static final int DEFAULT_KEY_LENGTH = 128
|
||||
|
@ -88,8 +90,6 @@ class ScryptCipherProviderGroovyTest {
|
|||
final String PASSWORD = "shortPassword"
|
||||
final byte[] SALT = cipherProvider.generateSalt()
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -99,7 +99,7 @@ class ScryptCipherProviderGroovyTest {
|
|||
byte[] iv = cipher.getIV()
|
||||
logger.info("IV: ${Hex.encodeHexString(iv)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(em, PASSWORD, SALT, iv, DEFAULT_KEY_LENGTH, false)
|
||||
|
@ -108,7 +108,7 @@ class ScryptCipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,8 +119,6 @@ class ScryptCipherProviderGroovyTest {
|
|||
final byte[] SALT = cipherProvider.generateSalt()
|
||||
final byte[] IV = Hex.decodeHex("01" * 16 as char[])
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -129,7 +127,7 @@ class ScryptCipherProviderGroovyTest {
|
|||
Cipher cipher = cipherProvider.getCipher(em, PASSWORD, SALT, IV, DEFAULT_KEY_LENGTH, true)
|
||||
logger.info("IV: ${Hex.encodeHexString(IV)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(em, PASSWORD, SALT, IV, DEFAULT_KEY_LENGTH, false)
|
||||
|
@ -138,7 +136,7 @@ class ScryptCipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,8 +151,6 @@ class ScryptCipherProviderGroovyTest {
|
|||
|
||||
final int LONG_KEY_LENGTH = 256
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -164,7 +160,7 @@ class ScryptCipherProviderGroovyTest {
|
|||
byte[] iv = cipher.getIV()
|
||||
logger.info("IV: ${Hex.encodeHexString(iv)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
cipher = cipherProvider.getCipher(em, PASSWORD, SALT, iv, LONG_KEY_LENGTH, false)
|
||||
|
@ -173,7 +169,7 @@ class ScryptCipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -265,7 +261,6 @@ class ScryptCipherProviderGroovyTest {
|
|||
final String EXPECTED_FORMATTED_SALT = cipherProvider.formatSaltForScrypt(SALT)
|
||||
logger.info("Expected salt: ${EXPECTED_FORMATTED_SALT}")
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
EncryptionMethod encryptionMethod = EncryptionMethod.AES_CBC
|
||||
logger.info("Using algorithm: ${encryptionMethod.getAlgorithm()}")
|
||||
|
||||
|
@ -276,7 +271,7 @@ class ScryptCipherProviderGroovyTest {
|
|||
byte[] iv = cipher.getIV()
|
||||
logger.info("IV: ${Hex.encodeHexString(iv)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
// Manually initialize a cipher for decrypt with the expected salt
|
||||
|
@ -294,7 +289,7 @@ class ScryptCipherProviderGroovyTest {
|
|||
logger.info("Recovered: ${recovered}")
|
||||
|
||||
// Assert
|
||||
assert plaintext.equals(recovered)
|
||||
assert PLAINTEXT.equals(recovered)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -368,8 +363,6 @@ class ScryptCipherProviderGroovyTest {
|
|||
final byte[] SALT = cipherProvider.generateSalt()
|
||||
final byte[] IV = Hex.decodeHex("00" * 16 as char[])
|
||||
|
||||
final String plaintext = "This is a plaintext message."
|
||||
|
||||
// Act
|
||||
for (EncryptionMethod em : strongKDFEncryptionMethods) {
|
||||
logger.info("Using algorithm: ${em.getAlgorithm()}")
|
||||
|
@ -378,7 +371,7 @@ class ScryptCipherProviderGroovyTest {
|
|||
Cipher cipher = cipherProvider.getCipher(em, PASSWORD, SALT, IV, DEFAULT_KEY_LENGTH, true)
|
||||
logger.info("IV: ${Hex.encodeHexString(IV)}")
|
||||
|
||||
byte[] cipherBytes = cipher.doFinal(plaintext.getBytes("UTF-8"))
|
||||
byte[] cipherBytes = cipher.doFinal(PLAINTEXT.getBytes("UTF-8"))
|
||||
logger.info("Cipher text: ${Hex.encodeHexString(cipherBytes)} ${cipherBytes.length}")
|
||||
|
||||
def msg = shouldFail(IllegalArgumentException) {
|
||||
|
@ -398,8 +391,6 @@ class ScryptCipherProviderGroovyTest {
|
|||
final byte[] SALT = cipherProvider.generateSalt()
|
||||
final byte[] IV = Hex.decodeHex("01" * 16 as char[])
|
||||
|
||||
final String PLAINTEXT = "This is a plaintext message."
|
||||
|
||||
final def VALID_KEY_LENGTHS = AES_KEY_LENGTHS
|
||||
EncryptionMethod encryptionMethod = EncryptionMethod.AES_CBC
|
||||
|
||||
|
@ -431,8 +422,6 @@ class ScryptCipherProviderGroovyTest {
|
|||
final byte[] SALT = cipherProvider.generateSalt()
|
||||
final byte[] IV = Hex.decodeHex("00" * 16 as char[])
|
||||
|
||||
final String PLAINTEXT = "This is a plaintext message."
|
||||
|
||||
// Even though Scrypt can derive keys of arbitrary length, it will fail to validate if the underlying cipher does not support it
|
||||
final def INVALID_KEY_LENGTHS = [-1, 40, 64, 112, 512]
|
||||
// Currently only AES ciphers are compatible with Scrypt, so redundant to test all algorithms
|
||||
|
|
|
@ -322,8 +322,8 @@ public class EncryptContent extends AbstractProcessor {
|
|||
final String password = context.getProperty(PASSWORD).getValue();
|
||||
final KeyDerivationFunction kdf = KeyDerivationFunction.valueOf(context.getProperty(KEY_DERIVATION_FUNCTION).getValue());
|
||||
final String keyHex = context.getProperty(RAW_KEY_HEX).getValue();
|
||||
final boolean encrypt = context.getProperty(MODE).getValue().equalsIgnoreCase(ENCRYPT_MODE);
|
||||
if (isPGPAlgorithm(algorithm)) {
|
||||
final boolean encrypt = context.getProperty(MODE).getValue().equalsIgnoreCase(ENCRYPT_MODE);
|
||||
final String publicKeyring = context.getProperty(PUBLIC_KEYRING).getValue();
|
||||
final String publicUserId = context.getProperty(PUBLIC_KEY_USERID).getValue();
|
||||
final String privateKeyring = context.getProperty(PRIVATE_KEYRING).getValue();
|
||||
|
@ -334,7 +334,7 @@ public class EncryptContent extends AbstractProcessor {
|
|||
} else { // Not PGP
|
||||
boolean allowWeakCrypto = context.getProperty(ALLOW_WEAK_CRYPTO).getValue().equalsIgnoreCase(WEAK_CRYPTO_ALLOWED_NAME);
|
||||
if (encryptionMethod.isKeyedCipher()) { // Raw key or derived key from password
|
||||
validationResults.addAll(validateKeyed(encryptionMethod, kdf, keyHex, password, allowWeakCrypto));
|
||||
validationResults.addAll(validateKeyed(encryptionMethod, kdf, keyHex, password, allowWeakCrypto, encrypt));
|
||||
} else { // PBE
|
||||
validationResults.addAll(validatePBE(encryptionMethod, kdf, password, allowWeakCrypto));
|
||||
}
|
||||
|
@ -479,7 +479,7 @@ public class EncryptContent extends AbstractProcessor {
|
|||
}
|
||||
|
||||
|
||||
private List<ValidationResult> validateKeyed(EncryptionMethod encryptionMethod, KeyDerivationFunction kdf, String keyHex, String password, boolean allowWeakCrypto) {
|
||||
private List<ValidationResult> validateKeyed(EncryptionMethod encryptionMethod, KeyDerivationFunction kdf, String keyHex, String password, boolean allowWeakCrypto, boolean encrypt) {
|
||||
List<ValidationResult> validationResults = new ArrayList<>();
|
||||
boolean limitedStrengthCrypto = !CipherUtility.isUnlimitedStrengthCryptoSupported();
|
||||
|
||||
|
@ -526,6 +526,17 @@ public class EncryptContent extends AbstractProcessor {
|
|||
.explanation(KEY_DERIVATION_FUNCTION.getDisplayName() + " is required to be " + StringUtils.join(kdfsForKeyedCipher, ", ") + " when using algorithm " +
|
||||
encryptionMethod.getAlgorithm()).build());
|
||||
}
|
||||
|
||||
if (encrypt && EncryptionMethod.AES_CBC_NO_PADDING == encryptionMethod) {
|
||||
validationResults.add(new ValidationResult.Builder()
|
||||
.subject(ENCRYPTION_ALGORITHM.getDisplayName())
|
||||
.input(encryptionMethod.name())
|
||||
.explanation(String.format("Encryption not supported for [%s]", encryptionMethod.getAlgorithm()))
|
||||
.valid(false)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
return validationResults;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.apache.nifi.security.util.KeyDerivationFunction
|
|||
import org.apache.nifi.security.util.crypto.Argon2CipherProvider
|
||||
import org.apache.nifi.security.util.crypto.Argon2SecureHasher
|
||||
import org.apache.nifi.security.util.crypto.CipherUtility
|
||||
import org.apache.nifi.security.util.crypto.KeyedEncryptor
|
||||
import org.apache.nifi.security.util.crypto.PasswordBasedEncryptor
|
||||
import org.apache.nifi.security.util.crypto.RandomIVPBECipherProvider
|
||||
import org.apache.nifi.util.MockFlowFile
|
||||
|
@ -58,6 +59,8 @@ class TestEncryptContentGroovy {
|
|||
private static final String WEAK_CRYPTO_ALLOWED = EncryptContent.WEAK_CRYPTO_ALLOWED_NAME
|
||||
private static final String WEAK_CRYPTO_NOT_ALLOWED = EncryptContent.WEAK_CRYPTO_NOT_ALLOWED_NAME
|
||||
|
||||
private static final List<EncryptionMethod> SUPPORTED_KEYED_ENCRYPTION_METHODS = EncryptionMethod.values().findAll { it.isKeyedCipher() && it != EncryptionMethod.AES_CBC_NO_PADDING }
|
||||
|
||||
@BeforeClass
|
||||
static void setUpOnce() throws Exception {
|
||||
Security.addProvider(new BouncyCastleProvider())
|
||||
|
@ -198,15 +201,13 @@ class TestEncryptContentGroovy {
|
|||
Collection<ValidationResult> results
|
||||
MockProcessContext pc
|
||||
|
||||
def encryptionMethods = EncryptionMethod.values().findAll { it.isKeyedCipher() }
|
||||
|
||||
final int VALID_KEY_LENGTH = 128
|
||||
final String VALID_KEY_HEX = "ab" * (VALID_KEY_LENGTH / 8)
|
||||
logger.info("Using key ${VALID_KEY_HEX} (${VALID_KEY_HEX.length() * 4} bits)")
|
||||
|
||||
runner.setProperty(EncryptContent.MODE, EncryptContent.ENCRYPT_MODE)
|
||||
|
||||
encryptionMethods.each { EncryptionMethod encryptionMethod ->
|
||||
SUPPORTED_KEYED_ENCRYPTION_METHODS.each { EncryptionMethod encryptionMethod ->
|
||||
logger.info("Trying encryption method ${encryptionMethod.name()}")
|
||||
runner.setProperty(EncryptContent.ENCRYPTION_ALGORITHM, encryptionMethod.name())
|
||||
|
||||
|
@ -315,8 +316,7 @@ class TestEncryptContentGroovy {
|
|||
Collection<ValidationResult> results
|
||||
MockProcessContext pc
|
||||
|
||||
def keyedEncryptionMethods = EncryptionMethod.values().findAll { it.isKeyedCipher() }
|
||||
logger.info("Testing keyed encryption methods: ${keyedEncryptionMethods*.name()}")
|
||||
logger.info("Testing keyed encryption methods: ${SUPPORTED_KEYED_ENCRYPTION_METHODS*.name()}")
|
||||
|
||||
final int VALID_KEY_LENGTH = 128
|
||||
final String VALID_KEY_HEX = "ab" * (VALID_KEY_LENGTH / 8)
|
||||
|
@ -330,7 +330,7 @@ class TestEncryptContentGroovy {
|
|||
final def VALID_KDFS = KeyDerivationFunction.values().findAll { it.isStrongKDF() }
|
||||
|
||||
// Scenario 1 - RKH w/ KDF NONE & em in [CBC, CTR, GCM] (no password)
|
||||
keyedEncryptionMethods.each { EncryptionMethod kem ->
|
||||
SUPPORTED_KEYED_ENCRYPTION_METHODS.each { EncryptionMethod kem ->
|
||||
logger.info("Trying encryption method ${kem.name()} with KDF ${none.name()}")
|
||||
runner.setProperty(EncryptContent.ENCRYPTION_ALGORITHM, kem.name())
|
||||
runner.setProperty(EncryptContent.KEY_DERIVATION_FUNCTION, none.name())
|
||||
|
@ -440,9 +440,7 @@ class TestEncryptContentGroovy {
|
|||
testRunner.setProperty(EncryptContent.RAW_KEY_HEX, RAW_KEY_HEX)
|
||||
testRunner.setProperty(EncryptContent.KEY_DERIVATION_FUNCTION, KeyDerivationFunction.NONE.name())
|
||||
|
||||
def keyedCipherEMs = EncryptionMethod.values().findAll { it.isKeyedCipher() }
|
||||
|
||||
keyedCipherEMs.each { EncryptionMethod encryptionMethod ->
|
||||
SUPPORTED_KEYED_ENCRYPTION_METHODS.each { EncryptionMethod encryptionMethod ->
|
||||
logger.info("Attempting {}", encryptionMethod.name())
|
||||
testRunner.setProperty(EncryptContent.ENCRYPTION_ALGORITHM, encryptionMethod.name())
|
||||
testRunner.setProperty(EncryptContent.MODE, EncryptContent.ENCRYPT_MODE)
|
||||
|
@ -469,6 +467,33 @@ class TestEncryptContentGroovy {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDecryptAesCbcNoPadding() {
|
||||
final TestRunner testRunner = TestRunners.newTestRunner(new EncryptContent())
|
||||
final String RAW_KEY_HEX = "ab" * 16
|
||||
testRunner.setProperty(EncryptContent.RAW_KEY_HEX, RAW_KEY_HEX)
|
||||
testRunner.setProperty(EncryptContent.KEY_DERIVATION_FUNCTION, KeyDerivationFunction.NONE.name())
|
||||
testRunner.setProperty(EncryptContent.ENCRYPTION_ALGORITHM, EncryptionMethod.AES_CBC_NO_PADDING.name())
|
||||
testRunner.setProperty(EncryptContent.MODE, EncryptContent.DECRYPT_MODE)
|
||||
|
||||
final String content = "ExactBlockSizeRequiredForProcess"
|
||||
final byte[] bytes = content.getBytes(StandardCharsets.UTF_8)
|
||||
final ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)
|
||||
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream()
|
||||
|
||||
final KeyedEncryptor encryptor = new KeyedEncryptor(EncryptionMethod.AES_CBC_NO_PADDING, Hex.decodeHex(RAW_KEY_HEX))
|
||||
encryptor.encryptionCallback.process(inputStream, outputStream)
|
||||
outputStream.close()
|
||||
|
||||
final byte[] encrypted = outputStream.toByteArray()
|
||||
testRunner.enqueue(encrypted)
|
||||
testRunner.run()
|
||||
|
||||
testRunner.assertAllFlowFilesTransferred(EncryptContent.REL_SUCCESS, 1)
|
||||
MockFlowFile flowFile = testRunner.getFlowFilesForRelationship(EncryptContent.REL_SUCCESS).get(0)
|
||||
flowFile.assertContentEquals(content)
|
||||
}
|
||||
|
||||
// TODO: Implement
|
||||
@Test
|
||||
void testArgon2EncryptionShouldWriteAttributesWithEncryptionMetadata() throws IOException {
|
||||
|
|
Loading…
Reference in New Issue