NiFi выполнить скрипт шифрования JSON - PullRequest
0 голосов
/ 25 мая 2018

Привет, ссылаясь на этот вопрос: nifi encrypt json Я попытался использовать предоставленный шаблон .Я обнаружил ошибку при попытке выполнить процессор executeScript: enter image description here

Без перехвата попытки:

enter image description here

Обычно он пытается выполнить следующий скрипт:

import javax.crypto.Cipher
import javax.crypto.SecretKey
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
import java.nio.charset.StandardCharsets

FlowFile flowFile = session.get()

if (!flowFile) {
    return
}

try {
    // Get the raw values of the attributes
    String normalAttribute = flowFile.getAttribute('Normal Attribute')
    String sensitiveAttribute = flowFile.getAttribute('Sensitive Attribute')

    // Instantiate an encryption cipher
    // Lots of additional code could go here to generate a random key, derive a key from a password, read from a file or keyring, etc.
    String keyHex = "0123456789ABCDEFFEDCBA9876543210" // * 2 for 256-bit encryption
    SecretKey key = new SecretKeySpec(keyHex.getBytes(StandardCharsets.UTF_8), "AES")
    IvParameterSpec iv = new IvParameterSpec(keyHex[0..<16].getBytes(StandardCharsets.UTF_8))

    Cipher aesGcmEncCipher = Cipher.getInstance("AES/GCM/NoPadding", "BC")
    aesGcmEncCipher.init(Cipher.ENCRYPT_MODE, key, iv)

    String encryptedNormalAttribute = Base64.encoder.encodeToString(aesGcmEncCipher.doFinal(normalAttribute.bytes))
    String encryptedSensitiveAttribute = Base64.encoder.encodeToString(aesGcmEncCipher.doFinal(sensitiveAttribute.bytes))

    // Add a new attribute with the encrypted normal attribute
    flowFile = session.putAttribute(flowFile, 'Normal Attribute (encrypted)', encryptedNormalAttribute)

    // Replace the sensitive attribute inline with the cipher text
    flowFile = session.putAttribute(flowFile, 'Sensitive Attribute', encryptedSensitiveAttribute)
    session.transfer(flowFile, REL_SUCCESS)
} catch (Exception e) {
    log.error("There was an error encrypting the attributes: ${e.getMessage()}")
    session.transfer(flowFile, REL_FAILURE)
}

1 Ответ

0 голосов
/ 25 мая 2018

Этот сценарий был предоставлен как непроверенный (и нерабочий) шаблон для демонстрации возможностей ExecuteScript в конкретном случае использования.Как указал @daggett, экземпляр шифра должен был быть #init() снова перед вызовом другого #doFinal(), потому что шифр G / CM вычисляет и применяет тег аутентификации к зашифрованному тексту.

Вот рабочая реализация того же поведения.

import org.apache.commons.codec.binary.Hex

import javax.crypto.Cipher
import javax.crypto.SecretKey
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
import java.nio.charset.StandardCharsets
import java.security.SecureRandom

FlowFile flowFile = session.get()

if (!flowFile) {
    return
}

try {
    // Get the raw values of the attributes
    String normalAttribute = flowFile.getAttribute('normal_attr')
    String sensitiveAttribute = flowFile.getAttribute('sensitive_attr')

    // Instantiate an encryption cipher
    // Lots of additional code could go here to generate a random key, derive a key from a password, read from a file or keyring, etc.
    String keyHex = "0123456789ABCDEFFEDCBA9876543210" // * 2 for 256-bit encryption
    SecretKey key = new SecretKeySpec(Hex.decodeHex(keyHex), "AES")
    byte[] ivBytes = new byte[16]
    SecureRandom secureRandom = new SecureRandom()
    secureRandom.nextBytes(ivBytes)
    IvParameterSpec iv = new IvParameterSpec(ivBytes)

    Cipher aesGcmEncCipher = Cipher.getInstance("AES/GCM/NoPadding", "BC")
    aesGcmEncCipher.init(Cipher.ENCRYPT_MODE, key, iv)

    String cipherTextBase64 = Base64.encoder.encodeToString(aesGcmEncCipher.doFinal(normalAttribute.bytes))
    String encryptedNormalAttribute = "${Base64.encoder.encodeToString(ivBytes)}||${cipherTextBase64}"

    // Re-initialize the cipher
    secureRandom.nextBytes(ivBytes)
    iv = new IvParameterSpec(ivBytes)
    aesGcmEncCipher.init(Cipher.ENCRYPT_MODE, key, iv)

    cipherTextBase64 = Base64.encoder.encodeToString(aesGcmEncCipher.doFinal(sensitiveAttribute.bytes))
    String encryptedSensitiveAttribute = "${Base64.encoder.encodeToString(ivBytes)}||${cipherTextBase64}"

    // Add a new attribute with the encrypted normal attribute
    flowFile = session.putAttribute(flowFile, 'normal_attr_encrypted', encryptedNormalAttribute)

    // Replace the sensitive attribute inline with the cipher text
    flowFile = session.putAttribute(flowFile, 'sensitive_attr', encryptedSensitiveAttribute)
    session.transfer(flowFile, REL_SUCCESS)
} catch (Exception e) {
    log.error("There was an error encrypting the attributes: ${e.getMessage()}")
    session.transfer(flowFile, REL_FAILURE)
}

IV ( nonce ) является уникальным и случайным для каждой операции шифрования, кодируется Base64 и добавляется к зашифрованному тексту с использованием || в качестве разделителя.

Пример вывода:

--------------------------------------------------
Standard FlowFile Attributes
Key: 'entryDate'
    Value: 'Fri May 25 12:50:29 PDT 2018'
Key: 'lineageStartDate'
    Value: 'Fri May 25 12:50:29 PDT 2018'
Key: 'fileSize'
    Value: '29'
FlowFile Attribute Map Content
Key: 'normal_attr_encrypted'
    Value: 'LOdE0y0LTZ4N/sax/sQnGw==||1c6V7b6F2yWxLPGWW4EOZcEYd8n9P6lMM4lPApTYQmI2/DCcMGyesn3WPA=='
Key: 'sensitive_attr'
    Value: 'ZaA4Se5gck8Dgk7DeuYvYg==||pO4Oqt3FL/nvQDwJguCrJlwE5ORNIPwZlNEwzyFt5AVPRwZe+jpkJt0jGmAbmAY='
Key: 'filename'
    Value: '246287463224762'
Key: 'normal_attr'
    Value: 'This is a normal attribute.'
Key: 'path'
    Value: './'
Key: 'uuid'
    Value: 'cefae690-eeb2-4b82-8abd-e1b12fd6c410'
--------------------------------------------------
This is a plaintext message.

Обратите внимание, что вам понадобится commons-codec-1.11.jar в вашем ExecuteScript каталоге модулей .

...