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

prng.utilities.PBEFileDecrypt Maven / Gradle / Ivy

The newest version!
package prng.utilities;

import java.io.*;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.zip.GZIPInputStream;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.Mac;

/**
 * Decrpyt files previously encryptes with PBEFileEncrypt
 *
 * @author Simon Greatrix
 *
 */
public class PBEFileDecrypt {
    /** Resource name used for data */
    public static final String DATA_RESOURCE = "\ufe4f\ufe4f\ufe4f\ufe4f\ufe4f\ufe33DATA\ufe33%x\ufe33\ufe4f\ufe4f\ufe4f\ufe4f\ufe4f";

    /** Resource name used for meta information */
    public static final String META_RESOURCE = "\ufe4f\ufe4f\ufe4f\ufe4f\ufe4f\ufe33META\ufe33%x\ufe33\ufe4f\ufe4f\ufe4f\ufe4f\ufe4f";


    /**
     * Get the password from the console.
     *
     * @return the password
     */
    static char[] getPassword() {
        Console cons = System.console();
        if( cons == null ) {
            return "password".toCharArray();
        }
        char[] password;
        while( true ) {
            password = cons.readPassword("Enter password (ASCII only) : ");
            char[] check = cons.readPassword("Confirm password            : ");
            if( !Arrays.equals(password, check) ) {
                cons.format("\nPasswords differ. Please re-enter.\n\n");
            } else {
                Arrays.fill(check, '\0');
                break;
            }
        }
        cons.format("Password accepted.\n");
        return password;
    }


    /**
     * Application entry point
     *
     * @param args
     *            command line arguments
     * @throws IOException
     *            if the file cannot be read
     * @throws GeneralSecurityException
     *            if decryption fails
     */
    public static void main(String[] args)
            throws IOException, GeneralSecurityException {
        PBEFileDecrypt instance = new PBEFileDecrypt();
        instance.exec();
    }


    /**
     * Read the unencrypted meta data
     *
     * @return the meta data
     * @throws IOException
     */
    private static PBEItem readMeta0() throws IOException {
        String name = "/" + String.format(META_RESOURCE, 0);
        try (InputStream in = PBEFileDecrypt.class.getResourceAsStream(name)) {
            DataInputStream dataIn = new DataInputStream(in);
            dataIn.readInt();
            return new PBEItem(dataIn);
        }
    }

    /** The password */
    char[] password;


    /**
     * Run the application
     *
     * @throws IOException
     * @throws GeneralSecurityException
     */
    private void exec() throws IOException, GeneralSecurityException {
        password = getPassword();
        PBEItem meta0 = readMeta0();
        PBEItem[] items = readMeta1(meta0);
        for(int i = 0;i < items.length;i++) {
            readData(i, items[i]);
        }
        Arrays.fill(password, '\0');
    }


    /**
     * Read a data file and write it out
     *
     * @param i
     *            the file's index
     * @param pbeItem
     *            the associated meta data
     * @throws IOException
     * @throws GeneralSecurityException
     */
    private void readData(int i, PBEItem pbeItem)
            throws IOException, GeneralSecurityException {
        String name = "/" + String.format(DATA_RESOURCE, i);
        Cipher cipher = pbeItem.createCipher(password, Cipher.DECRYPT_MODE);
        try (InputStream in = PBEFileDecrypt.class.getResourceAsStream(name)) {
            Mac mac = pbeItem.getMac();
            @SuppressWarnings("resource")
            InputStream dataIn = new MacInputStream(
                    new GZIPInputStream(new CipherInputStream(in, cipher)),
                    mac);

            File outFile = new File(pbeItem.getPath());
            try (OutputStream out = new FileOutputStream(outFile)) {
                int r;
                byte[] buffer = new byte[0x10000];
                while( (r = dataIn.read(buffer)) != -1 ) {
                    out.write(buffer, 0, r);
                }
            }

            // Check the MAC of the meta information
            byte[] macActual = mac.doFinal();
            byte[] macExp = pbeItem.getExpectedMac();
            if( !Arrays.equals(macActual, macExp) ) {
                System.err.println("\n\nData corruption detected for "
                        + pbeItem.getPath() + "\n\n" + "MAC expected : "
                        + PBEItem.toHex(macExp) + "\nMAC observed : "
                        + PBEItem.toHex(macActual) + "\n\n");
                System.exit(1);
            }
        }
    }


    /**
     * Read the encrypted meta data
     *
     * @param meta0
     *            the PBE specification for the encrypted meta data
     * @return the decrypted meta data
     * @throws IOException
     * @throws GeneralSecurityException
     */
    private PBEItem[] readMeta1(PBEItem meta0)
            throws IOException, GeneralSecurityException {
        String name = "/" + String.format(META_RESOURCE, 1);
        Cipher cipher = meta0.createCipher(password, Cipher.DECRYPT_MODE);
        try (InputStream in = PBEFileDecrypt.class.getResourceAsStream(name)) {
            Mac mac = meta0.getMac();
            DataInputStream dataIn = new DataInputStream(
                    new MacInputStream(new CipherInputStream(in, cipher), mac));
            int count = dataIn.readInt();
            PBEItem[] items = new PBEItem[count];
            for(int i = 0;i < count;i++) {
                items[i] = new PBEItem(dataIn);
            }

            // Check the MAC of the meta information
            byte[] macActual = mac.doFinal();
            byte[] macExp = meta0.getExpectedMac();
            if( !Arrays.equals(macActual, macExp) ) {
                System.err.println(
                        "\n\nData corruption detected in meta information.\n\n"
                                + "MAC expected : " + PBEItem.toHex(macExp)
                                + "\nMAC observed : " + PBEItem.toHex(macActual)
                                + "\n\n");
                System.exit(1);
            }

            return items;
        }

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy