package test;
/**
* Created by
* newbme on 12/25/2018.
*/
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
public class MyJava {
/**
* IT IS THIS CLASS THAT WILL ENCRYPT OR DECRYPT
* ANY FILE
*/
private static final String SECRET_KEY_1 = "ssdkF$HUy2A#D%kd";
private static final String SECRET_KEY_2 = "weJiSEvR5yAC5ftB";
private IvParameterSpec ivParameterSpec;
private SecretKeySpec secretKeySpec;
private Cipher cipher;
private File from,to;
private static boolean trouble =false;
/**
* CBC MODE
*/
public MyJava(File from,File to) throws UnsupportedEncodingException, NoSuchPaddingException, NoSuchAlgorithmException {
ivParameterSpec = new IvParameterSpec(SECRET_KEY_1.getBytes("UTF-8"));
secretKeySpec = new SecretKeySpec(SECRET_KEY_2.getBytes("UTF-8"), "AES");
cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
//INITIALIZE THE PLACE TO READ AND SAVE FILE
this.from =from;
this.to =to;
//if the desination doesnt exists create it
if(! this.to .exists()){
try {
this.to.getParentFile().mkdirs();
this.to.createNewFile();
}catch (Exception ex){
ex.printStackTrace();
}
}
}
/**
*
* USE THIS METHOD TO ENCRYPT ANYTHING
*/
public boolean encrypt()throws Exception{
FileInputStream fis =null;
FileOutputStream fos=null;
boolean success =false;
try {
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
//read the file into memory
fis = new FileInputStream(from);
fos = new FileOutputStream(to);
byte [] inBytes = new byte[50*1024];
int count;
while( ( count = fis.read(inBytes)) > 0){
byte encrypted[] = cipher.doFinal(inBytes);
fos.write(encrypted,0,count);
fos.flush();
}
success =true;
}catch(InvalidKeyException ivke){
ivke.printStackTrace();
trouble = true;
}finally{
if(fis!=null)fis.close();
if(fos!=null)fos.close();
}
//return Base64.encodeBase64String(encrypted);
return success;
}
/**
*
* USE THIS METHOD TO DECRYPT ANYTHING
*/
public boolean decrypt() throws Exception{
FileInputStream fis =null;
FileOutputStream fos=null;
boolean success =false;
try {
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
//read the file into memory
fis = new FileInputStream(from);
fos = new FileOutputStream(to);
byte [] inBytes = new byte[50*1024];
int count;
while( ( count = fis.read(inBytes)) > 0){
byte decrypted[] = cipher.doFinal(inBytes);//this line fails
fos.write(decrypted,0,count);
fos.flush();
}
success =true;
}catch(InvalidKeyException ivke){
trouble = true;
ivke.printStackTrace();
}finally{
if(fis!=null)fis.close();
if(fos!=null)fos.close();
}
//return Base64.encodeBase64String(encrypted);
return success;
}
private static boolean isInvalidKeyException(){
return trouble;
}
public static void main(String [] R){
File f = new File(PATH);
//encrypt
new MyJava(f,new File("c:/logs1/"+f.getName())).encrypt();
//Toast.makeText(context,"to decrypt",Toast.LENGTH_LONG).show();
//decrypt
new MyJava(f,new File("c:/logs2/"+f.getName())).decrypt();
}
}
错误:
D/OpenSSLLib: OpensslErr:Module:30(101:); file:external/boringssl/src/crypto/cipher/cipher.c ;Line:460;Function:EVP_DecryptFinal_ex
W/System.err: javax.crypto.BadPaddingException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT
W/System.err: at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method)
W/System.err: at com.android.org.conscrypt.OpenSSLCipher$EVP_CIPHER.doFinalInternal(OpenSSLCipher.java:568)
W/System.err: at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:350)
W/System.err: at javax.crypto.Cipher.doFinal(Cipher.java:2056)
W/System.err: at com.presentapps.aiapp.utility.AISCipher.decrypt(AISCipher.java:122)
W/System.err: at com.presentapps.aiapp.popups.ActionPop$1.onClick(ActionPop.java:65)
您好,我尝试加密一个文件,该文件可以是文本文件或音乐文件等。程序有点对它进行加密,但是,当我尝试解密时,它会引发异常。 我一直在尝试使用CBC模式使其运行几天,现在有人可以指出我的错误吗?
嗯,我实际上是在Android设备上运行它,所以我在SO上发布时用“ c:”更改了根部分,所以发布的错误与从A.S上的调试器控制台获得的错误相同。
我是Java的新手,只是在我的学习上有所进步,因此可以提供任何帮助。谢谢。
答案 0 :(得分:1)
请注意,对于每个加密,实际代码均应使用非秘密的随机IV,而不是固定的秘密IV。密码应使用密码哈希功能来构成密钥。为此,可以在Android和Java上使用PBKDF2。
您的代码有很多问题:
Cipher.doFinal()
。结合固定的IV,结果实际上等效于ECB模式,因此是不安全的。对所有中间块使用Cipher.update()
,直到最后一个块,然后调用Cipher.doFinal()
。inBytes
读取少于完整缓冲区的数据时,您将提供无效数据以进行加密和解密。count
是读入的字节数,不一定是encrypted
的大小。您应该准确输出encrypted
的内容,而不是其中的一部分。PATH
处的文件进行加密,然后将结果写入c:/logs1/PATH
。然后,它尝试解密PATH
处的文件,但该文件是纯文本文件,而不是密文文件。以下是经过纠正的encrypt
和decrypt
方法:
public boolean encrypt() throws Exception {
FileInputStream fis = null;
FileOutputStream fos = null;
boolean success = false;
try {
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
//read the file into memory
fis = new FileInputStream(from);
fos = new FileOutputStream(to);
byte[] inBytes = new byte[50 * 1024];
int count;
while ((count = fis.read(inBytes)) > 0) {
byte encrypted[] = cipher.update(inBytes, 0, count);
fos.write(encrypted);
}
byte encrypted[] = cipher.doFinal();
fos.write(encrypted);
fos.flush(); // redundant, since closing the stream will flush it.
success = true;
} catch (InvalidKeyException ivke) {
ivke.printStackTrace();
trouble = true;
} finally {
if (fis != null) fis.close();
if (fos != null) fos.close();
}
//return Base64.encodeBase64String(encrypted);
return success;
}
public boolean decrypt() throws Exception {
FileInputStream fis = null;
FileOutputStream fos = null;
boolean success = false;
try {
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
//read the file into memory
fis = new FileInputStream(from);
fos = new FileOutputStream(to);
byte[] inBytes = new byte[50 * 1024];
int count;
while ((count = fis.read(inBytes)) > 0) {
byte decrypted[] = cipher.update(inBytes, 0, count);
fos.write(decrypted);
}
byte decrypted[] = cipher.doFinal();
fos.write(decrypted);
fos.flush();
success = true;
} catch (InvalidKeyException ivke) {
trouble = true;
ivke.printStackTrace();
} finally {
if (fis != null) fis.close();
if (fos != null) fos.close();
}
//return Base64.encodeBase64String(encrypted);
return success;
}