Search in sources :

Example 1 with EncryptionMethod

use of org.apache.nifi.security.util.EncryptionMethod in project nifi by apache.

the class EncryptContent method onTrigger.

@Override
public void onTrigger(final ProcessContext context, final ProcessSession session) {
    FlowFile flowFile = session.get();
    if (flowFile == null) {
        return;
    }
    final ComponentLog logger = getLogger();
    final String method = context.getProperty(ENCRYPTION_ALGORITHM).getValue();
    final EncryptionMethod encryptionMethod = EncryptionMethod.valueOf(method);
    final String providerName = encryptionMethod.getProvider();
    final String algorithm = encryptionMethod.getAlgorithm();
    final String password = context.getProperty(PASSWORD).getValue();
    final KeyDerivationFunction kdf = KeyDerivationFunction.valueOf(context.getProperty(KEY_DERIVATION_FUNCTION).getValue());
    final boolean encrypt = context.getProperty(MODE).getValue().equalsIgnoreCase(ENCRYPT_MODE);
    Encryptor encryptor;
    StreamCallback callback;
    try {
        if (isPGPAlgorithm(algorithm)) {
            final String filename = flowFile.getAttribute(CoreAttributes.FILENAME.key());
            final String publicKeyring = context.getProperty(PUBLIC_KEYRING).getValue();
            final String privateKeyring = context.getProperty(PRIVATE_KEYRING).getValue();
            if (encrypt && publicKeyring != null) {
                final String publicUserId = context.getProperty(PUBLIC_KEY_USERID).getValue();
                encryptor = new OpenPGPKeyBasedEncryptor(algorithm, providerName, publicKeyring, publicUserId, null, filename);
            } else if (!encrypt && privateKeyring != null) {
                final char[] keyringPassphrase = context.getProperty(PRIVATE_KEYRING_PASSPHRASE).evaluateAttributeExpressions().getValue().toCharArray();
                encryptor = new OpenPGPKeyBasedEncryptor(algorithm, providerName, privateKeyring, null, keyringPassphrase, filename);
            } else {
                final char[] passphrase = Normalizer.normalize(password, Normalizer.Form.NFC).toCharArray();
                encryptor = new OpenPGPPasswordBasedEncryptor(algorithm, providerName, passphrase, filename);
            }
        } else if (kdf.equals(KeyDerivationFunction.NONE)) {
            // Raw key
            final String keyHex = context.getProperty(RAW_KEY_HEX).getValue();
            encryptor = new KeyedEncryptor(encryptionMethod, Hex.decodeHex(keyHex.toCharArray()));
        } else {
            // PBE
            final char[] passphrase = Normalizer.normalize(password, Normalizer.Form.NFC).toCharArray();
            encryptor = new PasswordBasedEncryptor(encryptionMethod, passphrase, kdf);
        }
        if (encrypt) {
            callback = encryptor.getEncryptionCallback();
        } else {
            callback = encryptor.getDecryptionCallback();
        }
    } catch (final Exception e) {
        logger.error("Failed to initialize {}cryption algorithm because - ", new Object[] { encrypt ? "en" : "de", e });
        session.rollback();
        context.yield();
        return;
    }
    try {
        final StopWatch stopWatch = new StopWatch(true);
        flowFile = session.write(flowFile, callback);
        logger.info("successfully {}crypted {}", new Object[] { encrypt ? "en" : "de", flowFile });
        session.getProvenanceReporter().modifyContent(flowFile, stopWatch.getElapsed(TimeUnit.MILLISECONDS));
        session.transfer(flowFile, REL_SUCCESS);
    } catch (final ProcessException e) {
        logger.error("Cannot {}crypt {} - ", new Object[] { encrypt ? "en" : "de", flowFile, e });
        session.transfer(flowFile, REL_FAILURE);
    }
}
Also used : FlowFile(org.apache.nifi.flowfile.FlowFile) KeyedEncryptor(org.apache.nifi.security.util.crypto.KeyedEncryptor) PasswordBasedEncryptor(org.apache.nifi.security.util.crypto.PasswordBasedEncryptor) KeyedEncryptor(org.apache.nifi.security.util.crypto.KeyedEncryptor) OpenPGPPasswordBasedEncryptor(org.apache.nifi.security.util.crypto.OpenPGPPasswordBasedEncryptor) OpenPGPKeyBasedEncryptor(org.apache.nifi.security.util.crypto.OpenPGPKeyBasedEncryptor) EncryptionMethod(org.apache.nifi.security.util.EncryptionMethod) ComponentLog(org.apache.nifi.logging.ComponentLog) OpenPGPKeyBasedEncryptor(org.apache.nifi.security.util.crypto.OpenPGPKeyBasedEncryptor) StreamCallback(org.apache.nifi.processor.io.StreamCallback) ProcessException(org.apache.nifi.processor.exception.ProcessException) DecoderException(org.apache.commons.codec.DecoderException) StopWatch(org.apache.nifi.util.StopWatch) KeyDerivationFunction(org.apache.nifi.security.util.KeyDerivationFunction) ProcessException(org.apache.nifi.processor.exception.ProcessException) OpenPGPPasswordBasedEncryptor(org.apache.nifi.security.util.crypto.OpenPGPPasswordBasedEncryptor) PasswordBasedEncryptor(org.apache.nifi.security.util.crypto.PasswordBasedEncryptor) OpenPGPPasswordBasedEncryptor(org.apache.nifi.security.util.crypto.OpenPGPPasswordBasedEncryptor)

