-1

I'm trying to write a few helper methods to take care of reading and writing an encrypted file. I have two methods which successfully fulfill this and return an InputStream or an OutputStream (which are really the Cipher version) that I can use to read or write to the file. I have confirmed that these methods work peachy keen when wrapped with an Object stream and used to read and write an encrypted Object to file.

However, the problem arises when I try to read from an encrypted text file. I can verify that the String I feed it is being encrypted and written to the correct file, but when I try to read back from this file, the BufferedReader reports an EOF (null). The InputStream.available() method returns 0. I can assure that the file is there, is being found, and that the InputStream itself is not null. Can anybody tell me what might cause this?

Reading/Writing encrypted Object works beautifully (CorruptedStreamException is good here):

        private static void testWriteObject() {
    String path = "derp.derp";
    Derp start = new Derp("Asymmetril: " + message, 12543, 21.4, false);
    FilesEnDe.writeEncryptedObject(key, "derp.derp", start);
    echo("original");
    echo(">"+start);

    Object o;
    try {
        ObjectInputStream ois = new ObjectInputStream(ResourceManager.getResourceStatic(path));
        o = ois.readObject();
        echo("encrypted");
        echo(">"+o);
        ois.close();
    } catch (Exception e) {
        e.printStackTrace();
    }

    o = FilesEnDe.readEncryptedObject(key, path);
    echo("decrypted");
    echo(">"+o);
}

Output:

original
>Asymmetril: WE CAME, WE SAW, WE CONQUERED.; 12543; 21.4; false
[RM] > Trying to load resource: derp.derp
java.io.StreamCorruptedException
[RM] > Trying to load resource: derp.derp
decrypted
>Asymmetril: WE CAME, WE SAW, WE CONQUERED.; 12543; 21.4; false

Trying to decrypt the text file doesn't (note that the encrypted text is readable):

private static void testWriteFile() {
    String path = "EncryptedOut.txt";
    BufferedReader bis1, bis2;

    try {
        BufferedOutputStream os = new BufferedOutputStream(FilesEnDe.getEncryptedOutputStream(key, path));
        os.write(message.getBytes());
        os.flush();
                    os.close();
    } catch (IOException e1) {
        e1.printStackTrace();
    }

    echo("original");
    echo(">"+message);

    try {
        bis1 = new BufferedReader (new InputStreamReader(ResourceManager.getResourceStatic(path)));
        echo("encrypted");
        echo(">" + bis1.readLine());
        bis1.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        InputStream is = FilesEnDe.getEncryptedInputStream(key, path);
        InputStreamReader isr = new InputStreamReader(is);
        bis2 = new BufferedReader (isr);
        echo("bits in stream? " + is.available());

        echo("decrypted");
        echo(">"+bis2.readLine());
        bis2.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    }

Output:

original
>WE CAME, WE SAW, WE CONQUERED.
encrypted
>¤ƒ]£¬Vß4E?´?ùûe
[RM] > Trying to load resource: EncryptedOut.txt
bytes in stream? 0
decrypted
>null

The code used to create the CipherInputStream:

    public static InputStream getEncryptedInputStream(String key, String path) {
    try {
        InputStream is = ResourceManager.getResourceStatic(path);
        SecretKeySpec keyspec = new SecretKeySpec(getHash(key),"AES");
        Cipher c = Cipher.getInstance("AES");
        c.init(Cipher.DECRYPT_MODE, keyspec);
        return new CipherInputStream(is,c);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    }
    return null;
    }

THE PROBLEM OCCURS WHEN I TRY TO USE A CIPHERINPUTSTREAM TO DECRYPT THE FILE AND RETRIEVE THE ORIGINAL STRING.

2 Answers2

1

However, the problem arises when I try to read from an encrypted text file.

There is no such thing as an 'encrypted text file'. The result of encryption is binary, not text.

I can verify that the String I feed it is being encrypted and written to the correct file, but when I try to read back from this file, the BufferedReader reports an EOF (null).

You shouldn't be using a BufferedReader. It isn't text, it is binary. Use a BufferedInputStream.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Note that I can read the encrypted text just fine. It looks like garbage because you're right. I am forcing that binary to be read as text and it produces a lot of gibberish. The problem is that when I create a CipherInputStream from the file, I'm unable to pull anything from it, buffered or not, binary or not. Thanks for trying, though. – user3471447 Mar 28 '14 at 07:21
  • 1
    Your question was 'can anybody tell me what might cause this?' referring to the `BufferedReader,` which also features prominently as the first word of your title. I've answered it. Did you have another one? – user207421 Mar 28 '14 at 07:21
  • Your file is corrupted due to using of `PrintWriter` - it threats outgoing data as text (as char codes) insteed of raw data, and applies some filters dependent to your platform encoding. Use strict Input/Output (not writers,readers) and everything will be just fine. – Antoniossss Mar 28 '14 at 07:29
  • I've changed to title to something more appropriate and will now try replacing the printwriter. – user3471447 Mar 28 '14 at 07:32
  • I've replaced the PrintWriter with a BufferedOutputStream and wrote the bytes of the message instead. I've updated the code above to reflect this. The problem persists, though. The CipherInputStream for the file is still empty, whether I fill the file via PrintWriter or a BufferedOutputStream. Have I misunderstood what you meant? – user3471447 Mar 28 '14 at 07:39
  • `CipherInputStream.available()` is probably returning zero, as it can't know how many bytes it can read without blocking without decrypting them. If you're using that as an indication that the stream is empty, you're misusing `available()`. That's not what it's for. It's about bytes available *now* and *without blocking.* Just read the data and ignore what `available()` tells you. There are few correct uses of it, and this isn't one of them. – user207421 Mar 30 '14 at 04:19
0

It didn't matter whether I wrote via a PrintWriter or a BufferedOutputStream, nor whether I read with a Reader or not. Turns out, I forgot to close the OutputStream that created the file. As soon as I added that one little line, everything began working. Thank you to Antoniossss for suggesting I redo the broken part of my method. I wonder why Eclipse didn't mention a resource leak about it...

  • It did matter. Using a Writer or Reader on binary data is incorrect. – user207421 Mar 29 '14 at 00:16
  • You are correct, sir. However, if you had actually read my question, you would have noticed that I used the writer to write a String to a Stream. The encryption happens afterward. Later, I used a reader to read a string from a stream after the decryption had already happened. I'm not saying you're wrong, but you're solving the wrong problem and I don't appreciate being downvoted just because of a miscommunication. – user3471447 Mar 29 '14 at 02:39
  • The variable message is a String, notice how nicely it prints in the output you evidently glazed over. – user3471447 Mar 29 '14 at 02:40