18

For encryption I use something like this:

SecretKey aesKey = KeyGenerator.getInstance("AES").generateKey();
StringEncrypter aesEncrypt = new StringEncrypter(aesKey, aesKey.getAlgorithm());
String aesEncrypted= aesEncrypt.encrypt(StringContent);

If I print out aesKey I get: "javax.crypto.spec.SecretKeySpec@1708d".

So for encryption I would like to ask user for key but dont know how and what format should it be. My plan was something like this:

SecretKey aesKey = javax.crypto.spec.SecretKeySpec@1708d;
StringEncrypter aesEncrypt = new StringEncrypter(aesKey, aesKey.getAlgorithm());
String aesDecrypt = aesEncrypt.decrypt(aesEncrypted);

But seems its not working. Is there some easy way to print out the key after encryption to console so user can save it(or remember it) and then Use for Decryption ?

Whole code is here:Cannot decrypt cyphertext from text file, symmetric key implement. in java So Im sorry for posting again but Im not sure If the code is even readable(I'm newbie).

0

4 Answers 4

28

I've had to do this myself recently. And while the other answers here led me in the right direction, it could have been easier. So here is my "share" for the day, a couple of helper methods for simple AES key manipulation. (Note the dependency on Apache Commons and Codec.)

This is all in a git repo now: github.com/stuinzuri/SimpleJavaKeyStore

import static org.apache.commons.codec.binary.Hex.*;
import static org.apache.commons.io.FileUtils.*;
import java.io.*;
import java.security.NoSuchAlgorithmException;
import javax.crypto.*;
import org.apache.commons.codec.DecoderException;

public static SecretKey generateKey() throws NoSuchAlgorithmException
{
    KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
    keyGenerator.init(256); // 128 default; 192 and 256 also possible
    return keyGenerator.generateKey();
}

public static void saveKey(SecretKey key, File file) throws IOException
{
    char[] hex = encodeHex(key.getEncoded());
    writeStringToFile(file, String.valueOf(hex));
}

public static SecretKey loadKey(File file) throws IOException
{
    String data = new String(readFileToByteArray(file));
    byte[] encoded;
    try {
        encoded = decodeHex(data.toCharArray());
    } catch (DecoderException e) {
        e.printStackTrace();
        return null;
    }
    return new SecretKeySpec(encoded, "AES");
}
Sign up to request clarification or add additional context in comments.

2 Comments

Won't this fail if the array returned by getEncoded() has leading null bytes or if the first byte has the highest bit set?
I'm a fan of static utility functions and static imports :)
18

Most Java Key instances are represented as a string of bytes resulting from their getEncoded() method. This is what needs to be stored in order to reconstruct the key later.

However, to store a key safely in electronic form, it should be encrypted. Of course, encrypting the key would require another key (or password)… and so you have an infinite regress. A Java KeyStore can be used to store SecretKey objects in this manner, and that is useful when you have many secret keys that are all protected by a single "master" password. But for protecting a single key, it doesn't make a lot of sense.

One alternative is to present the key to the user in a form that can be stored in some safe manner (in many applications, that might be on a slip of paper in their wallet). This could be as simple as displaying the bytes of the key encoded in hexadecimal, Base-64, or other text encoding, and asking the user to write it down.

Another approach is to allow the user to choose a memorable password, and generate a key with that, using an algorithm like PBKDF2. The salt (and maybe the iteration count) used for key derivation would need to be recorded somewhere though. Another drawback is that people tend to choose from a relatively limited number of passwords out of the total available. So keys derived from passwords may be easier guess than than the key size suggests.


Here is an illustration of the basic technique for persisting and reconstituting a secret key.

byte[] encoded = aesKey.getEncoded();
/* Now store "encoded" somewhere. For example, display the key and 
   ask the user to write it down. */
String output = Base64.getEncoder().withoutPadding().encodeToString(encoded);
System.out.println("Keep it secret, keep it safe! " + output);

...

/* At some point, you need to reconstitute the key. Let's say the user 
   enters it as a base-64 number that you convert to bytes. */
String input = ... ;
byte[] encoded = Base64.getDecoder().decode(input);
SecretKey aesKey = new SecretKeySpec(encoded, "AES");

4 Comments

Thanks for explanation. But How can I call the key instead of genenerating one(KeyGenerator.getInstance("AES").generateKey(); )? I can now print out the key with getEncoded(), user will write it down. But how I call the key back ?
I'm seeing inconsistent reads with the new BigInteger(input, 16).toByteArray() portion of this code. More often than not its reading in 17bytes and giving me an 'invalid aes key length: 17 bytes' error when i try to use it. What might cause this?
@sapatos if the high bit of the key is set, BigInteger will add a zero byte to the beginning of the byte array to prevent it from being interpreted as a negative number. Maybe instead of new BigInteger(1, encoded), you should allow the string to be a negative number: new BigInteger(encoded)
@sapatos Now that support for base-64 is built-in, I recommend that.
4

I've stored keys in java keystore files. Here's an article that may help you out

http://www.informit.com/articles/article.aspx?p=170967&seqNum=3

Comments

0

Just for reference, the output you're seeing is the result of the default toString method and the funny number on the end is a hash code. See here. Hash codes are by design not reversible, and toString is not necessarily guaranteed to give you enough information to reconstruct the original object (although it does for certain classes).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.