无法在AES加密/解密中将解密文件作为字符串获取

时间:2014-07-22 11:12:01

标签: java encryption cryptography aes

我正在尝试加密包含一些示例数据的文件,例如

company=abc-company

我编写了以下代码,使用密码和salt使用AES-128位密钥加密文件。我能够将文件成功加密到文件,并将解密后的数据从文件成功写入另一个文件。但是,我想将解密的数据存储在一个字符串中。所以,在SO上漫游之后,我使用了ByteArrayOutputStream。但有了这个,我无法将完整的明文输入到字符串中。我从文件中获取部分数据(只有前16个字符,即不包括'any')。如何从文件中获取完整的文本到字符串?

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TestAES {

    private static final Logger logger = LoggerFactory.getLogger(TestAES.class);
    private char[] password = "1111111111111111".toCharArray();
    private byte[] salt = "SampleSalt".getBytes();
    private byte[] initializationVector;

    public static void main(String[] args) {
        TestAES aes = new TestAES();

        aes.encrypt(new File("D:\\plainText.licence"), new File("D:\\sample.licence"));
        aes.decrypt(new File("D:\\sample.licence"));
    }

    public void encrypt(File plainTextFile, File encryptedLicenceFile) {

        if (plainTextFile.exists() == false) {
            try {
                throw new FileNotFoundException("The plainTextFile was not found");
            } catch (FileNotFoundException e) {
                logger.error("The plainTextFile was not found", e);
                e.printStackTrace();
            }
        }

        if (encryptedLicenceFile.exists() == false) {
            try {
                encryptedLicenceFile.createNewFile();
            } catch (IOException e) {
                logger.error("IOException while creating encryptedLicenceFile", e);
                e.printStackTrace();
            }
        }

        logger.info("plainTextFile.exists() = " + plainTextFile.exists());

        // To read the file to be encrypted
        FileInputStream fileInputStream = null;

        // To write the encrypted file
        FileOutputStream fileOutputStream = null;

        // To read the file information and to encrypt
        CipherInputStream cipherInputStream = null;
        try {
            fileInputStream = new FileInputStream(plainTextFile);
            fileOutputStream = new FileOutputStream(encryptedLicenceFile);

            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            KeySpec keySpec = new PBEKeySpec(password, salt, 65536, 128);
            logger.info("Generating KeySpec with password, salt.");

            SecretKey secretKey = factory.generateSecret(keySpec);
            SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            logger.debug("Obtaining AES cipher in encryption mode with secret key.");
            cipher.init(Cipher.ENCRYPT_MODE, secret);
            AlgorithmParameters parameters = cipher.getParameters();
            this.initializationVector = parameters.getParameterSpec(IvParameterSpec.class).getIV();
            logger.info("Initialization Vector length = " + initializationVector.length);

            cipherInputStream = new CipherInputStream(fileInputStream, cipher);

            int read = 0;
            while ((read = cipherInputStream.read()) != -1) {
                fileOutputStream.write((char) read);
                fileOutputStream.flush();
            }

            logger.info("Successfully written the sample.licence file.");

        } catch (NoSuchAlgorithmException e) {
            logger.error("NoSuchAlgorithmException: Check alogrithm.", e);
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            logger.error("NoSuchPaddingException: Check padding.", e);
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            logger.error("InvalidKeySpecException: Check keySpec.", e);
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            logger.error("InvalidKeyException: Check keySize.", e);
            e.printStackTrace();
        } catch (InvalidParameterSpecException e) {
            logger.error("InvalidParameterSpecException: Check parameters.", e);
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            logger.error("FileNotFoundException: Check fileToBeEncrypted.", e);
            e.printStackTrace();
        } catch (IOException e) {
            logger.error("IOException occured.", e);
            e.printStackTrace();
        } finally {
            try {
                if (cipherInputStream != null) {
                    cipherInputStream.close();
                }
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                logger.error("Exception while closing stream.", e);
                e.printStackTrace();
            }
        }

    }

    public void decrypt(File sampleLicence) {

        if (sampleLicence.exists() == false) {
            try {
                throw new FileNotFoundException("The sampleLicence was not found");
            } catch (FileNotFoundException e) {
                logger.error("The sampleLicence was not found", e);
                e.printStackTrace();
            }
        }

        // To read the sample.licence
        FileInputStream fileInputStream = null;

        // To write decrypted licence file
        FileOutputStream fileOutputStream = null;

        // To read encrypted licence file and decrypt it
        CipherOutputStream cipherOutputStream = null;
        ByteArrayOutputStream byteArrayOutputStream = null;
        try {
            fileInputStream = new FileInputStream(sampleLicence);
            byteArrayOutputStream = new ByteArrayOutputStream();

            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            KeySpec keySpec = new PBEKeySpec(password, salt, 65536, 128);
            logger.info("Generating KeySpec with password, salt during decryption.");

            SecretKey secretKey = factory.generateSecret(keySpec);
            SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            logger.debug("Obtaining AES cipher in decryption mode with secret key.");
            cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(initializationVector));

            cipherOutputStream = new CipherOutputStream(byteArrayOutputStream, cipher);
            byte[] data = new byte[4096];
            int read;
            while ((read = fileInputStream.read(data)) != -1) {
                cipherOutputStream.write(data, 0, read);
            }
            cipherOutputStream.flush();

            byte[] plainText = byteArrayOutputStream.toByteArray();
            System.out.println(new String(plainText, "UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            logger.error("NoSuchAlgorithmException: Check alogrithm.", e);
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            logger.error("NoSuchPaddingException: Check padding.", e);
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            logger.error("InvalidKeySpecException: Check keySpec.", e);
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            logger.error("InvalidKeyException: Check keySize.", e);
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            logger.error("FileNotFoundException: Check fileToBeEncrypted.", e);
            e.printStackTrace();
        } catch (IOException e) {
            logger.error("IOException occured.", e);
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            logger.error("InvalidAlgorithmParameterException", e);
            e.printStackTrace();
        } finally {
            try {
                if (cipherOutputStream != null) {
                    cipherOutputStream.close();
                }
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
                if (byteArrayOutputStream != null) {
                    byteArrayOutputStream.close();
                }
            } catch (IOException e) {
                logger.error("Exception while closing stream.", e);
                e.printStackTrace();
            }
        }

    }
}

1 个答案:

答案 0 :(得分:1)

我没有尝试过,但看起来您需要关闭cipherOutputStream

cipherOutputStream.close();

而不是你当前的冲洗。

原因是可以多次调用flush,因此在调用close之前解密将不会完成。