AES与GUI无法正常工作

时间:2014-08-10 04:22:14

标签: encryption javafx cryptography aes

我正在开发JavaFX中的AES-128位对称密钥加密器。这是我的疑问:当一个人点击加密按钮时,下面附加的类加密方法被称为。但是当有人试图使用给定的方法解密文件时,它实际上并不解密。它提供了一个仍然加密的文件

同样的事情,当我为基于控制台的程序执行时,它运作完美。

GUI类(不起作用的项目摘录!)

package application;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Arrays;

import javafx.application.Platform;
import javafx.concurrent.Service;
import javafx.concurrent.Task;

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

public class AESEncryption {

private final File toBeUsed;
private final String password;

public AESEncryption(String passkey, File given){
    this.password = passkey;
    this.toBeUsed = given;
}

public void encrypt(boolean toBeLocal){
    Service<Void> encryption = new Service<Void>() {

        @Override
        protected Task<Void> createTask() {

            return new Task<Void>(){

                @Override
                protected Void call() throws Exception {
                    if(toBeLocal) this.startEncryption();
                    this.success();
                    return null;

                }

                private void success() {
                    Platform.runLater(new Runnable() {

                        @Override
                        public void run() {
                            EncryptionSuccessController controller = (EncryptionSuccessController)new OfflineWindow("/fxml/encryption_success.fxml", "Success").getLoader().getController();
                            controller.setPath(toBeUsed.getAbsolutePath()+".enc");
                        }

                    });
                }

                private void startEncryption() throws Exception{
                     SecureRandom randomizer = new SecureRandom();
                     byte[] salt = new byte[16];
                     randomizer.nextBytes(salt);

                     byte key[] = (password+salt).getBytes("UTF-8");  
                     MessageDigest sha = MessageDigest.getInstance("SHA-1");
                     key = sha.digest(key);
                     key = Arrays.copyOf(key, 16);

                     SecretKeySpec pass = new SecretKeySpec(key,"AES");  
                     Cipher encrypt =  Cipher.getInstance("AES");  
                     encrypt.init(Cipher.ENCRYPT_MODE, pass);

                     FileOutputStream fos = new FileOutputStream(toBeUsed.getAbsolutePath() +".enc");
                     try(FileInputStream fis =new FileInputStream(toBeUsed.getAbsolutePath())){
                        try(CipherOutputStream cout=new CipherOutputStream(fos, encrypt)){
                            copy(fis,cout);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                     }
                }

                private void copy(InputStream is,OutputStream os) throws Exception{
                     byte buf[] = new byte[4096];
                     int read = 0;
                     while((read = is.read(buf)) != -1) os.write(buf,0,read); 
                }
            };

        };
    };
    encryption.start(); 
}

public void decrypt(boolean isLocallyEncrypted){
    Service<Void> decryption = new Service<Void>() {

        @Override
        protected Task<Void> createTask() {

            return new Task<Void>(){

                @Override
                protected Void call() throws Exception {

                    if(isLocallyEncrypted) this.startDecryption();
                    this.message();
                    return null;

                }

                private void message() {
                    Platform.runLater(new Runnable(){

                        @Override
                        public void run() {
                            DecryptionCompleteController controller = (DecryptionCompleteController)new OfflineWindow("/fxml/decryption_over.fxml", "Completed").getLoader().getController();
                            controller.setPath(toBeUsed.getAbsolutePath());
                        }

                    });
                }

                private void startDecryption() throws Exception{
                    SecureRandom randomizer = new SecureRandom();
                    byte[] salt = new byte[16];
                    randomizer.nextBytes(salt);
                    byte key[] = (password+salt).getBytes("UTF-8");  
                    MessageDigest sha = MessageDigest.getInstance("SHA-1");
                    key = sha.digest(key);
                    key = Arrays.copyOf(key, 16); 

                    SecretKeySpec pass = new SecretKeySpec(key,"AES");  
                    Cipher decrypt =  Cipher.getInstance("AES");  
                    decrypt.init(Cipher.DECRYPT_MODE, pass);
                    FileInputStream fis = new FileInputStream(toBeUsed.getAbsolutePath());
                    try(CipherInputStream cin=new CipherInputStream(fis, decrypt)){  
                       try(FileOutputStream fos =new FileOutputStream(toBeUsed.getAbsolutePath().substring(0,toBeUsed.getAbsolutePath().lastIndexOf(".")))){
                          copy(cin,fos);
                       }
                    }
                }

                private void copy(InputStream is,OutputStream os) throws Exception{
                     byte buf[] = new byte[4096];
                     int read = 0;
                     while((read = is.read(buf)) != -1) os.write(buf,0,read); 
                }
            };

        };

    };
    decryption.start();
  }

}

基于控制台的代码:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Arrays;

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


public class AES {
private String algo;
 private String path;
 private String password;
 public AES(String algo,String path, String password) {
     this.algo = algo; //setting algo
     this.path = path;//setting file path
     this.password = password;
    }

