我正在开发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智能社区的最佳答案。
答案 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提供商的默认设置。另请注意,我稍微更改了代码以进行测试。