I am trying to do an PBE encryption with AES algorithm and SunJCE provider, using the SealedObject class to encrypt/decrypt the data...
And Im still getting the "invalid stream header" exception. Ive searched this forum, readed lots of posts, examples etc...
Here is my code for encryption (i collected it from more classes, so hopefully I didnt forget anything...):
//assume that INPUT_STREAM is the source of plaintext
//and OUTPUT_STREAM is the stream to save the ciphertext data to
char[] pass; //assume initialized password
SecureRandom r = new SecureRandom();
byte[] salt = new byte[20];
r.nextBytes(salt);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(pass, salt, 1536, 128);
SecretKey pbKey = factory.generateSecret(keySpec);
SecretKeySpec key = new SecretKeySpec(pbKey.getEncoded(), "AES");
Cipher ciph = Cipher.getInstance("AES/CTR/NoPadding");
ciph.init(Cipher.ENCRYPT_MODE, key);
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
int ch;
while ((ch = INPUT_STREAM.read()) >= 0) {
byteOut.write(ch);
}
SealedObject sealed = new SealedObject(byteOut.toByteArray(), ciph);
BufferedOutputStream bufOut = new BufferedOutputStream(OUTPUTSTREAM);
ObjectOutputStream objOut = new ObjectOutputStream(bufOut);
objOut.writeObject(sealed);
objOut.close();
}
And here is my code for decrypting:
//assume that INPUT_STREAM is the source of ciphertext
//and OUTPUT_STREAM is the stream to save the plaintext data to
char[] pass; //assume initialized password
SecureRandom r = new SecureRandom();
byte[] salt = new byte[20];
r.nextBytes(salt);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(pass, salt, 1536, 128);
SecretKey pbKey = factory.generateSecret(keySpec);
SecretKeySpec key = new SecretKeySpec(pbKey.getEncoded(), "AES");
BufferedInputStream bufIn = new BufferedInputStream(INPUT_STREAM); //MARK #1
ObjectInputStream objIn = new ObjectInputStream(bufIn);
SealedObject sealed = (SealedObject) objIn.readObject();
byte[] unsealed = (byte[]) sealed.getObject(key); //MARK #2
ByteArrayInputStream byteIn = new ByteArrayInputStream(unsealed);
int ch;
while ((ch = byteIn.read()) >= 0) {
OUTPUT_STREAM.write(ch);
}
OUTPUT_STREAM.close();
Everytime I run it, it gives me this exception:
Exception in thread "main" java.io.StreamCorruptedException: invalid stream header: B559ADBE
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:783)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:280)
at javax.crypto.SunJCE_i.<init>(DashoA13*..)
at javax.crypto.SealedObject.unseal(DashoA13*..)
at javax.crypto.SealedObject.getObject(DashoA13*..)
at oopsifrovanie.engine.ItemToCrypt.decrypt(ItemToCrypt.java:91) //MARKED AS #2
at oopsifrovanie.Main.main(Main.java:37) //The class with all code below MARK #1
I've also found out that the hashCode of the generated "key" object in the decrypting routine is not the same as the hashCode of the "key" object in the ecrypting routine. Can this be a problem? I assume that maybe yes... but don't know what to do...
When I delete the r.nextBytes(salt); from both routines, the hashCodes are the same, but that's not the thing I want to do...
I think, that the source of problem can be this part of code (generating the key):
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(pass, salt, 1536, 128);
SecretKey pbKey = factory.generateSecret(keySpec);
SecretKeySpec key = new SecretKeySpec(pbKey.getEncoded(), "AES");
But I derived it from posts like: [http://forums.sun.com/thread.jspa?threadID=5307763] and [http://stackoverflow.com/questions/992019/java-256bit-aes-encryption] and they claimed it's working there...
Is there anyone that can help me?
Btw, I don't want to use any other providers like Bouncycastle etc. and I want to use PBE with AES and also SealedObject to store the parameters of encryption...