    public void encrypt() throws Exception{
     SecureRandom padding = new SecureRandom();
     byte[] salt = new byte[16];
     padding.nextBytes(salt);
         //generating key
     byte k[] = (password+salt).getBytes("UTF-8");  
     MessageDigest sha = MessageDigest.getInstance("SHA-1");
     k = sha.digest(k);
     k = Arrays.copyOf(k, 16);  
     for(int i=0;i<k.length;i++) System.out.print(k[i]);
         SecretKeySpec key = new SecretKeySpec(k,algo);  
         //creating and initialising cipher and cipher streams
         Cipher encrypt =  Cipher.getInstance(algo);  
         encrypt.init(Cipher.ENCRYPT_MODE, key);
         //opening streams
         FileOutputStream fos =new FileOutputStream(path+".enc");
         try(FileInputStream fis =new FileInputStream(path)){
            try(CipherOutputStream cout=new CipherOutputStream(fos, encrypt)){
                copy(fis,cout);
            }
         }
     }

     public void decrypt() throws Exception{
     SecureRandom padding = new SecureRandom();
     byte[] salt = new byte[16];
     padding.nextBytes(salt);
         //generating same key
      byte k[] = (password+salt).getBytes("UTF-8");  
     MessageDigest sha = MessageDigest.getInstance("SHA-1");
     k = sha.digest(k);
     k = Arrays.copyOf(k, 16); 
      for(int i=0;i<k.length;i++) System.out.print(k[i]);
         SecretKeySpec key = new SecretKeySpec(k,algo);  
         //creating and initialising cipher and cipher streams
         Cipher decrypt =  Cipher.getInstance(algo);  
         decrypt.init(Cipher.DECRYPT_MODE, key);
         //opening streams
         FileInputStream fis = new FileInputStream(path);
         try(CipherInputStream cin=new CipherInputStream(fis, decrypt)){  
            try(FileOutputStream fos =new FileOutputStream(path.substring(0,path.lastIndexOf(".")))){
               copy(cin,fos);
           }
         }
      }

  private void copy(InputStream is,OutputStream os) throws Exception{
     byte buf[] = new byte[4096];  //4K buffer set
     int read = 0;
     while((read = is.read(buf)) != -1)  //reading
        os.write(buf,0,read);  //writing
  }

}

一直期待Stack Overflow智能社区的最佳答案。

2 个答案:

答案 0 :(得分:1)

看起来您的GUI应用程序中的salt值在加密和解密之间是不同的。我不确定为什么它在你的控制台应用程序中是一样的,但是为了使用你正在使用的方法获得相同的密钥,salt也应该是相同的。

答案 1 :(得分:0)

您的盐对于加密和解密都是随机的;这将永远不会起作用,因为每次键都不同(你应该记下)。

您不能将字节数组连接到字符串。隐式地调用toString()方法,它只显示有关引用的一些信息。

public class AES_GUI {
    private String algo;
    private String path;
    private String password;

    public AES_GUI(String algo, String path, String password) {
        this.algo = algo; // setting algo
        this.path = path;// setting file path
        this.password = password;
    }

    public void encrypt() throws Exception {
        SecureRandom padding = new SecureRandom();
        byte[] salt = new byte[16];
        padding.nextBytes(salt);
        // generating key
        byte k[] = password.getBytes("UTF-8");
        MessageDigest sha = MessageDigest.getInstance("SHA-1");
        sha.update(salt);
        k = sha.digest(k);
        k = Arrays.copyOf(k, 16);
        for (int i = 0; i < k.length; i++)
            System.out.print(k[i]);
        System.out.println();

        SecretKeySpec key = new SecretKeySpec(k, algo);
        // creating and initialising cipher and cipher streams
        Cipher encrypt = Cipher.getInstance(algo);
        encrypt.init(Cipher.ENCRYPT_MODE, key);
        // opening streams
        FileOutputStream fos = new FileOutputStream(path + ".enc");
        fos.write(salt);
        try (FileInputStream fis = new FileInputStream(path)) {
            try (CipherOutputStream cout = new CipherOutputStream(fos, encrypt)) {
                copy(fis, cout);
            }
        }
    }

    public void decrypt() throws Exception {
        BufferedInputStream fis = new BufferedInputStream(new FileInputStream(path + ".enc"), 16);

        byte[] salt = new byte[16];
        int read = fis.read(salt);
        if (read != 16) {
            throw new IllegalStateException();
        }

        // generating same key
        byte k[] = password.getBytes("UTF-8");
        MessageDigest sha = MessageDigest.getInstance("SHA-1");
        sha.update(salt);
        k = sha.digest(k);
        k = Arrays.copyOf(k, 16);
        for (int i = 0; i < k.length; i++)
            System.out.print(k[i]);
        System.out.println();
        SecretKeySpec key = new SecretKeySpec(k, algo);
        // creating and initialising cipher and cipher streams
        Cipher decrypt = Cipher.getInstance(algo);
        decrypt.init(Cipher.DECRYPT_MODE, key);
        // opening streams
        try (CipherInputStream cin = new CipherInputStream(fis, decrypt)) {
            try (FileOutputStream fos = new FileOutputStream(path + ".dec")) {
                copy(cin, fos);
            }
        }
    }

    private void copy(InputStream is, OutputStream os) throws Exception {
        byte buf[] = new byte[4096]; // 4K buffer set
        int read = 0;
        while ((read = is.read(buf)) != -1)
            // reading
            os.write(buf, 0, read); // writing
    }
}

请注意,此代码不安全。您应该尝试使用PBKDF2从密码派生密钥,并使用与ECB不同的操作模式(这是Oracle SUN提供商的默认设置。另请注意,我稍微更改了代码以进行测试。