org.candlepin.config.EncryptedValueConfigurationParser.java Source code

Java tutorial

Introduction

Here is the source code for org.candlepin.config.EncryptedValueConfigurationParser.java

Source

/**
 * Copyright (c) 2009 - 2012 Red Hat, Inc.
 *
 * This software is licensed to you under the GNU General Public License,
 * version 2 (GPLv2). There is NO WARRANTY for this software, express or
 * implied, including the implied warranties of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
 * along with this software; if not, see
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
 *
 * Red Hat trademarks are not licensed under GPLv2. No permission is
 * granted to use or replicate Red Hat trademarks that are incorporated
 * in this software or its documentation.
 */
package org.candlepin.config;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.log4j.Logger;

/**
 * EncryptedValueConfigurationParser
 */
public abstract class EncryptedValueConfigurationParser extends ConfigurationParser {
    private String passphrase = null;
    private static Logger log = Logger.getLogger(EncryptedValueConfigurationParser.class);

    public EncryptedValueConfigurationParser(Config config) {
        String secretFile = config.getString(ConfigProperties.PASSPHRASE_SECRET_FILE);

        log.info("reading secret file: " + secretFile);
        try {
            BufferedReader in = new BufferedReader(new FileReader(secretFile));
            String str;
            StringBuilder tmpPassphrase = new StringBuilder();
            while ((str = in.readLine()) != null) {
                log.info("str passphrase: " + str);
                tmpPassphrase.append(str);
            }
            in.close();
            log.info("tmpPassphrase: " + tmpPassphrase.toString());
            passphrase = tmpPassphrase.toString();
        } catch (FileNotFoundException e) {
            log.info("File not found: " + secretFile);
            passphrase = null;
            // FIXME: log, complain, etc
        } catch (IOException e) {
            log.info("IOException while reading: " + secretFile);
            passphrase = null;
        }

        log.info("Using katello-passwd passphrase: " + passphrase);
    }

    /*
     * (non-Javadoc)
     * @see org.candlepin.config.ConfigurationParser#getPrefix()
     */
    public abstract String getPrefix();

    public Properties parseConfig(Map<String, String> inputConfiguration) {
        // pull out properties that we know might be crypted passwds
        // unencrypt them, and update the properties with the new versions
        // do this here so DbBasicAuthConfigParser and JPAConfigParser
        // will do it. Split it to a sub method so sub classes can
        // provide there own implementation of crypt/decrypt
        //
        Properties toReturn = new Properties();
        Properties toDecrypt = stripPrefixFromConfigKeys(inputConfiguration);
        toReturn.putAll(toDecrypt);

        if (encryptedConfigKeys() != null) {
            for (String encConfigKey : encryptedConfigKeys()) {
                String passwordString = toDecrypt.getProperty(encConfigKey);
                if (passwordString != null) {
                    String deCryptedValue = decryptValue(passwordString, getPassphrase());
                    toReturn.setProperty(encConfigKey, deCryptedValue);

                }
            }
        }
        return toReturn;
    }

    /*
     * returns a Set of config keys that should be decrypted if need be
     */
    public abstract Set<String> encryptedConfigKeys();

    /* encrypt config value, such as a password */
    public String encryptValue(String toEnc) {

        // FIXME: clearly this needs a real implementation
        return toEnc;
    }

    /* encrypt config valud, such as a password */
    public String decryptValue(String toDecrypt, String passphrase) {
        log.info("decrypt called");
        if (!toDecrypt.startsWith("$1$")) {
            // this is not an ecnrypted password, just return it
            log.debug("this is not an encrypted string");
            return toDecrypt;
        }

        // remove the magic string
        toDecrypt = toDecrypt.substring(3);

        try {
            Cipher cipher;
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

            // NOTE: we are creating a 64byte digest here,
            // but only the first 16 bytes are used as the iv
            String ivString = passphrase + passphrase;
            String iv = DigestUtils.sha256Hex(ivString);
            String passphraseDigest = DigestUtils.sha256Hex(passphrase);

            // FIXME: katello-password creates a 64 byte key, but somewhere
            // it gets truncated to 32 bytes, so we have to do that here.
            SecretKeySpec spec = new SecretKeySpec(Arrays.copyOfRange(passphraseDigest.getBytes(), 0, 32), "AES");

            cipher.init(Cipher.DECRYPT_MODE, spec, new IvParameterSpec(iv.getBytes(), 0, 16));

            log.info("gh10");
            // NOTE: the encrypted password is stored hex base64
            byte[] b64bytes = Base64.decodeBase64(toDecrypt);
            String plaintext = new String(cipher.doFinal(b64bytes));

            return plaintext;
        } catch (Exception e) {
            log.info("Failure trying to decrypt" + toDecrypt, e);
            throw new RuntimeException(e);
        }
    }

    /**
     * @return the passphrase
     */
    public String getPassphrase() {
        // read /etc/katello/secure/passphrase and use it's contents as
        // passpharse
        log.info("getPassphrase: " + passphrase);
        return passphrase;
    }

    /**
     * @param passphrase the passphrase to set
     */
    public void setPassphrase(String passphrase) {
        this.passphrase = passphrase;
    }
}