All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.miloss.fgsms.common.AES Maven / Gradle / Ivy

/**
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * If it is not possible or desirable to put the notice in a particular
 * file, then You may include the notice in a location (such as a LICENSE
 * file in a relevant directory) where a recipient would be likely to look
 * for such a notice.
 *
 * 
 */
/*  ---------------------------------------------------------------------------
 *  U.S. Government, Department of the Army
 *  Army Materiel Command
 *  Research Development Engineering Command
 *  Communications Electronics Research Development and Engineering Center
 *  ---------------------------------------------------------------------------
 */
package org.miloss.fgsms.common;

import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.GeneralSecurityException;
import org.apache.log4j.Level;
import org.miloss.fgsms.common.Logger;
import org.miloss.fgsms.common.codec.Base64;

;

/**
 * This program uses a AES key, retrieves its raw bytes, and then reinstantiates
 * a AES key from the key bytes. The reinstantiated key is used to initialize a
 * AES cipher for encryption and decryption. source :
 * http://java.sun.com/developer/technicalArticles/Security/AES/AES_v1.html
 *
 * This is the encryption/decryption module of fgsms. used for passwords and
 * certain database columns
 */
public class AES {

    public final static boolean isJCEInstalled;

    public static final String logname = "fgsms.Utility";
    public static final Logger log = Logger.getLogger(logname);

    //pist don't tell anyone, but this is the default key in case all other mechanisms fail to load a valid key
    // private final static String something256 = "gaPVPK6SONri9LCeWJlB2cUMPQL8a3JLegXaJObWj0Q=:F9798Q6FY+YNEaZz5xa6c8OkXk9yp8BcBpX/5avR/Oc=";
    private final static String something128 = "m0b3b70CH0P4Ua7rxksnRw==:o1QNVJ/KY453VEB3VsQn39tQpu5yKovGAH/LQvyzawI=";

    /**
     * Generate a new AES 256 bit encryption key. Once generated, this key can
     * be used to replace the default key.
     *
     * @return
     */
    public static String GEN() {

        return GEN((short) 128);
    }

    /**
     * Generate a new AES 256 bit encryption key. Once generated, this key can
     * be used to replace the default key.
     *
     * @param keysize must be a supported key size, using 128 or 256
     * @return
     */
    public static String GEN(final short keysize) {
        try {
            return AesCbcWithIntegrity.generateKey().toString();
        } catch (GeneralSecurityException ex) {
            log.log(Level.ERROR, "There was an error generating key, this could indicate that you're making a 256 bit key on a system that does not have the Java Crypto Extensions installed. . Is JCE installed? " + (isJCEInstalled ? "yes " : "no ") + ex.getMessage());
            log.log(Level.DEBUG, "error generating key, this could indicate that you're making a 256 bit key on a system that does not have the Java Crypto Extensions installed. " + ex.getMessage(), ex);
        }
        return null;
    }

    private URI getUrl(String FileName) {
        URL pcsurl = null;
        if (pcsurl == null) {
            try {
                pcsurl = Thread.currentThread().getContextClassLoader().getResource(FileName);
                log.log(Level.DEBUG, "Loading encryption key from " + pcsurl.toString());
            } catch (Exception ex) {
                log.log(Level.DEBUG, "not found", ex);
            }
        }
        if (pcsurl == null) {
            try {
                pcsurl = Thread.currentThread().getContextClassLoader().getResource("/" + FileName);
                log.log(Level.DEBUG, "Loading encryption key from " + pcsurl.toString());
            } catch (Exception ex) {
                log.log(Level.DEBUG, "not found", ex);
            }
        }

        if (pcsurl == null) {
            try {
                pcsurl = new URL(FileName);
                log.log(Level.DEBUG, "Loading encryption key from " + pcsurl.toString());
            } catch (Exception ex) {
                log.log(Level.DEBUG, "not found", ex);
            }
        }

        if (pcsurl == null) {
            try {
                pcsurl = AES.class.getClassLoader().getResource(FileName);
                log.log(Level.DEBUG, "Loading encryption key from " + pcsurl.toString());
            } catch (Exception ex) {
                log.log(Level.DEBUG, "not found", ex);
            }
        }
        if (pcsurl == null) {
            try {
                pcsurl = AES.class.getClassLoader().getResource("/" + FileName);
                log.log(Level.DEBUG, "Loading encryption key from " + pcsurl.toString());
            } catch (Exception ex) {
                log.log(Level.DEBUG, "not found", ex);
            }
        }
        try {
            if (pcsurl != null) {
                return pcsurl.toURI();
            }
        } catch (URISyntaxException ex) {
            log.log(Level.DEBUG, null, ex);
        }
        return null;
    }