Example 2 with EncryptionMethod

use of org.apache.nifi.security.util.EncryptionMethod in project nifi by apache.

the class TestEncryptContent method testRoundTrip.

@Test
public void testRoundTrip() throws IOException {
    final TestRunner testRunner = TestRunners.newTestRunner(new EncryptContent());
    testRunner.setProperty(EncryptContent.PASSWORD, "short");
    testRunner.setProperty(EncryptContent.KEY_DERIVATION_FUNCTION, KeyDerivationFunction.NIFI_LEGACY.name());
    // Must be allowed or short password will cause validation errors
    testRunner.setProperty(EncryptContent.ALLOW_WEAK_CRYPTO, "allowed");
    for (final EncryptionMethod encryptionMethod : EncryptionMethod.values()) {
        if (encryptionMethod.isUnlimitedStrength()) {
            // cannot test unlimited strength in unit tests because it's not enabled by the JVM by default.
            continue;
        }
        // KeyedCiphers tested in TestEncryptContentGroovy.groovy
        if (encryptionMethod.isKeyedCipher()) {
            continue;
        }
        logger.info("Attempting {}", encryptionMethod.name());
        testRunner.setProperty(EncryptContent.ENCRYPTION_ALGORITHM, encryptionMethod.name());
        testRunner.setProperty(EncryptContent.MODE, EncryptContent.ENCRYPT_MODE);
        testRunner.enqueue(Paths.get("src/test/resources/hello.txt"));
        testRunner.clearTransferState();
        testRunner.run();
        testRunner.assertAllFlowFilesTransferred(EncryptContent.REL_SUCCESS, 1);
        MockFlowFile flowFile = testRunner.getFlowFilesForRelationship(EncryptContent.REL_SUCCESS).get(0);
        testRunner.assertQueueEmpty();
        testRunner.setProperty(EncryptContent.MODE, EncryptContent.DECRYPT_MODE);
        testRunner.enqueue(flowFile);
        testRunner.clearTransferState();
        testRunner.run();
        testRunner.assertAllFlowFilesTransferred(EncryptContent.REL_SUCCESS, 1);
        logger.info("Successfully decrypted {}", encryptionMethod.name());
        flowFile = testRunner.getFlowFilesForRelationship(EncryptContent.REL_SUCCESS).get(0);
        flowFile.assertContentEquals(new File("src/test/resources/hello.txt"));
    }
}
Also used : MockFlowFile(org.apache.nifi.util.MockFlowFile) TestRunner(org.apache.nifi.util.TestRunner) EncryptionMethod(org.apache.nifi.security.util.EncryptionMethod) File(java.io.File) MockFlowFile(org.apache.nifi.util.MockFlowFile) Test(org.junit.Test)

