Reputation: 199
In conjunction from my another question, and after changing this small part of the codes
FileOutputStream output = new FileOutputStream("sheepTest.png");
CipherOutputStream cos = new CipherOutputStream(output, pbeCipher);
ImageIO.write(input, "PNG", cos);
cos.close();
from the decrypt part, I've faced another error which is this
Exception in thread "main" java.lang.IllegalArgumentException: image == null!
at javax.imageio.ImageTypeSpecifier.createFromRenderedImage(Unknown Source)
at javax.imageio.ImageIO.getWriter(Unknown Source)
at javax.imageio.ImageIO.write(Unknown Source)
at encypt.com.trial.main(trial.java:82)
and when i click the sheepTest.png, the file is empty. Where is the mistake(s)? Can anyone help me to solve the error? Thank you.
public class trial {
public static void main(String[] arg) throws Exception {
// Scanner to read the user's password. The Java cryptography
// architecture points out that strong passwords in strings is a
// bad idea, but we'll let it go for this assignment.
Scanner scanner = new Scanner(System.in);
// Arbitrary salt data, used to make guessing attacks against the
// password more difficult to pull off.
byte[] salt = { (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c,
(byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99 };
{
File inputFile = new File("sheep.png");
BufferedImage input = ImageIO.read(inputFile);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
// Get a password from the user.
System.out.print("Password: ");
System.out.flush();
PBEKeySpec pbeKeySpec = new PBEKeySpec(scanner.nextLine().toCharArray());
// Set up other parameters to be used by the password-based
// encryption.
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, 20);
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
// Make a PBE Cyhper object and initialize it to encrypt using
// the given password.
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
FileOutputStream output = new FileOutputStream("sheepTest.png");
CipherOutputStream cos = new CipherOutputStream(
output, pbeCipher);
//File outputFile = new File("image.png");
ImageIO.write(input,"PNG",cos);
cos.close();
}
// Now, create a Cipher object to decrypt for us. We are repeating
// some of the same code here to illustrate how java applications on
// two different hosts could set up compatible encryption/decryption
// mechanisms.
{
File inputFile = new File("sheepTest.png");
BufferedImage input = ImageIO.read(inputFile);
// Get another (hopefully the same) password from the user.
System.out.print("Decryption Password: ");
System.out.flush();
PBEKeySpec pbeKeySpec = new PBEKeySpec(scanner.next().toCharArray());
// Set up other parameters to be used by the password-based
// encryption.
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, 20);
SecretKeyFactory keyFac = SecretKeyFactory
.getInstance("PBEWithMD5AndDES");
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
// Make a PBE Cyper object and initialize it to decrypt using
// the given password.
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec);
// Decrypt the ciphertext and then print it out.
/*byte[] cleartext = pbeCipher.doFinal(ciphertext);
System.out.println(new String(cleartext));*/
FileOutputStream output = new FileOutputStream("sheepTest.png");
CipherOutputStream cos = new CipherOutputStream(
output, pbeCipher);
ImageIO.write(input,"PNG", cos);
cos.close();
}
}
}
Upvotes: 0
Views: 13337
Reputation: 347314
Further to NateCK's insightful post (well done by the way), I've modified your decrypt section
// Note that we are not reading the image in here...
System.out.print("Decryption Password: ");
System.out.flush();
PBEKeySpec pbeKeySpec = new PBEKeySpec(scanner.next().toCharArray());
// Set up other parameters to be used by the password-based
// encryption.
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, 20);
SecretKeyFactory keyFac = SecretKeyFactory
.getInstance("PBEWithMD5AndDES");
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
// Make a PBE Cyper object and initialize it to decrypt using
// the given password.
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec);
// We're now going to read the image in, using the cipher
// input stream, which wraps a file input stream
File inputFile = new File("sheepTest.png");
FileInputStream fis = new FileInputStream(inputFile);
CipherInputStream cis = new CipherInputStream(fis, pbeCipher);
// We then use all that to read the image
BufferedImage input = ImageIO.read(cis);
cis.close();
// We then write the dcrypted image out...
// Decrypt the ciphertext and then print it out.
FileOutputStream output = new FileOutputStream("sheepTest.png");
ImageIO.write(input, "PNG", output);
My example is based on NateCKs findings. If you find it useful, an upvote would be nice, but NateCK deserves the credit ;)
Upvotes: 6
Reputation: 5932
I'd guess that this line is returning null:
BufferedImage input = ImageIO.read(inputFile);
The documentation for ImageIO.read
says:
"If no registered ImageReader claims to be able to read the resulting stream, null is returned."
That null is passed on to this call, which results in the NPE:
ImageIO.write(input,"PNG", cos);
I'm not familiar with this API, but from the documentation and what I see here, I think I can infer that the reason ImageIO.read
is returning null is because it's trying to interpret the image data in the file, but it can't because it's encrypted. You need to decrypt the data first before you can interpret it as an image.
You are doing the decryption, but your format conversion is using the original, encrypted file as its input, not the decrypted image data.
Upvotes: 4