You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@nifi.apache.org by GitBox <gi...@apache.org> on 2023/01/03 17:55:32 UTC

[GitHub] [nifi] exceptionfactory opened a new pull request, #6821: NIFI-11022 Add DecryptContent Compatibility Processors

exceptionfactory opened a new pull request, #6821:
URL: https://github.com/apache/nifi/pull/6821

   # Summary
   
   [NIFI-11022](https://issues.apache.org/jira/browse/NIFI-11022) Adds the following new Processors to support decryption of content encrypted using the `EncryptContent` Processor:
   
   - `DecryptContentCompatibilityMode`
   - `DecryptContentEncoded`
   
   A new `nifi-cipher-bundle` with `nifi-cipher-nar` module contains the new Processors. A new `nifi-security-crypto-key` module in `nifi-commons` provides standard interfaces and implementations of strong Key Derivation Functions using Bouncy Castle components.
   
   The purpose of the new Processors is to maintain components that are capable of decrypting historical information without needing to maintain encryption of insecure and custom formats.
   
   ## DecryptContentCompatibilityMode
   
   The `DecryptContentCompatibilityMode` Processor focuses on legacy Password-Based Encryption algorithms, many of which are defined in [RFC 8018](https://www.rfc-editor.org/rfc/rfc8018). The Processor supports a `Key Derivation Strategy` using either [OpenSSL EVP BytesToKey](https://www.openssl.org/docs/man3.0/man3/EVP_BytesToKey.html) or [Jasypt Java simplified encryption](http://www.jasypt.org/). These settings map to the OpenSSL and NiFi Legacy settings in the `EncryptContent` Processor. Neither of these key derivation strategies meet the security requirements of modern cryptography, so the `DecryptContentCompatibilityMode` Processor exists exclusively to provide compatibility with historical modes of encryption. This Processor relies on the Bouncy Castle Security Provider to support cipher operations, but avoids global registration of the provider.
   
   ## DecryptContentEncoded
   
   The `DecryptContentEncoded` Processor focuses on newer Key Derivation Functions, supporting Argon2, bcrypt, PBKDF2, and scrypt algorithms. The Processor supports selection of `Cipher Algorithm Mode` and `Cipher Algorithm Padding`, defaulting to `GCM` and `NoPadding` respectively. These settings match the default configuration of `EncryptContent` for the AES symmetric cipher. The `EncryptContent` Processor and supporting implementation components write encrypted content using a format that is specific to Apache NiFi, and also write the content header using a standard byte format specific to each support Key Derivation Function. The `DecryptContentEncoded` Processor leverages this standard byte formatting to determine the appropriate Key Derivation Function for decryption. The Processor supports a `Key Specification Format` property, defaulting to `PASSWORD`, but also allowing `RAW` to enable configuration of a raw key encoded as a hexadecimal string. Both the `DecryptContentEncoded
 ` Processor and the supporting `nifi-security-crypto-key` library include extensive tests to exercise byte format detection and cipher algorithm configurations.
   
   # Tracking
   
   Please complete the following tracking steps prior to pull request creation.
   
   ### Issue Tracking
   
   - [X] [Apache NiFi Jira](https://issues.apache.org/jira/browse/NIFI) issue created
   
   ### Pull Request Tracking
   
   - [X] Pull Request title starts with Apache NiFi Jira issue number, such as `NIFI-00000`
   - [X] Pull Request commit message starts with Apache NiFi Jira issue number, as such `NIFI-00000`
   
   ### Pull Request Formatting
   
   - [X] Pull Request based on current revision of the `main` branch
   - [X] Pull Request refers to a feature branch with one commit containing changes
   
   # Verification
   
   Please indicate the verification steps performed prior to pull request creation.
   
   ### Build
   
   - [X] Build completed using `mvn clean install -P contrib-check`
     - [X] JDK 8
     - [X] JDK 11
     - [X] JDK 17
   
   ### Licensing
   
   - [ ] New dependencies are compatible with the [Apache License 2.0](https://apache.org/licenses/LICENSE-2.0) according to the [License Policy](https://www.apache.org/legal/resolved.html)
   - [ ] New dependencies are documented in applicable `LICENSE` and `NOTICE` files
   
   ### Documentation
   
   - [ ] Documentation formatting appears as expected in rendered files
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@nifi.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nifi] greyp9 commented on pull request #6821: NIFI-11022 Add DecryptContent Compatibility Processors

Posted by "greyp9 (via GitHub)" <gi...@apache.org>.
greyp9 commented on PR #6821:
URL: https://github.com/apache/nifi/pull/6821#issuecomment-1401120102

   @exceptionfactory this all looks really cool, thanks for the effort!
   
   Did some usage testing, and wanted to share some feedback.  I plan to follow up with a pass at the code.
   
   - The sample flow attached to the JIRA was really helpful to me to give a sense of the depth of permutations.  It occurs to me that those nine sample configurations might form the basis of some helpful user documentation.  Something like a table that describes, for a particular `EncryptContent` configuration, what an equivalent `DecryptContentEncoded`/`DecryptContentCompatibility` configuration should be.
   
     - EncryptContent 
   Key Derivation Function = NiFi Legacy KDF
   Encryption Algorithm = MD5_DES
   
     - DecryptContentCompatibilityMode
   Encryption Scheme = PBE_WITH_MD5_AND_DES
   Key Derivation Strategy = JASYPT_STANDARD
   
     If not in the user documentation somewhere, maybe some other reference-able place.  The nine samples give a good sense of the configurability; no need to document every permutation.
   
   - After a FlowFile has gone through an encrypt / decrypt processor pair, should any of the `encryptcontent.*` attributes be stripped out of the FF attribute set?  Not sure if that breaks an existing FF convention, but if those are left over, they might confuse downstream processors, or lead to IV reuse, for example.
   
   - It looks like the encryption algorithms are specified in `EncryptionMethod` (for `EncryptContent`) and `CompatibilityModeEncryptionScheme` (for `DecryptContentCompatibilityMode`).  What do you think of these being alphabetized in the UI listbox?  The choices matching `DecryptContentCompatibilityMode` `PBE_WITH_MD5_*` appear in two separate groupings in the UI listbox.
   
   - `org.jasypt` has released a `1.9.3` version.  Might this be a good time to consider bumping the version dependency?
   
   - When specifying a raw key (for `Key Specification Format`), it might be nice for the tooltip to provide a hint as to the number of hex characters expected.  There might not be a single answer, given that many algorithms (AES) have implementations with multiple key sizes.  Maybe some blurb along the lines of:
     > Advanced Encryption Standard (AES) keys are symmetric keys that can be three different key lengths (128, 192, or 256 bits).
   
     This may be better handled as follow on work.
   
   - In my usage testing, I was swapping back and forth between use of `Password` versus `Raw Key (hexidecimal)`, using parameters `#{MyPassword}` and `#{MyRawKey}`.  These are two distinct properties in `EncryptContent`.  But in `DecryptContentEncoded`, one property is overridden to provide storage for both `Key Specification Format` options.  It might be nice for these to be two distinct properties, so changing the format does not require changing the key specification value.  These could be presented in the UI the same way using `PropertyDependency`.
   
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@nifi.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nifi] exceptionfactory commented on a diff in pull request #6821: NIFI-11022 Add DecryptContent Compatibility Processors

Posted by "exceptionfactory (via GitHub)" <gi...@apache.org>.
exceptionfactory commented on code in PR #6821:
URL: https://github.com/apache/nifi/pull/6821#discussion_r1088228234


##########
nifi-nar-bundles/nifi-cipher-bundle/nifi-cipher-processors/src/main/resources/docs/org.apache.nifi.processors.cipher.DecryptContentCompatibilityMode/additionalDetails.html:
##########
@@ -0,0 +1,144 @@
+<!DOCTYPE html>
+<html lang="en">
+  <!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+        http://www.apache.org/licenses/LICENSE-2.0
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+  -->
+  <head>
+    <meta charset="UTF-8">
+    <title>DecryptContentCompatibilityMode</title>
+    <link rel="stylesheet" href="../../../../../css/component-usage.css" type="text/css" />
+  </head>
+  <body>
+    <h2>Summary</h2>
+    <p>
+      This Processor supports decryption using legacy formats and Password-Based Encryption Algorithms.
+      <a href="https://www.rfc-editor.org/rfc/rfc8018">RFC 8018</a> defines the Password-Based Cryptography

Review Comment:
   Good point, adding the `target` attribute to the tag should help by opening it in a new window.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@nifi.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nifi] exceptionfactory commented on pull request #6821: NIFI-11022 Add DecryptContent Compatibility Processors

Posted by GitBox <gi...@apache.org>.
exceptionfactory commented on PR #6821:
URL: https://github.com/apache/nifi/pull/6821#issuecomment-1370170118

   The [DecryptContent Flow](https://issues.apache.org/jira/secure/attachment/13054291/DecryptContent_Flow.json) attached to [NIFI-11022](https://issues.apache.org/jira/browse/NIFI-11022) includes multiple Process Group configurations with `EncryptContent` and the new `DecryptContent` Processors.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@nifi.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nifi] greyp9 commented on a diff in pull request #6821: NIFI-11022 Add DecryptContent Compatibility Processors

Posted by "greyp9 (via GitHub)" <gi...@apache.org>.
greyp9 commented on code in PR #6821:
URL: https://github.com/apache/nifi/pull/6821#discussion_r1088182867


##########
nifi-nar-bundles/nifi-cipher-bundle/nifi-cipher-processors/src/main/java/org/apache/nifi/processors/cipher/compatibility/CompatibilityModeEncryptionScheme.java:
##########
@@ -0,0 +1,216 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.processors.cipher.compatibility;
+
+import org.apache.nifi.processors.cipher.algorithm.SymmetricCipher;
+import org.apache.nifi.processors.cipher.algorithm.DigestAlgorithm;
+import org.apache.nifi.components.DescribedValue;
+
+import static org.apache.nifi.processors.cipher.algorithm.SymmetricCipher.AES;
+import static org.apache.nifi.processors.cipher.algorithm.SymmetricCipher.DES;
+import static org.apache.nifi.processors.cipher.algorithm.SymmetricCipher.DESEDE;
+import static org.apache.nifi.processors.cipher.algorithm.SymmetricCipher.RC2;
+import static org.apache.nifi.processors.cipher.algorithm.SymmetricCipher.RC4;
+import static org.apache.nifi.processors.cipher.algorithm.SymmetricCipher.TWOFISH;
+
+/**
+ * Compatibility Mode Encryption Schemes supporting decryption using legacy algorithms such as PBES1 defined in RFC 8018 Section 6.1
+ */
+public enum CompatibilityModeEncryptionScheme implements DescribedValue {
+    PBE_WITH_MD5_AND_AES_CBC_128(
+            "PBEWITHMD5AND128BITAES-CBC-OPENSSL",
+            DigestAlgorithm.MD5,
+            AES,
+            "PKCS12 with MD5 digest and Advanced Encryption Standard in Cipher Block Chaining mode using 128 bit keys."
+    ),
+
+    PBE_WITH_MD5_AND_AES_CBC_192(
+            "PBEWITHMD5AND192BITAES-CBC-OPENSSL",
+            DigestAlgorithm.MD5,
+            AES,
+            "PKCS12 with MD5 digest and Advanced Encryption Standard in Cipher Block Chaining mode using 192 bit keys."
+    ),
+
+    PBE_WITH_MD5_AND_AES_CBC_256(
+            "PBEWITHMD5AND256BITAES-CBC-OPENSSL",
+            DigestAlgorithm.MD5,
+            AES,
+            "PKCS12 with MD5 digest and Advanced Encryption Standard in Cipher Block Chaining mode using 256 bit keys."
+    ),
+
+    PBE_WITH_MD5_AND_DES(
+            "PBEWITHMD5ANDDES",
+            DigestAlgorithm.MD5,
+            DES,
+            "PKCS5 Scheme 1 with MD5 digest and Data Encryption Standard 64 bit keys. OID 1.2.840.113549.1.5.3"

Review Comment:
   > PKCS5
   
   Is this a typo?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@nifi.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nifi] greyp9 closed pull request #6821: NIFI-11022 Add DecryptContent Compatibility Processors

Posted by "greyp9 (via GitHub)" <gi...@apache.org>.
greyp9 closed pull request #6821: NIFI-11022 Add DecryptContent Compatibility Processors
URL: https://github.com/apache/nifi/pull/6821


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@nifi.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nifi] exceptionfactory commented on pull request #6821: NIFI-11022 Add DecryptContent Compatibility Processors

Posted by "exceptionfactory (via GitHub)" <gi...@apache.org>.
exceptionfactory commented on PR #6821:
URL: https://github.com/apache/nifi/pull/6821#issuecomment-1405659129

   Thanks for the feedback @greyp9, I updated the RFC 8018 link and renamed the Processors as follows:
   
   - Renamed `DecryptContentEncoded` to `DecryptContent`
   - Renamed `DecryptContentCompatibilityMode` to `DecryptContentCompatibility`


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@nifi.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nifi] exceptionfactory commented on pull request #6821: NIFI-11022 Add DecryptContent Compatibility Processors

Posted by "exceptionfactory (via GitHub)" <gi...@apache.org>.
exceptionfactory commented on PR #6821:
URL: https://github.com/apache/nifi/pull/6821#issuecomment-1402036808

   Thanks for the thorough testing and feedback @greyp9!
   
   In response to your notes:
   
   1. I agree that including some additional documentation for these Processors describing the mapping between configuration settings would be helpful. Creating additional details documents for these two Processors seems like a good starting location. There is more general encryption documentation in the Administrator's Guide, which could be updated separately when we are ready to deprecate the EncryptContent Processor.
   
   2. The EncryptContent FlowFile attributes were at one time intended to support simplified integration, but that was never completed implemented. The Initialization Vector cannot be configured in the DecryptContent Processors, and both expect to read it from the FlowFile content. For these reasons, I don't think it is necessary to remove any of the attributes that EncryptContent applies.
   
   3. The EncryptionMethod values have retained their current order for a long time, so I think those should remain unchanged. However, I agree that the values for DecryptContentCompatibilityMode should be alphabetized, so I will make those changes.
   
   4. The jasypt dependency is not actually used, so I created [NIFI-11090](https://issues.apache.org/jira/browse/NIFI-11090) to remove the dependency.
   
   5. With the DecryptContent Processors, any raw hexadecimal key must match the value used for encryption. Adding a note might be helpful as a follow on effort, but I'm not sure it is particularly helpful given that it should already be known, otherwise decryption will fail.
   
   6. I considered having separate properties versus sharing the same property and interpreting it based on the `Key Specification Format` property. I would not expect the value and format to change in normal usage, so it seems more straightforward to keep the current approach, as opposed to introducing a separate property. If you think it would be significantly better to have a separate property, and have both properties depend on the format property, I can look at making those changes.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@nifi.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nifi] greyp9 commented on a diff in pull request #6821: NIFI-11022 Add DecryptContent Compatibility Processors

Posted by "greyp9 (via GitHub)" <gi...@apache.org>.
greyp9 commented on code in PR #6821:
URL: https://github.com/apache/nifi/pull/6821#discussion_r1088327831


##########
nifi-nar-bundles/nifi-cipher-bundle/nifi-cipher-processors/src/main/java/org/apache/nifi/processors/cipher/DecryptContentEncoded.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.processors.cipher;
+
+import org.apache.nifi.annotation.behavior.InputRequirement;
+import org.apache.nifi.annotation.behavior.SideEffectFree;
+import org.apache.nifi.annotation.behavior.SupportsBatching;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.processor.AbstractProcessor;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSession;
+import org.apache.nifi.processor.Relationship;
+import org.apache.nifi.processor.io.StreamCallback;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.processors.cipher.algorithm.CipherAlgorithmMode;
+import org.apache.nifi.processors.cipher.algorithm.CipherAlgorithmPadding;
+import org.apache.nifi.processors.cipher.algorithm.SymmetricCipher;
+import org.apache.nifi.processors.cipher.encoded.EncodedDelimiter;
+import org.apache.nifi.processors.cipher.encoded.KeySpecificationFormat;
+import org.apache.nifi.processors.cipher.io.DecryptStreamCallback;
+import org.apache.nifi.security.crypto.key.DerivedKeyParameterSpec;
+import org.apache.nifi.security.crypto.key.DerivedKeySpec;
+import org.apache.nifi.security.crypto.key.StandardDerivedKeySpec;
+import org.apache.nifi.security.crypto.key.detection.DetectedDerivedKeyParameterSpecReader;
+import org.apache.nifi.security.crypto.key.detection.DetectedDerivedKeyProvider;
+import org.apache.nifi.security.crypto.key.io.ByteBufferSearch;
+import org.bouncycastle.util.encoders.Hex;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.ByteBuffer;
+import java.security.GeneralSecurityException;
+import java.security.Key;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.KeySpec;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@SideEffectFree
+@SupportsBatching
+@InputRequirement(InputRequirement.Requirement.INPUT_REQUIRED)
+@Tags({"cryptography", "decipher", "decrypt", "AES", "Argon2", "bcrypt", "scrypt", "PBKDF2"})
+@CapabilityDescription("Decrypt content encrypted with AES and encoded according conventions added in NiFi 0.5.0 for the EncryptContent Processor. " +
+        "The Processor reads the first 256 bytes to determine the presence of a cryptographic salt based on finding the 'NiFiSALT' delimiter. " +
+        "The salt is not present for content encrypted with a raw hexadecimal key. " +
+        "The Processor determines the presence of the initialization vector based on finding the 'NiFiIV' delimiter." +
+        "The salt format indicates the Key Derivation Function that the Processor uses to generate a secret key based on a configured password. " +
+        "The Processor derives keys with a size of 128 bits according to the conventions implemented in NiFi 0.5.0."
+)
+public class DecryptContentEncoded extends AbstractProcessor {
+
+    static final PropertyDescriptor CIPHER_ALGORITHM_MODE = new PropertyDescriptor.Builder()
+            .name("cipher-algorithm-mode")
+            .displayName("Cipher Algorithm Mode")
+            .description("Block cipher mode of operation for decryption using the Advanced Encryption Standard")
+            .required(true)
+            .allowableValues(CipherAlgorithmMode.class)
+            .defaultValue(CipherAlgorithmMode.GCM.getValue())
+            .build();
+
+    static final PropertyDescriptor CIPHER_ALGORITHM_PADDING = new PropertyDescriptor.Builder()
+            .name("cipher-algorithm-padding")
+            .displayName("Cipher Algorithm Padding")
+            .description("Padding specification used in cipher operation for decryption using the Advanced Encryption Standard")
+            .required(true)
+            .allowableValues(CipherAlgorithmPadding.class)
+            .defaultValue(CipherAlgorithmPadding.NO_PADDING.getValue())
+            .build();
+
+    static final PropertyDescriptor KEY_SPECIFICATION_FORMAT = new PropertyDescriptor.Builder()
+            .name("key-specification-format")
+            .displayName("Key Specification Format")
+            .description("Format describing the configured Key Specification")
+            .required(true)
+            .allowableValues(KeySpecificationFormat.class)
+            .defaultValue(KeySpecificationFormat.PASSWORD.getValue())
+            .build();
+
+    static final PropertyDescriptor KEY_SPECIFICATION = new PropertyDescriptor.Builder()
+            .name("key-specification")
+            .displayName("Key Specification")
+            .description("Specification providing the raw secret key or a password from which to derive a secret key")
+            .required(true)
+            .sensitive(true)
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .build();
+
+    static final Relationship SUCCESS = new Relationship.Builder()
+            .name("success")
+            .description("Decryption succeeded")
+            .build();
+
+    static final Relationship FAILURE = new Relationship.Builder()
+            .name("failure")
+            .description("Decryption failed")
+            .build();
+
+    private static final List<PropertyDescriptor> DESCRIPTORS = Collections.unmodifiableList(Arrays.asList(
+            CIPHER_ALGORITHM_MODE,
+            CIPHER_ALGORITHM_PADDING,
+            KEY_SPECIFICATION_FORMAT,
+            KEY_SPECIFICATION
+    ));
+
+    private static final Set<Relationship> RELATIONSHIPS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
+            SUCCESS,
+            FAILURE
+    )));
+
+    private static final SymmetricCipher SYMMETRIC_CIPHER = SymmetricCipher.AES;
+
+    private static final String TRANSFORMATION_FORMAT = "%s/%s/%s";
+
+    /**
+     * Get Supported Property Descriptors
+     *
+     * @return Processor Property Descriptors
+     */
+    @Override
+    public List<PropertyDescriptor> getSupportedPropertyDescriptors() {
+        return DESCRIPTORS;
+    }
+
+    /**
+     * Get Relationships
+     *
+     * @return Processor Relationships
+     */
+    @Override
+    public Set<Relationship> getRelationships() {
+        return RELATIONSHIPS;
+    }
+
+    /**
+     * On Trigger decrypts Flow File contents using configured properties
+     *
+     * @param context Process Context
+     * @param session Process Session
+     */
+    @Override
+    public void onTrigger(final ProcessContext context, final ProcessSession session) {
+        FlowFile flowFile = session.get();
+        if (flowFile == null) {
+            return;
+        }
+
+        final String specificationFormat = context.getProperty(KEY_SPECIFICATION_FORMAT).getValue();
+        final KeySpecificationFormat keySpecificationFormat = KeySpecificationFormat.valueOf(specificationFormat);
+
+        final String cipherTransformation = getCipherTransformation(context);
+        final Cipher cipher = getCipher(cipherTransformation);
+        final String algorithmMode = context.getProperty(CIPHER_ALGORITHM_MODE).getValue();
+        final CipherAlgorithmMode cipherAlgorithmMode = CipherAlgorithmMode.valueOf(algorithmMode);
+
+        final KeySpec keySpec = getKeySpec(context, keySpecificationFormat);
+        final StreamCallback callback = new DecryptCallback(cipher, cipherAlgorithmMode, keySpec);
+        try {
+            flowFile = session.write(flowFile, callback);
+            getLogger().debug("Decryption completed using [{}] {}", cipherTransformation, flowFile);
+            session.transfer(flowFile, SUCCESS);
+        } catch (final RuntimeException e) {
+            getLogger().error("Decryption failed using [{}] {}", cipherTransformation, flowFile, e);
+            session.transfer(flowFile, FAILURE);
+        }
+    }
+
+    private String getCipherTransformation(final ProcessContext context) {
+        final String algorithmMode = context.getProperty(CIPHER_ALGORITHM_MODE).getValue();
+        final String algorithmPadding = context.getProperty(CIPHER_ALGORITHM_PADDING).getValue();
+        return String.format(TRANSFORMATION_FORMAT, SYMMETRIC_CIPHER.getValue(), algorithmMode, algorithmPadding);
+    }
+
+    private Cipher getCipher(final String transformation) {
+        try {
+            return Cipher.getInstance(transformation);
+        } catch (final GeneralSecurityException e) {
+            final String message = String.format("Cipher [%s] not found", transformation);
+            throw new CipherException(message, e);
+        }
+    }
+
+    private KeySpec getKeySpec(final ProcessContext context, final KeySpecificationFormat keySpecificationFormat) {
+        final KeySpec keySpec;
+        final String keySpecification = context.getProperty(KEY_SPECIFICATION).getValue();
+        if (KeySpecificationFormat.RAW == keySpecificationFormat) {
+            final byte[] decodedKey = Hex.decode(keySpecification);
+            keySpec = new SecretKeySpec(decodedKey, SYMMETRIC_CIPHER.getValue());
+        } else {
+            final char[] password = keySpecification.toCharArray();
+            keySpec = new PBEKeySpec(password);
+        }
+        return keySpec;
+    }
+
+    private interface SerializedParameterSpec {
+
+        byte[] getParameters();
+    }
+
+    private static class GCMSerializedParameterSpec extends GCMParameterSpec implements SerializedParameterSpec {
+
+        private static final int GCM_TAG_LENGTH_BITS = 128;

Review Comment:
   https://crypto.stackexchange.com/questions/41601/aes-gcm-recommended-iv-size-why-12-bytes



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@nifi.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nifi] exceptionfactory commented on a diff in pull request #6821: NIFI-11022 Add DecryptContent Compatibility Processors

