- Subscribe to RSS Feed
- Mark Question as New
- Mark Question as Read
- Float this Question for Current User
- Bookmark
- Subscribe
- Mute
- Printer Friendly Page
building a encrypt Content-like script for NiFi with PGP Encryption
- Labels:
-
Apache NiFi
Created on 03-08-2022 11:54 AM - edited 03-08-2022 03:29 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I need to encrypt some content with PGP, but i can't use the processor Encrypt Content because we require that the "Keyring file route" and the "passphrase" must be entered through attributes (We must use an old version of NiFi). I make this script using the repo of NiFi and modifying the things that i need and using a single script file considering how the processor works. My problem is that the result can't be decrypted backwards.
I'm using Nifi 1.13.2
With Groovy as language
and Bouncy Castle (bcpg-jdk15on-1.70 and bcprov-jdk15on-1.70)
And my code is:
import org.bouncycastle.bcpg.ArmoredOutputStream
import org.bouncycastle.openpgp.PGPCompressedData
import org.bouncycastle.openpgp.PGPCompressedDataGenerator
import org.bouncycastle.openpgp.PGPEncryptedData
import org.bouncycastle.openpgp.PGPEncryptedDataGenerator
import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPLiteralData
import org.bouncycastle.openpgp.PGPPublicKey
import org.bouncycastle.openpgp.PGPLiteralDataGenerator
import org.bouncycastle.openpgp.operator.PGPKeyEncryptionMethodGenerator
import org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator
import org.bouncycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder
import org.bouncycastle.openpgp.PGPPublicKeyRing
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection
import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator
import org.bouncycastle.jce.provider.BouncyCastleProvider
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.security.SecureRandom
import java.util.Date
import java.util.zip.Deflater
FlowFile flowFile = session.get()
if (!flowFile) {
return
}
final int BUFFER_SIZE = 65536;
final int BLOCK_SIZE = 4096;
try {
flowFile = session.write(flowFile, { inputStream, outputStream ->
output = new ArmoredOutputStream(outputStream)
int cipher = PGPEncryptedData.AES_256
String provider = "BC"
filename = "encrypted.txt"
publicKeyUserId = flowFile.getAttribute('PublicKeyUserId')
publicKeyringFile = flowFile.getAttribute('publicKeyRoute')
publicKey = getPublicKey(publicKeyUserId, publicKeyringFile)
try {
PGPEncryptedDataGenerator encryptedDataGenerator = new PGPEncryptedDataGenerator(
new JcePGPDataEncryptorBuilder(cipher).setWithIntegrityPacket(true).setSecureRandom(new SecureRandom()).setProvider(provider))
encryptedDataGenerator.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(publicKey).setProvider(provider))
OutputStream encryptedOut = encryptedDataGenerator.open(output, new byte[BUFFER_SIZE])
PGPCompressedDataGenerator compressedDataGenerator = new PGPCompressedDataGenerator(PGPCompressedData.ZIP, Deflater.BEST_SPEED)
OutputStream compressedOut = compressedDataGenerator.open(encryptedOut, new byte[BUFFER_SIZE])
PGPLiteralDataGenerator literalDataGenerator = new PGPLiteralDataGenerator()
OutputStream literalOut = literalDataGenerator.open(compressedOut, PGPLiteralData.BINARY, filename, new Date(), new byte[BUFFER_SIZE])
final byte[] buffer = new byte[BLOCK_SIZE];
int len;
while ((len = inputStream.read(buffer)) >= 0) {
literalOut.write(buffer, 0, len);
}
} finally {
output.close();
}
} as StreamCallback)
session.transfer(flowFile, REL_SUCCESS)
} catch (Exception e) {
log.error("There was an error encrypting the attributes: ${e.getMessage()}")
session.transfer(flowFile, REL_FAILURE)
}
static PGPPublicKey getPublicKey(String userId, String publicKeyringFile){
FileInputStream keyInputStream = new FileInputStream(publicKeyringFile)
// Form the PublicKeyRing collection (1.53 way with fingerprint calculator)
PGPPublicKeyRingCollection pgpPublicKeyRingCollection = new PGPPublicKeyRingCollection(keyInputStream, new BcKeyFingerprintCalculator());
// Iterate over all public keyrings
Iterator<PGPPublicKeyRing> iter = pgpPublicKeyRingCollection.getKeyRings();
PGPPublicKeyRing keyRing;
while (iter.hasNext()) {
keyRing = iter.next();
// Iterate over each public key in this keyring
Iterator<PGPPublicKey> keyIter = keyRing.getPublicKeys();
while (keyIter.hasNext()) {
PGPPublicKey publicKey = keyIter.next();
// Iterate over each userId attached to the public key
Iterator userIdIterator = publicKey.getUserIDs();
while (userIdIterator.hasNext()) {
String id = (String) userIdIterator.next();
if (userId.equalsIgnoreCase(id)) {
return publicKey;
}
}
}
}
}
Can anyone help me making this work?
Thank you!
Created 03-08-2022 12:37 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please have a look at this. It doesn't use PGP but it's a similar encryption implementation using Groovy:
In that case I used parameters but you can replace them with variables/attributes.
Let me know if that helps.
André
--
Was your question answered? Make sure to mark the answer as the accepted solution.
If you find a reply useful, say thanks by clicking on the thumbs up button.
Was your question answered? Please take some time to click on "Accept as Solution" below this post.
If you find a reply useful, say thanks by clicking on the thumbs up button.
Created 03-08-2022 03:27 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks, but i must use PGP, with the public and private keys and all that.
Created 03-08-2022 03:28 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What's the error you're getting?
André
Was your question answered? Please take some time to click on "Accept as Solution" below this post.
If you find a reply useful, say thanks by clicking on the thumbs up button.
Created 03-08-2022 03:31 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
When i try to decrypt it with kleoptatra, it throws the diagnostic message "gpg: [don't know]: 1st length byte missing".
Created 03-08-2022 06:53 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Can you share your flow definition?
André
Was your question answered? Please take some time to click on "Accept as Solution" below this post.
If you find a reply useful, say thanks by clicking on the thumbs up button.
Created 03-08-2022 10:21 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In the test version that i build is something like this: it creates the flow (In the original is a query from a database), adds the custom attributes (like the filename, the location of the public key, etc, those i get them from another table), it encrypts the contents and finally the encrypted content is transferred to an ftp.
This is what you need, right? I can upload the xml somewhere if you like.
Thank you!