/* * 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.encrypt; import java.security.Security; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.util.NiFiProperties; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.exceptions.EncryptionInitializationException; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; /** * <p> * An application specific string encryptor that collects configuration from the * application properties, system properties, and/or system environment. * </p> * * <p> * Instance of this class are thread-safe</p> * * <p> * The encryption provider and algorithm is configured using the application * properties: * <ul> * <li>nifi.sensitive.props.provider</li> * <li>nifi.sensitive.props.algorithm</li> * </ul> * </p> * * <p> * The encryptor's password may be set by configuring the below property: * <ul> * <li>nifi.sensitive.props.key</li> * </ul> * </p> * */ public final class StringEncryptor { static { Security.addProvider(new BouncyCastleProvider()); } public static final String NF_SENSITIVE_PROPS_KEY = "nifi.sensitive.props.key"; public static final String NF_SENSITIVE_PROPS_ALGORITHM = "nifi.sensitive.props.algorithm"; public static final String NF_SENSITIVE_PROPS_PROVIDER = "nifi.sensitive.props.provider"; private static final String DEFAULT_SENSITIVE_PROPS_KEY = "nififtw!"; private static final String TEST_PLAINTEXT = "this is a test"; private final StandardPBEStringEncryptor encryptor; private StringEncryptor(final String aglorithm, final String provider, final String key) { encryptor = new StandardPBEStringEncryptor(); encryptor.setAlgorithm(aglorithm); encryptor.setProviderName(provider); encryptor.setPassword(key); encryptor.setStringOutputType("hexadecimal"); encryptor.initialize(); } /** * Creates an instance of the nifi sensitive property encryptor. Validates * that the encryptor is actually working. * * @param niFiProperties properties * @return encryptor * @throws EncryptionException if any issues arise initializing or * validating the encryptor */ public static StringEncryptor createEncryptor(final NiFiProperties niFiProperties) throws EncryptionException { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); final String sensitivePropAlgorithmVal = niFiProperties.getProperty(NF_SENSITIVE_PROPS_ALGORITHM); final String sensitivePropProviderVal = niFiProperties.getProperty(NF_SENSITIVE_PROPS_PROVIDER); final String sensitivePropValueNifiPropVar = niFiProperties.getProperty(NF_SENSITIVE_PROPS_KEY, DEFAULT_SENSITIVE_PROPS_KEY); if (StringUtils.isBlank(sensitivePropAlgorithmVal)) { throw new EncryptionException(NF_SENSITIVE_PROPS_ALGORITHM + "must bet set"); } if (StringUtils.isBlank(sensitivePropProviderVal)) { throw new EncryptionException(NF_SENSITIVE_PROPS_PROVIDER + "must bet set"); } if (StringUtils.isBlank(sensitivePropValueNifiPropVar)) { throw new EncryptionException(NF_SENSITIVE_PROPS_KEY + "must bet set"); } final StringEncryptor nifiEncryptor; try { nifiEncryptor = new StringEncryptor(sensitivePropAlgorithmVal, sensitivePropProviderVal, sensitivePropValueNifiPropVar); //test that we can infact encrypt and decrypt something if (!nifiEncryptor.decrypt(nifiEncryptor.encrypt(TEST_PLAINTEXT)).equals(TEST_PLAINTEXT)) { throw new EncryptionException("NiFi property encryptor does appear to be working - decrypt/encrypt return invalid results"); } } catch (final EncryptionInitializationException | EncryptionOperationNotPossibleException ex) { throw new EncryptionException("Cannot initialize sensitive property encryptor", ex); } return nifiEncryptor; } /** * Encrypts the given clear text. * * @param clearText the message to encrypt * * @return the cipher text * * @throws EncryptionException if the encrypt fails */ public String encrypt(String clearText) throws EncryptionException { try { return encryptor.encrypt(clearText); } catch (final EncryptionOperationNotPossibleException | EncryptionInitializationException eonpe) { throw new EncryptionException(eonpe); } } /** * Decrypts the given cipher text. * * @param cipherText the message to decrypt * * @return the clear text * * @throws EncryptionException if the decrypt fails */ public String decrypt(String cipherText) throws EncryptionException { try { return encryptor.decrypt(cipherText); } catch (final EncryptionOperationNotPossibleException | EncryptionInitializationException eonpe) { throw new EncryptionException(eonpe); } } }