0

I have a class that stores a password (I'm going to be adding more things than just the password) called Data:

import java.io.Serializable;

public class Data implements Serializable{

    public String password = "";    

}

As a test I ran these two:

private static File datafile = new File("data.src");

public static void checkDatafile() {
        try {
            Data data = new Data();
            data.password = "Newwww";
            if (!datafile.exists()) {
                datafile.createNewFile();
                ObjectOutputStream oos = new ObjectOutputStream(
                        new FileOutputStream(datafile));
                oos.writeObject(data);
                oos.flush();
                oos.close();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

public static Data loadData(Data data) {
    try {
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(datafile));
    data = (Data) ois.readObject();
    ois.close();
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    }
    return data;
}

It writes and reads perfectly but when I open the data.src in notepad it's somewhat readable by humans and the password is not secure, this is the output of data.src:

ャ・ sr data.Data克ラ淕6J・ L passwordt Ljava/lang/String;xpt Newwww

The password is easily seen and is not safe, is there a way to encrypt/encode the object when writing to a file so that it's unreadable by humans?

Also, I'd rather stick to the standard Java libs then to download and use others.

FOD
  • 333
  • 6
  • 16
  • 3
    I'd recommend not storing passwords at all. It is better to store their hashes. That allows you to verify whether the entered password is correct, without needing to store them in a format that can be used to recover them in reasonable time. – Gregor Raýman Apr 06 '15 at 22:41
  • 1
    Yes, merely encrypting passwords allows them to be recovered by "soft" means like social engineering and reverse-engineering code. No responsible website stores passwords, encrypted or not. You hash them--with a good, salted, memory-hard hash--and store that. That way, you couldn't even leak a password under subpoena or torture. – Lee Daniel Crocker Apr 06 '15 at 22:50
  • @LeeDanielCrocker Using hash can you still change the password if asked to during runtime? – FOD Apr 06 '15 at 22:52
  • 1
    The password field should certainly be private, for the same reasons you are asking the question. And it should be a `char[],` for the same reason. – user207421 Apr 06 '15 at 22:54
  • @FOD, "changing" the password when only storing its hash value means you'll now be storing the new password's hash value – fspinnenhirn Apr 07 '15 at 00:21

4 Answers4

2

It depends on what you mean by "unreadable". If your goal is to prevent a malicious person from extracting the password, even if they have the necessary permissions to run your program, you'll be hard-pressed to do so. After all, if a program can decrypt the password, a person with the same permissions can too. Even without appropriate permissions, a malicious user could potentially inspect raw bytes in memory and extract the password if they have access to the machine.

On the other hand, if you can reasonably trust the user, but just want to avoid having them accidentally see the password in clear-text, any number of simple schemes will work; even just serializing the string as its hex codepoints would be good enough.

If you must store the password itself, i.e. you're accessing a third-party service that requires a password, you essentially have to lock down the machine and limit its access to people you absolutely trust. There's no way around that. There are a number of resources describing encrypting passwords, but they all rely on you being able to lock out users from some part of the system, generally either the encryption key or the cypher-text.

However you likely do not need to, and should not, actually be storing the password at all. The standard way to authenticate a user is to never store their password, and instead store a one-way hash of the password. This is (theoretically) impossible to decipher back into the original password, but by hashing the password the user enters when they log in and comparing it to the hash you have on file you can verify their identity without ever knowing what their password is.

Edit: One more thing about systems which need to store actual passwords. In addition to locking down the machine, you need to create a robust audit trail that records all attempts to access the passwords. Every interaction with that machine and its data should be logged and tracked so that, in the event something goes wrong, you can inspect your audit history and understand the scope of the problem. If you don't have an audit trail you'll have to assume your system is entirely compromised, because you'll have no evidence to the contrary.

Community
  • 1
  • 1
dimo414
  • 47,227
  • 18
  • 148
  • 244
1

not via ObjectOutputStream. you'll have to use a encryption library and either encrypt the complete file, or the password.

0

You can have the Data class implement the writeObject/readObject methods to encrypt/decrypt the passwords as you read and write the object.

private void writeObject(ObjectOutputStream os) throws IOException{
     password = encrypt(password);
     os.defaultWriteObject();
}

private void readObject(ObjectOutputStream os) throws IOException{
     os.defaultReadObject();
     password = decrypt(password);
}

Where encrypt/decrypt define the ecryption/decryption algorithm you wish to use. This being said and as noted in a comment by Gregor Raýman, you might consider just hashing the passwords rather than storing them.

copeg
  • 8,290
  • 19
  • 28
  • 1
    You would also have to define the password as transient. – user207421 Apr 06 '15 at 22:55
  • I'm not sure why you'd want to do that if the purpose is to encrypt its value. Marking it transient would just mark the variable to not be serialized, as opposed to actually encrypting the value of the variable during serialization – copeg Apr 06 '15 at 23:55
0

You can try encoding/decoding your content. You can use MD5 hash-functioning. There are pre-written functions and its usage is pretty simple.

The following link can help you understand how to use it in you code. http://www.asjava.com/core-java/java-md5-example/

  • to clarify: one can _encrypt/decrypt_, **or** one can _hash_, but you can't use MD5 (a hash function) to "encode/decode"; hash functions, by design, are one-way, and not reversible – fspinnenhirn Apr 07 '15 at 00:04