我正在开发基于AES-128位对称加密的基于GUI的加密器/解密器。 我的问题是如何确定没有发生解密并显示“解密失败”对话框。我编写的代码总是生成一个没有.enc扩展名的文件,无论它是否仍然是加密的!
希望能从Stack Overflow的顶级程序员那里得到答案:)
请注意解密进程不会失败或抛出异常!这只是它生成一个仍未解密的文件的事实。我们必须停下来,这就是我的意思!
此处代码:(抱歉压痕不好!)
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.security.MessageDigest;
public class FileEncryptor{
private String algo;
private String path;
private String password;
public FileEncryptor(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();
MessageDigest sha = MessageDigest.getInstance("SHA-1");
k = sha.digest(k);
k = Arrays.copyOf(k, 16);
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.getBytes();
MessageDigest sha = MessageDigest.getInstance("SHA-1");
k = sha.digest(k);
k = Arrays.copyOf(k, 16);
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
}
public static void main (String[] args)throws Exception {
System.out.println("Enter Password: ");
new FileEncryptor("AES","sample.txt",new java.util.Scanner(System.in).nextLine()).encrypt();
new FileEncryptor("AES","sample.txt.enc",new java.util.Scanner(System.in).nextLine()).decrypt();
}
}
答案 0 :(得分:1)
如果不查看API调用,解密方法应该在发生错误时抛出异常。在异常处理程序中,您可以设置一个标志,以便显示错误消息。您还可以延迟解密文件创建,直到成功解密(或至少直到第一个块成功解密后)。如果解密然后沿着该行进一步失败,则可以删除(基本上是临时的)解密输出文件并显示错误消息。
[编辑]
我稍微误解了原帖,所以有些建议要检查解密失败(注意这些比AES更高级别,因此它可能仅适用于您的应用程序):
答案 1 :(得分:1)
我建议在加密前为您的数据添加常量而不是校验和,并在加密后验证它。
加密算法应该使用链接,这意味着要避免使用ECB(请参阅此处原因:http://bobnalice.wordpress.com/2009/01/28/friends-don%E2%80%99t-let-friends-use-ecb-mode-encryption)。
使用带链接的常量几乎与校验和一样好,而且更简单。