    private static String readAllText(File file) {
        if (file == null || !file.exists()) {
            log.log(Level.WARN, "Referenced key does not exist" + file.getAbsolutePath());
            return null;
        }
        FileInputStream stream = null;
        try {
            stream = new FileInputStream(file);
            String str = readAllText(stream);
            stream.close();
            return (str);
        } catch (Exception e) {
            log.log(Level.DEBUG, "error reading key", e);
            return null;
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (Exception ex) {
                    log.log(Level.DEBUG, "error reading key", ex);
                }
            }
        }

    }

    private static String readAllText(InputStream stream) {
        try {
            int size = 1024;
            byte chars[] = new byte[size];
            int k = stream.read(chars);
            StringBuilder str = new StringBuilder();
            while (k > 0) {

                for (int i = 0; i < k; i++) {
                    str.append((char) chars[i]);
                }
                k = stream.read(chars);
            }
            stream.close();
            return (str.toString());
        } catch (Exception e) {
            log.log(Level.DEBUG, "error reading key", e);
            return null;
        }
    }

    /* 
     * 
     * note we don't actually store the key in memory at any point in time
     * double edged sword, 1) increases IO, 2) decreases risk
     */
    private static String loadKey() {
        String key = null;
        if (System.getenv("fgsms.keyFile") != null) {
            //attempt load from system environment variable, kind of risky but ok
            key = readAllText(new File(System.getenv("fgsms.keyFile")));
        } else if (key == null && System.getProperty("fgsms.keyFile") != null) {
            //attempt to load from system property
            key = readAllText(new File(System.getProperty("fgsms.keyFile")));
        } else if (key == null) {

            //if (isJCEInstalled)
            {
                //prefer the strong encryption, if it's available
                try {
                    File f = new File(new AES().getUrl("fgsms-aes128.key"));
                    key = readAllText(f);
                } catch (Exception ex) {
                    log.log(Level.DEBUG,null,ex);
                }
                if (key == null) {
                    try {
                        File f = new File(AES.class.getResource("fgsms-aes128.key").toURI());
                        key = readAllText(f);
                    } catch (Exception ex) {
                        log.log(Level.DEBUG,null,ex);
                    }
                }
                if (key == null) {
                    try {
                        InputStream is = AES.class.getResourceAsStream("fgsms-aes128.key");
                        key = readAllText(is);
                        is.close();
                    } catch (Exception ex) {
                        log.log(Level.DEBUG,null,ex);
                    }
                }
                //try to load as a class resource

            }
            /*else {
                try {
                    File f = new File(new AES().getUrl("org/miloss/fgsms/common/aes128.key"));
                    key = readAllText(f);
                } catch (Exception e) {

                }
            }*/
        }
        if (key != null) {
            log.log(Level.DEBUG, "key loaded from file");
            return (key);
        } else {
            log.log(Level.WARN, "Could not load the key, using hard coded default key instead. This should be considered a security risk.");

            return (something128);

        }
    }

    public static String EN(final String cleartext) throws Exception {
        return EN(cleartext, (loadKey()));
    }

    public static String EN(final String cleartext, final String key) throws Exception {
        AesCbcWithIntegrity.SecretKeys skey = AesCbcWithIntegrity.keys(key);
        AesCbcWithIntegrity.CipherTextIvMac encrypt = AesCbcWithIntegrity.encrypt(cleartext, skey);
        return encrypt.toString();
    }

    public static String DE(final String ciphertext) throws Exception {

        return DE(ciphertext, (loadKey()));
    }

    public static String DE(final String ciphertext, final String key) throws Exception {
        AesCbcWithIntegrity.SecretKeys skey = AesCbcWithIntegrity.keys(key);
        AesCbcWithIntegrity.CipherTextIvMac civ = new AesCbcWithIntegrity.CipherTextIvMac(ciphertext);
        return AesCbcWithIntegrity.decryptString(civ, skey);
    }

    /**
     * return true is the supplied key is a valid aes key
     *
     * @param key
     * @return
     */
    public static boolean validateKey(final String key) {
        try {
            String src = "abcdefghijklmopqrstuvwxyz123567890!@#$%^&*()_+{}|:\">?<,";
            String x = EN(src, key);
            String y = DE(x, key);
            //if the sample text is encryptable and decryptable, and it was actually encrypted
            return y.equals(src) && !x.equals(y);
        } catch (Throwable ex) {
//            log.log(Level.WARN, null, ex);
            return false;
        }
    }

    /*
     * public static OutputStream DE(InputStream ciphertext) throws Exception {
     * byte[] raw =//skey.getEncoded(); hexToBytes(something); // SecretKeySpec
     * skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher =
     * Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, skeySpec);
     * CipherInputStream cis = new CipherInputStream(ciphertext, cipher);
     * cis.read(raw);
     *
     * byte[] original = cipher.doFinal(hexToBytes(ciphertext)); return new
     * String(original); }
     */
    static {
        String key = GEN((short) 256);
        isJCEInstalled = validateKey(key);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy