图像文件的加密和解密

时间:2012-08-27 05:19:48

标签: java image encryption aes

与我的另一个question结合使用,并在更改代码的这一小部分之后

FileOutputStream output = new FileOutputStream("sheepTest.png");
    CipherOutputStream cos = new CipherOutputStream(output, pbeCipher);
    ImageIO.write(input, "PNG", cos);
    cos.close();
从解密部分

,我遇到了另一个错误,就是这个

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)

当我点击sheepTest.png时,文件为空。错误在哪里?任何人都可以帮我解决错误吗?谢谢。

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();

   }
   }
}

2 个答案:

答案 0 :(得分:5)

除了NateCK的深刻见解(顺便说一下),我修改了你的解密部分

// 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);

我的例子是基于NateCKs的调查结果。如果你发现它很有用,那么upvote会很好,但是NateCK值得赞扬;)

答案 1 :(得分:4)

我猜这行是返回null:

BufferedImage input = ImageIO.read(inputFile);

ImageIO.read的文档说:

“如果没有已注册的ImageReader声称能够读取生成的流,则返回null。”

将null传递给此调用,从而产生NPE:

ImageIO.write(input,"PNG",  cos);

我不熟悉这个API,但是从文档和我在这里看到的内容,我想我可以推断出ImageIO.read返回null的原因是因为它试图解释文件中的图像数据,但它不能,因为它是加密的。在将数据解释为图像之前,您需要先解密数据。

您正在进行解密,但您的格式转换是使用原始的加密文件作为输入,而不是解密的图像数据。