Example 3 with EncryptionMethod

use of org.apache.nifi.security.util.EncryptionMethod in project nifi by apache.

the class AESProvenanceEventEncryptor method decrypt.

/**
 * Decrypts the provided byte[] (an encrypted record with accompanying metadata).
 *
 * @param encryptedRecord the encrypted record in byte[] form
 * @param recordId        an identifier for this record (eventId, generated, etc.)
 * @return the decrypted record
 * @throws EncryptionException if there is an issue decrypting this record
 */
@Override
public byte[] decrypt(byte[] encryptedRecord, String recordId) throws EncryptionException {
    if (encryptedRecord == null) {
        throw new EncryptionException("The encrypted provenance record cannot be missing");
    }
    EncryptionMetadata metadata;
    try {
        metadata = extractEncryptionMetadata(encryptedRecord);
    } catch (IOException | ClassNotFoundException e) {
        final String msg = "Encountered an error reading the encryption metadata: ";
        logger.error(msg, e);
        throw new EncryptionException(msg, e);
    }
    if (!SUPPORTED_VERSIONS.contains(metadata.version)) {
        throw new EncryptionException("The event was encrypted with version " + metadata.version + " which is not in the list of supported versions " + StringUtils.join(SUPPORTED_VERSIONS, ","));
    }
    if (keyProvider == null || !keyProvider.keyExists(metadata.keyId) || CryptoUtils.isEmpty(metadata.keyId)) {
        throw new EncryptionException("The requested key ID " + metadata.keyId + " is not available");
    } else {
        try {
            logger.debug("Decrypting provenance record " + recordId + " with key ID " + metadata.keyId);
            EncryptionMethod method = EncryptionMethod.forAlgorithm(metadata.algorithm);
            Cipher cipher = initCipher(method, Cipher.DECRYPT_MODE, keyProvider.getKey(metadata.keyId), metadata.ivBytes);
            // Strip the metadata away to get just the cipher bytes
            byte[] cipherBytes = extractCipherBytes(encryptedRecord, metadata);
            // Perform the actual decryption
            byte[] plainBytes = cipher.doFinal(cipherBytes);
            logger.debug("Decrypted provenance event record " + recordId + " with key ID " + metadata.keyId);
            return plainBytes;
        } catch (EncryptionException | BadPaddingException | IllegalBlockSizeException | KeyManagementException e) {
            final String msg = "Encountered an exception decrypting provenance record " + recordId;
            logger.error(msg, e);
            throw new EncryptionException(msg, e);
        }
    }
}
Also used : IllegalBlockSizeException(javax.crypto.IllegalBlockSizeException) IOException(java.io.IOException) EncryptionMethod(org.apache.nifi.security.util.EncryptionMethod) BadPaddingException(javax.crypto.BadPaddingException) KeyManagementException(java.security.KeyManagementException) Cipher(javax.crypto.Cipher)

Example 4 with EncryptionMethod

use of org.apache.nifi.security.util.EncryptionMethod in project nifi by apache.

the class StringEncryptor method decryptPBE.

private byte[] decryptPBE(byte[] cipherBytes) throws DecoderException {
    PBECipherProvider pbecp = (PBECipherProvider) cipherProvider;
    final EncryptionMethod encryptionMethod = EncryptionMethod.forAlgorithm(algorithm);
    // Extract salt
    int saltLength = CipherUtility.getSaltLengthForAlgorithm(algorithm);
    byte[] salt = new byte[saltLength];
    System.arraycopy(cipherBytes, 0, salt, 0, saltLength);
    byte[] actualCipherBytes = Arrays.copyOfRange(cipherBytes, saltLength, cipherBytes.length);
    // Determine necessary key length
    int keyLength = CipherUtility.parseKeyLengthFromAlgorithm(algorithm);
    // Generate cipher
    try {
        Cipher cipher = pbecp.getCipher(encryptionMethod, new String(password.getPassword()), salt, keyLength, false);
        // Decrypt the plaintext
        return cipher.doFinal(actualCipherBytes);
    } catch (Exception e) {
        throw new EncryptionException("Could not decrypt sensitive value", e);
    }
}
Also used : EncryptionMethod(org.apache.nifi.security.util.EncryptionMethod) Cipher(javax.crypto.Cipher) DecoderException(org.apache.commons.codec.DecoderException) PBECipherProvider(org.apache.nifi.security.util.crypto.PBECipherProvider)

