В Java File Encryption отсутствуют байты - PullRequest
2 голосов
/ 24 апреля 2011

Я пытаюсь написать простую программу для шифрования и дешифрования файлов с использованием алгоритма 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 байтов, но переменная в (cipherinputstream) возвращает -1, когда она должна возвращать последние байты. Как мне получить последние биты?

Заранее спасибо

Отредактировано: добавлен комментарий, чтобы указать, что должно быть удалено. Вот некоторый код для правильного (т.е. без загрузки всего файла в java) шифрования и дешифрования файла в Java с использованием AES. Можно добавить дополнительные параметры (отступы и т. Д.), Но вот основной код.

Ответы [ 3 ]

3 голосов
/ 24 апреля 2011

Вам просто нужно удалить эту строку в вашем коде, и она будет работать нормально:

c1.update(b3);

Поскольку вы используете CipherInputStream, вам не нужно обновлять Cipher вручную,Он справляется с этим для вас, и, вызывая его, вы вмешиваетесь в расшифровку.

На заметку, для эффективности вы должны увеличить размер ваших массивов byte[] b и byte[] b3.Обычно 8192 подходит для буферизации.

0 голосов
/ 25 ноября 2011
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));
    }  
}  
0 голосов
/ 24 апреля 2011

Вот пример кода 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);
   }

}
...