Java文件加密缺少字节

时间:2011-04-24 10:14:13

标签: java file encryption

我正在尝试编写一个简单的程序来使用AES algortihm加密和解密文件。后来的意图是在一个更复杂的程序中使用将简单程序拆分为加密和解密方法。 他是该计划的加密部分:

 KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128);
SecretKey key = kg.generateKey();
 Cipher c = Cipher.getInstance("AES");
c.init(Cipher.ENCRYPT_MODE, key);
FileInputStream fis;    FileOutputStream fos;    CipherOutputStream cos;
fis = new FileInputStream("FileTo.encrypt");
fos = new FileOutputStream("Encrypted.file");

//write encrypted to file
cos = new CipherOutputStream(fos, c);
byte[] b = new byte[16];
int i = fis.read(b);
while (i != -1) {
    cos.write(b, 0, i);
    i = fis.read(b);
}
cos.close();

 //write key to file
 byte[] keyEncoded = key.getEncoded();    
 FileOutputStream kos = new FileOutputStream("crypt.key");
 kos.write(keyEncoded);
 kos.close();

这是解密部分:

 //Load Key
 FileInputStream fis2= new FileInputStream("a.key");
 File f=new File("a.key");
 long l=f.length();
 byte[] b1=new byte[(int)l];
 fis2.read(b1, 0, (int)l);



 SecretKeySpec ks2=new SecretKeySpec(b1,"AES");

  Cipher c1 = Cipher.getInstance("AES");
  c1.init(Cipher.DECRYPT_MODE, ks2);
 FileInputStream fis1=new FileInputStream("Encrypted.file");
 CipherInputStream in= new CipherInputStream(fis1,c1);
 FileOutputStream fos0 =new FileOutputStream("decrypted.file");
 byte[] b3=new byte[1];
 int ia=in.read(b3);
 while (ia >=0)
 {
    c1.update(b3); //<-------remove this
    fos0.write(b3, 0, ia);
    ia=in.read(b3);
 }
in.close();
fos0.flush();
fos0.close();

现在的问题是解密部分没有解密最后一位,有些位丢失了。在我看来,它只解密每16个字节,但是(cipherinputstream)中的变量在应该返回最后一个字节时返回-1。 我如何得到最后一位?

提前致谢

已编辑:添加评论以指出必须删除的内容。这里有一些正确的代码(即,没有在java中加载整个文件)使用AES加密和解密Java文件。可以添加其他参数(填充等),但这是基本代码。

3 个答案:

答案 0 :(得分:3)

您只需要在代码中删除此行,它就可以正常工作:

c1.update(b3);

由于您使用的是CipherInputStream,因此无需手动更新Cipher。它会为您处理,并通过调用它来干扰解密。

另外,为了提高效率,您应该增加byte[] bbyte[] b3数组的大小。通常情况下,8192是一个很好的缓冲大小。

答案 1 :(得分:0)

这是我挖出的一些DES示例代码,这可能会有所帮助......尤其是对doFinal的调用。

package forums;

import java.io.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;

/**
   This program tests the DES cipher. Usage:
   java DESTest -genkey keyfile
   java DESTest -encrypt plaintext encrypted keyfile
   java DESTest -decrypt encrypted decrypted keyfile
*/
public class DESTest
{
   private static void usage() {
      System.err.print(
          "This program tests the javax.crypto DES cipher package.\n"
        + "usage: java DESTest -genkey keyfile\n"
        + "java DESTest -encrypt plaintext encrypted keyfile\n"
        + "java DESTest -decrypt encrypted decrypted keyfile\n"
      );
   }

   public static void main(String[] args) {
      if ( args.length < 2 || args.length > 4
        || !args[0].matches("-genkey|-encrypt|-decrypt")
      ) {
          usage();
          return;
      }
      try {
         if ("-genkey".equals(args[0])) {
            KeyGenerator keygen = KeyGenerator.getInstance("DES");
            SecureRandom random = new SecureRandom();
            keygen.init(random);
            SecretKey key = keygen.generateKey();
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(args[1]));
            out.writeObject(key);
            out.close();
         } else {
            int mode;
            if ("-encrypt".equals(args[0])) {
               mode = Cipher.ENCRYPT_MODE;
            } else { //-decrypt
               mode = Cipher.DECRYPT_MODE;
            }

            ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(args[3]));
            Key key = (Key) keyIn.readObject();
            keyIn.close();

            InputStream in = new FileInputStream(args[1]);
            OutputStream out = new FileOutputStream(args[2]);
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(mode, key);

            crypt(in, out, cipher);
            in.close();
            out.close();
         }
      } catch (IOException exception) {
         exception.printStackTrace();
      } catch (GeneralSecurityException exception) {
         exception.printStackTrace();
      } catch (ClassNotFoundException exception) {
         exception.printStackTrace();
      }
   }

   /**
      Uses a cipher to transform the bytes in an input stream
      and sends the transformed bytes to an output stream.
      @param in the input stream
      @param out the output stream
      @param cipher the cipher that transforms the bytes
   */
   public static void crypt(InputStream in, OutputStream out, Cipher cipher) 
      throws IOException, GeneralSecurityException
   {
      int blockSize = cipher.getBlockSize();
      int outputSize = cipher.getOutputSize(blockSize);
      byte[] inBytes = new byte[blockSize];
      byte[] outBytes = new byte[outputSize];

      int inLength = 0;;
      boolean more = true;
      while (more) {
         inLength = in.read(inBytes);
         if (inLength == blockSize) {
            int outLength = cipher.update(inBytes, 0, blockSize, outBytes);
            out.write(outBytes, 0, outLength);
            System.out.println(outLength);
         } else {
            more = false;
         }
      }
      if (inLength > 0) {
         outBytes = cipher.doFinal(inBytes, 0, inLength);
      } else {
         outBytes = cipher.doFinal();
      }
      System.out.println(outBytes.length);
      out.write(outBytes);
   }

}

答案 2 :(得分:0)

import javax.crypto.Cipher;  
import javax.crypto.spec.SecretKeySpec;  

public class AESTest {  
     public static String asHex (byte buf[]) {
          StringBuffer strbuf = new StringBuffer(buf.length * 2);
          int i;

          for (i = 0; i < buf.length; i++) {
           if (((int) buf[i] & 0xff) < 0x10)
            strbuf.append("0");

           strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
          }

          return strbuf.toString();
     }

     public static void main(String[] args) throws Exception {  
        String keyString = "ssssssssssssssss";  
        // 546578746F2070617261207465737465 (Hex)  
        byte[] key = keyString.getBytes();  
        System.out.println(asHex(key).toUpperCase());  

        String clearText = "sdhhgfffhamayaqqqaaaa";  
        // ZXNzYXNlbmhhZWhmcmFjYQ== (Base64)  
        // 6573736173656E686165686672616361 (Hex)  
        byte[] clear = clearText.getBytes();  
        System.out.println(asHex(clear).toUpperCase());  

        SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");  
        // PKCS5Padding or NoPadding  
        Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");  
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);  

        byte[] encrypted = cipher.doFinal(clear);  
        System.out.println(asHex(encrypted).toUpperCase());  
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] original =
                    cipher.doFinal(encrypted);

        System.out.println(original);
        String originalString = new String(original);
        System.out.println("Original string: " +
                    originalString + " " + asHex(original));
    }  
}