Example 5 with EncryptionMethod

use of org.apache.nifi.security.util.EncryptionMethod in project nifi by apache.

the class StringEncryptor method encryptPBE.

private byte[] encryptPBE(String plaintext) {
    PBECipherProvider pbecp = (PBECipherProvider) cipherProvider;
    final EncryptionMethod encryptionMethod = EncryptionMethod.forAlgorithm(algorithm);
    // Generate salt
    byte[] salt;
    // NiFi legacy code determined the salt length based on the cipher block size
    if (pbecp instanceof NiFiLegacyCipherProvider) {
        salt = ((NiFiLegacyCipherProvider) pbecp).generateSalt(encryptionMethod);
    } else {
        salt = pbecp.generateSalt();
    }
    // Determine necessary key length
    int keyLength = CipherUtility.parseKeyLengthFromAlgorithm(algorithm);
    // Generate cipher
    try {
        Cipher cipher = pbecp.getCipher(encryptionMethod, new String(password.getPassword()), salt, keyLength, true);
        // Write IV if necessary (allows for future use of PBKDF2, Bcrypt, or Scrypt)
        // byte[] iv = new byte[0];
        // if (cipherProvider instanceof RandomIVPBECipherProvider) {
        // iv = cipher.getIV();
        // }
        // Encrypt the plaintext
        byte[] cipherBytes = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
        // byte[] rawBytes = CryptoUtils.concatByteArrays(salt, iv, cipherBytes);
        return CryptoUtils.concatByteArrays(salt, cipherBytes);
    } catch (Exception e) {
        throw new EncryptionException("Could not encrypt sensitive value", e);
    }
}
Also used : EncryptionMethod(org.apache.nifi.security.util.EncryptionMethod) Cipher(javax.crypto.Cipher) DecoderException(org.apache.commons.codec.DecoderException) PBECipherProvider(org.apache.nifi.security.util.crypto.PBECipherProvider) NiFiLegacyCipherProvider(org.apache.nifi.security.util.crypto.NiFiLegacyCipherProvider)

Aggregations

EncryptionMethod (org.apache.nifi.security.util.EncryptionMethod)10 KeyDerivationFunction (org.apache.nifi.security.util.KeyDerivationFunction)4 TestRunner (org.apache.nifi.util.TestRunner)4 Test (org.junit.Test)4 File (java.io.File)3 Cipher (javax.crypto.Cipher)3 DecoderException (org.apache.commons.codec.DecoderException)3 MockFlowFile (org.apache.nifi.util.MockFlowFile)3 ArrayList (java.util.ArrayList)2 ValidationResult (org.apache.nifi.components.ValidationResult)2 PBECipherProvider (org.apache.nifi.security.util.crypto.PBECipherProvider)2 IOException (java.io.IOException)1 KeyManagementException (java.security.KeyManagementException)1 BadPaddingException (javax.crypto.BadPaddingException)1 IllegalBlockSizeException (javax.crypto.IllegalBlockSizeException)1 AllowableValue (org.apache.nifi.components.AllowableValue)1 FlowFile (org.apache.nifi.flowfile.FlowFile)1 ComponentLog (org.apache.nifi.logging.ComponentLog)1 ProcessException (org.apache.nifi.processor.exception.ProcessException)1 StreamCallback (org.apache.nifi.processor.io.StreamCallback)1