I wonder if you're allowed to reuse the same key (declared as "final")
between encoding and decoding.

Other than that, and Nikolay's advice, here is what I do:


private static final byte[] SALT = { ...  };
private static final int COUNT = 10;
private static final byte[] REFERENCE_DATA = "Reference
data".getBytes(US_ASCII);
private static final String ALGORITHM = "PBEWithMD5AndDES";

public OutputStream wrapCipherOutputStream(OutputStream streamOut, String
password)
throws IOException, GeneralSecurityException {

PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(SALT, COUNT);

SecretKeyFactory keyFac = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);

Cipher pbeCipher = Cipher.getInstance(ALGORITHM);
pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);

/*
 * Write predefined data first (see the reading code)
 */
byte[] output = pbeCipher.doFinal(REFERENCE_DATA);
streamOut.write(output.length);
streamOut.write(output);

return new CipherOutputStream(streamOut, pbeCipher);
}

public InputStream wrapCipherInputStream(InputStream streamIn, String
password)
throws IOException, GeneralSecurityException {

PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(SALT, COUNT);

SecretKeyFactory keyFac = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);

Cipher pbeCipher = Cipher.getInstance(ALGORITHM);
pbeCipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec);

/*
 * Read a predefined data block. If the password is incorrect, we'll get a
security
 * exception here. Without this, we will only get an IOException later when
reading
 * the CipherInputStream, which is not specific enough for a good error
message.
 */
int count = streamIn.read();
if (count <= 0 || count > 1024) {
throw new IOException(
mContext.getString(R.string.backup_restore_error_bad_file));
}

byte[] input = new byte[count];
streamIn.read(input);
pbeCipher.doFinal(input);

return new CipherInputStream(streamIn, pbeCipher);
}

-- Kostya

2011/10/2 Nikolay Elenkov <nikolay.elen...@gmail.com>

> On Mon, Oct 3, 2011 at 2:36 AM, mac-systems <jens.h...@gmx.de> wrote:
> > I try to read encrypted data, but always get java.io.IOException: last
> > block incomplete in decryption
>
> Dump the encrypted stream to file and check its length. It must be a
> multiple of 8 (block size is 64 bits for DES) for decryption to work.
> If it's not, check your code, you probably have a bug somewhere.
>
> And don't use DES if you can avoid it.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Android Developers" group.
> To post to this group, send email to android-developers@googlegroups.com
> To unsubscribe from this group, send email to
> android-developers+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/android-developers?hl=en
>

-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Reply via email to