Posted by "exceptionfactory (via GitHub)" <gi...@apache.org>.
exceptionfactory commented on code in PR #6821:
URL: https://github.com/apache/nifi/pull/6821#discussion_r1088184226


##########
nifi-nar-bundles/nifi-cipher-bundle/nifi-cipher-processors/src/main/java/org/apache/nifi/processors/cipher/compatibility/CompatibilityModeEncryptionScheme.java:
##########
@@ -0,0 +1,216 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.processors.cipher.compatibility;
+
+import org.apache.nifi.processors.cipher.algorithm.SymmetricCipher;
+import org.apache.nifi.processors.cipher.algorithm.DigestAlgorithm;
+import org.apache.nifi.components.DescribedValue;
+
+import static org.apache.nifi.processors.cipher.algorithm.SymmetricCipher.AES;
+import static org.apache.nifi.processors.cipher.algorithm.SymmetricCipher.DES;
+import static org.apache.nifi.processors.cipher.algorithm.SymmetricCipher.DESEDE;
+import static org.apache.nifi.processors.cipher.algorithm.SymmetricCipher.RC2;
+import static org.apache.nifi.processors.cipher.algorithm.SymmetricCipher.RC4;
+import static org.apache.nifi.processors.cipher.algorithm.SymmetricCipher.TWOFISH;
+
+/**
+ * Compatibility Mode Encryption Schemes supporting decryption using legacy algorithms such as PBES1 defined in RFC 8018 Section 6.1
+ */
+public enum CompatibilityModeEncryptionScheme implements DescribedValue {
+    PBE_WITH_MD5_AND_AES_CBC_128(
+            "PBEWITHMD5AND128BITAES-CBC-OPENSSL",
+            DigestAlgorithm.MD5,
+            AES,
+            "PKCS12 with MD5 digest and Advanced Encryption Standard in Cipher Block Chaining mode using 128 bit keys."
+    ),
+
+    PBE_WITH_MD5_AND_AES_CBC_192(
+            "PBEWITHMD5AND192BITAES-CBC-OPENSSL",
+            DigestAlgorithm.MD5,
+            AES,
+            "PKCS12 with MD5 digest and Advanced Encryption Standard in Cipher Block Chaining mode using 192 bit keys."
+    ),
+
+    PBE_WITH_MD5_AND_AES_CBC_256(
+            "PBEWITHMD5AND256BITAES-CBC-OPENSSL",
+            DigestAlgorithm.MD5,
+            AES,
+            "PKCS12 with MD5 digest and Advanced Encryption Standard in Cipher Block Chaining mode using 256 bit keys."
+    ),
+
+    PBE_WITH_MD5_AND_DES(
+            "PBEWITHMD5ANDDES",
+            DigestAlgorithm.MD5,
+            DES,
+            "PKCS5 Scheme 1 with MD5 digest and Data Encryption Standard 64 bit keys. OID 1.2.840.113549.1.5.3"

Review Comment:
   No, `PKCS5` is correct. Some schemes follow the PKCS5 strategy for password handling, others follow PKCS12.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@nifi.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nifi] greyp9 commented on a diff in pull request #6821: NIFI-11022 Add DecryptContent Compatibility Processors

Posted by "greyp9 (via GitHub)" <gi...@apache.org>.
greyp9 commented on code in PR #6821:
URL: https://github.com/apache/nifi/pull/6821#discussion_r1088327831


##########
nifi-nar-bundles/nifi-cipher-bundle/nifi-cipher-processors/src/main/java/org/apache/nifi/processors/cipher/DecryptContentEncoded.java:
##########
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.processors.cipher;
+
+import org.apache.nifi.annotation.behavior.InputRequirement;
+import org.apache.nifi.annotation.behavior.SideEffectFree;
+import org.apache.nifi.annotation.behavior.SupportsBatching;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.processor.AbstractProcessor;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSession;
+import org.apache.nifi.processor.Relationship;
+import org.apache.nifi.processor.io.StreamCallback;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.processors.cipher.algorithm.CipherAlgorithmMode;
+import org.apache.nifi.processors.cipher.algorithm.CipherAlgorithmPadding;
+import org.apache.nifi.processors.cipher.algorithm.SymmetricCipher;
+import org.apache.nifi.processors.cipher.encoded.EncodedDelimiter;
+import org.apache.nifi.processors.cipher.encoded.KeySpecificationFormat;
+import org.apache.nifi.processors.cipher.io.DecryptStreamCallback;
+import org.apache.nifi.security.crypto.key.DerivedKeyParameterSpec;
+import org.apache.nifi.security.crypto.key.DerivedKeySpec;
+import org.apache.nifi.security.crypto.key.StandardDerivedKeySpec;
+import org.apache.nifi.security.crypto.key.detection.DetectedDerivedKeyParameterSpecReader;
+import org.apache.nifi.security.crypto.key.detection.DetectedDerivedKeyProvider;
+import org.apache.nifi.security.crypto.key.io.ByteBufferSearch;
+import org.bouncycastle.util.encoders.Hex;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.ByteBuffer;
+import java.security.GeneralSecurityException;
+import java.security.Key;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.KeySpec;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@SideEffectFree
+@SupportsBatching
+@InputRequirement(InputRequirement.Requirement.INPUT_REQUIRED)
+@Tags({"cryptography", "decipher", "decrypt", "AES", "Argon2", "bcrypt", "scrypt", "PBKDF2"})
+@CapabilityDescription("Decrypt content encrypted with AES and encoded according conventions added in NiFi 0.5.0 for the EncryptContent Processor. " +
+        "The Processor reads the first 256 bytes to determine the presence of a cryptographic salt based on finding the 'NiFiSALT' delimiter. " +
+        "The salt is not present for content encrypted with a raw hexadecimal key. " +
+        "The Processor determines the presence of the initialization vector based on finding the 'NiFiIV' delimiter." +
+        "The salt format indicates the Key Derivation Function that the Processor uses to generate a secret key based on a configured password. " +
+        "The Processor derives keys with a size of 128 bits according to the conventions implemented in NiFi 0.5.0."
+)
+public class DecryptContentEncoded extends AbstractProcessor {
+
+    static final PropertyDescriptor CIPHER_ALGORITHM_MODE = new PropertyDescriptor.Builder()
+            .name("cipher-algorithm-mode")
+            .displayName("Cipher Algorithm Mode")
+            .description("Block cipher mode of operation for decryption using the Advanced Encryption Standard")
+            .required(true)
+            .allowableValues(CipherAlgorithmMode.class)
+            .defaultValue(CipherAlgorithmMode.GCM.getValue())
+            .build();
+
+    static final PropertyDescriptor CIPHER_ALGORITHM_PADDING = new PropertyDescriptor.Builder()
+            .name("cipher-algorithm-padding")
+            .displayName("Cipher Algorithm Padding")
+            .description("Padding specification used in cipher operation for decryption using the Advanced Encryption Standard")
+            .required(true)
+            .allowableValues(CipherAlgorithmPadding.class)
+            .defaultValue(CipherAlgorithmPadding.NO_PADDING.getValue())
+            .build();
+
+    static final PropertyDescriptor KEY_SPECIFICATION_FORMAT = new PropertyDescriptor.Builder()
+            .name("key-specification-format")
+            .displayName("Key Specification Format")
+            .description("Format describing the configured Key Specification")
+            .required(true)
+            .allowableValues(KeySpecificationFormat.class)
+            .defaultValue(KeySpecificationFormat.PASSWORD.getValue())
+            .build();
+
+    static final PropertyDescriptor KEY_SPECIFICATION = new PropertyDescriptor.Builder()
+            .name("key-specification")
+            .displayName("Key Specification")
+            .description("Specification providing the raw secret key or a password from which to derive a secret key")
+            .required(true)
+            .sensitive(true)
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .build();
+
+    static final Relationship SUCCESS = new Relationship.Builder()
+            .name("success")
+            .description("Decryption succeeded")
+            .build();
+
+    static final Relationship FAILURE = new Relationship.Builder()
+            .name("failure")
+            .description("Decryption failed")
+            .build();
+
+    private static final List<PropertyDescriptor> DESCRIPTORS = Collections.unmodifiableList(Arrays.asList(
+            CIPHER_ALGORITHM_MODE,
+            CIPHER_ALGORITHM_PADDING,
+            KEY_SPECIFICATION_FORMAT,
+            KEY_SPECIFICATION
+    ));
+
+    private static final Set<Relationship> RELATIONSHIPS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
+            SUCCESS,
+            FAILURE
+    )));
+
+    private static final SymmetricCipher SYMMETRIC_CIPHER = SymmetricCipher.AES;
+
+    private static final String TRANSFORMATION_FORMAT = "%s/%s/%s";
+
+    /**
+     * Get Supported Property Descriptors
+     *
+     * @return Processor Property Descriptors
+     */
+    @Override
+    public List<PropertyDescriptor> getSupportedPropertyDescriptors() {
+        return DESCRIPTORS;
+    }
+
+    /**
+     * Get Relationships
+     *
+     * @return Processor Relationships
+     */
+    @Override
+    public Set<Relationship> getRelationships() {
+        return RELATIONSHIPS;
+    }
+
+    /**
+     * On Trigger decrypts Flow File contents using configured properties
+     *
+     * @param context Process Context
+     * @param session Process Session
+     */
+    @Override
+    public void onTrigger(final ProcessContext context, final ProcessSession session) {
+        FlowFile flowFile = session.get();
+        if (flowFile == null) {
+            return;
+        }
+
+        final String specificationFormat = context.getProperty(KEY_SPECIFICATION_FORMAT).getValue();
+        final KeySpecificationFormat keySpecificationFormat = KeySpecificationFormat.valueOf(specificationFormat);
+
+        final String cipherTransformation = getCipherTransformation(context);
+        final Cipher cipher = getCipher(cipherTransformation);
+        final String algorithmMode = context.getProperty(CIPHER_ALGORITHM_MODE).getValue();
+        final CipherAlgorithmMode cipherAlgorithmMode = CipherAlgorithmMode.valueOf(algorithmMode);
+
+        final KeySpec keySpec = getKeySpec(context, keySpecificationFormat);
+        final StreamCallback callback = new DecryptCallback(cipher, cipherAlgorithmMode, keySpec);
+        try {
+            flowFile = session.write(flowFile, callback);
+            getLogger().debug("Decryption completed using [{}] {}", cipherTransformation, flowFile);
+            session.transfer(flowFile, SUCCESS);
+        } catch (final RuntimeException e) {
+            getLogger().error("Decryption failed using [{}] {}", cipherTransformation, flowFile, e);
+            session.transfer(flowFile, FAILURE);
+        }
+    }
+
+    private String getCipherTransformation(final ProcessContext context) {
+        final String algorithmMode = context.getProperty(CIPHER_ALGORITHM_MODE).getValue();
+        final String algorithmPadding = context.getProperty(CIPHER_ALGORITHM_PADDING).getValue();
+        return String.format(TRANSFORMATION_FORMAT, SYMMETRIC_CIPHER.getValue(), algorithmMode, algorithmPadding);
+    }
+
+    private Cipher getCipher(final String transformation) {
+        try {
+            return Cipher.getInstance(transformation);
+        } catch (final GeneralSecurityException e) {
+            final String message = String.format("Cipher [%s] not found", transformation);
+            throw new CipherException(message, e);
+        }
+    }
+
+    private KeySpec getKeySpec(final ProcessContext context, final KeySpecificationFormat keySpecificationFormat) {
+        final KeySpec keySpec;
+        final String keySpecification = context.getProperty(KEY_SPECIFICATION).getValue();
+        if (KeySpecificationFormat.RAW == keySpecificationFormat) {
+            final byte[] decodedKey = Hex.decode(keySpecification);
+            keySpec = new SecretKeySpec(decodedKey, SYMMETRIC_CIPHER.getValue());
+        } else {
+            final char[] password = keySpecification.toCharArray();
+            keySpec = new PBEKeySpec(password);
+        }
+        return keySpec;
+    }
+
+    private interface SerializedParameterSpec {
+
+        byte[] getParameters();
+    }
+
+    private static class GCMSerializedParameterSpec extends GCMParameterSpec implements SerializedParameterSpec {
+
+        private static final int GCM_TAG_LENGTH_BITS = 128;

Review Comment:
   https://crypto.stackexchange.com/questions/41601/aes-gcm-recommended-iv-size-why-12-bytes



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@nifi.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nifi] greyp9 commented on a diff in pull request #6821: NIFI-11022 Add DecryptContent Compatibility Processors

