【问题标题】:Java File Encryption missing bytesJava 文件加密丢失字节
【发布时间】:2012-11-06 09:08:30
【问题描述】:

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

 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 个字节解密一次,但是当它应该返回最后一个字节时,变量 in(cipherinputstream) 返回 -1。 我如何获得最后的位?

提前致谢

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

【问题讨论】:

    标签: java file encryption


    【解决方案1】:

    你只需要在你的代码中删除这一行,它就可以正常工作了:

    c1.update(b3);
    

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

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

    【讨论】:

    • 它有效!非常感谢!应该知道的更好,我没有在加密部分这样做,出于某种原因,我在解密部分做了。再次感谢。
    • 是的,我只使用 1 字节缓冲区来尝试找出问题所在。我使用的是 2k 缓冲区。
    【解决方案2】:

    这是我挖出的一些 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);
       }
    
    }
    

    【讨论】:

      【解决方案3】:
      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));
          }  
      }  
      

      【讨论】:

        猜你喜欢
        • 2019-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-24
        • 1970-01-01
        • 2018-09-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多