Posted by "greyp9 (via GitHub)" <gi...@apache.org>.
greyp9 commented on code in PR #6821:
URL: https://github.com/apache/nifi/pull/6821#discussion_r1088221059


##########
nifi-nar-bundles/nifi-cipher-bundle/nifi-cipher-processors/src/main/resources/docs/org.apache.nifi.processors.cipher.DecryptContentCompatibilityMode/additionalDetails.html:
##########
@@ -0,0 +1,144 @@
+<!DOCTYPE html>
+<html lang="en">
+  <!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+        http://www.apache.org/licenses/LICENSE-2.0
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+  -->
+  <head>
+    <meta charset="UTF-8">
+    <title>DecryptContentCompatibilityMode</title>
+    <link rel="stylesheet" href="../../../../../css/component-usage.css" type="text/css" />
+  </head>
+  <body>
+    <h2>Summary</h2>
+    <p>
+      This Processor supports decryption using legacy formats and Password-Based Encryption Algorithms.
+      <a href="https://www.rfc-editor.org/rfc/rfc8018">RFC 8018</a> defines the Password-Based Cryptography

Review Comment:
   Weird interaction here between iframe and external link.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@nifi.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nifi] exceptionfactory commented on pull request #6821: NIFI-11022 Add DecryptContent Compatibility Processors

Posted by "exceptionfactory (via GitHub)" <gi...@apache.org>.
exceptionfactory commented on PR #6821:
URL: https://github.com/apache/nifi/pull/6821#issuecomment-1402724256

   Thanks again for the feedback @greyp9, I pushed an update with additional details documentation for both Processors, including tables that map new property values to matching values from `EncryptContent`.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@nifi.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org