My app prompts the user for the password that was used to encrypt a control file. If the wrong password is entered, the app responds by creating a new control file. Therefore I need to catch a BadPaddingException so I can trigger the appropriate response.
Here's the code snippet that should generate the exception
private void existingHashFile(String file) {
psUI = new passwordUI(new javax.swing.JFrame(), true, "existing");
psUI.setVisible(true);
this.key = passwordUI.key;
try {
hash.decryptHashFile(file, this.key); //this is line 240
} catch (BadPaddingException ex) {
Logger.getLogger(homePage.class.getName()).log(Level.SEVERE, null, ex);
//then the file was not decrypted
System.out.println("BPE 2!");
} catch (Exception ex) {
Logger.getLogger(homePage.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("BPE 3!");
}
For completeness, here's the decryptHashFile method that is called above
public void decryptHashFile(String filename, String key) throws BadPaddingException, UnsupportedEncodingException, Exception {
FileInputStream fis = null;
FileOutputStream fos = null;
CipherInputStream cis = null;
String outFile = filename.replace(".enc", "");
byte[] byteKey = key.getBytes("UTF-8");
Cipher cipher = getCipher(byteKey, "decrypt");
try {
fis = new FileInputStream(filename);
fos = new FileOutputStream(outFile);
cis = new CipherInputStream(fis, cipher);
byte[] buffer = new byte[1024];
int read = cis.read(buffer);
while (read != -1) {
fos.write(buffer, 0, read);
read = cis.read(buffer); //this is line 197
}
} catch (IOException ex) {
Logger.getLogger(hashListClass.class.getName()).log(Level.SEVERE, null, ex);
} finally {
if (fos != null) {
fos.close();
}
if (cis != null) {
cis.close();
}
if (fis != null) {
fis.close();
}
}
}
When I deliberately enter the wrong password, I see this stack trace, but my code (I've used a println in the example) isn't executed:
Dec 02, 2017 2:31:34 PM appwatch.hashListClass decryptHashFile
SEVERE: null
java.io.IOException: javax.crypto.BadPaddingException: Given final block not properly padded
at javax.crypto.CipherInputStream.getMoreData(CipherInputStream.java:121)
at javax.crypto.CipherInputStream.read(CipherInputStream.java:239)
at javax.crypto.CipherInputStream.read(CipherInputStream.java:215)
at appwatch.hashListClass.decryptHashFile(hashListClass.java:197)
at appwatch.homePage.existingHashFile(homePage.java:240)
CipherInputStream.read (your line 197) throws IOException, not BadPaddingException, therefore the exception is caught by the subsequent catch (IOException ex).
After that you are not explicitly throwing other exceptions, so there is nothing else to catch after decryptHashFile.
Related
In my application i have Decrypt file with AES256 and CBC .
i have written below codes, to check if file exists.
But when run application it shows me an error and not can open my file!
I used Log.e to show files's path and it shows me this path. but it says can not open file!
My code :
private SecureRandom r;
private byte[] _iv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
r = new SecureRandom();
_iv = new byte[16];
r.nextBytes(_iv);
String inputFile = getRootDirPath(context) + "/"+bookName;
String outPutFile = getRootDirPath(context) + "/BookFile_716798_decrypt3.html";
File file = new File(inputFile);
if (file.exists()) {
try {
decrypt(inputFile, encryptionPassword, outPutFile, "");
Log.e("DecryptLog", "0");
} catch (IOException e) {
e.printStackTrace();
Log.e("DecryptLog", "1 : " + e.getMessage());
Log.e("DecryptLog", "\nPath : " + inputFile);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
Log.e("DecryptLog", "2 : " + e.getMessage());
} catch (NoSuchPaddingException e) {
e.printStackTrace();
Log.e("DecryptLog", "3 : " + e.getMessage());
} catch (InvalidKeyException e) {
e.printStackTrace();
Log.e("DecryptLog", "4 : " + e.getMessage());
}
} else {
Toast.makeText(context, "Not", Toast.LENGTH_SHORT).show();
}
}
public String getRootDirPath(Context context) {
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
File file = ContextCompat.getExternalFilesDirs(context.getApplicationContext(),
null)[0];
return file.getAbsolutePath();
} else {
return context.getApplicationContext().getFilesDir().getAbsolutePath();
}
}
private void decrypt(String path, String password, String _initVector, String outPath)
throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
FileInputStream fis = new FileInputStream(path);
FileOutputStream fos = new FileOutputStream(outPath);
byte[] key = (password).getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16);
SecretKeySpec sks = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
try {
cipher.init(Cipher.DECRYPT_MODE, sks, new IvParameterSpec(_iv));
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
CipherInputStream cis = new CipherInputStream(fis, cipher);
int b;
byte[] d = new byte[8];
while ((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
fos.flush();
fos.close();
cis.close();
}
After run application show me this error :
2020-08-01 08:03:59.324 28560-28560/com.app.appE/DecryptLog: 1 : : open failed: ENOENT (No such file or directory)
2020-08-01 08:03:59.324 28560-28560/com.app.app E/DecryptLog: Path : /storage/emulated/0/Android/data/com.app.app/files/BookFile_716798.html
In my application I want to download an HTML file from server, then decrypt this file and show into webView!
The backend developer uses this library for encrypt file from server: https://github.com/soarecostin/file-vault
I wrote the code below, but when decrypting a file, it shows an error in Logcat and doesn't decrypt this file!
My code:
encryptionPassword = "7BOF%aZQMpfJ#2wUS*S6!#K+ZB$Sz+J0";
String inputFile = FileUtils.getDirPath(this) + "/BookFile_716798.html";
String outPutFile = FileUtils.getDirPath(this) + "/BookFile_716798_decrypt.html";
try {
decrypt(inputFile, encryptionPassword, outPutFile);
Log.e("DecryptLog", "0");
} catch (IOException e) {
e.printStackTrace();
Log.e("DecryptLog", "1");
Log.e("DecryptLog", "" + e.getMessage());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
Log.e("DecryptLog", "2");
} catch (NoSuchPaddingException e) {
e.printStackTrace();
Log.e("DecryptLog", "3");
} catch (InvalidKeyException e) {
e.printStackTrace();
Log.e("DecryptLog", "4");
}
private void decrypt(String path, String password, String outPath)
throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
FileInputStream fis = new FileInputStream(path);
FileOutputStream fos = new FileOutputStream(outPath);
byte[] key = (password).getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16);
SecretKeySpec sks = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, sks);
CipherInputStream cis = new CipherInputStream(fis, cipher);
int b;
byte[] d = new byte[8];
while ((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
fos.flush();
fos.close();
cis.close();
}
This message is shown in logCat:
2020-07-31 21:52:39.881 1367-1367/com.app.app E/DecryptLog: 1
2020-07-31 21:52:39.881 1367-1367/com.app.appE/DecryptLog: javax.crypto.BadPaddingException: pad block corrupted
How can I fix it?
I am creating a tar.Gzip file using GZIPOutputStream and I have added an another logic in that if any Exception caught while compressing file then, my code will retry three times.
When I am throwing an IOException to test my retry logic it throwing a below Exception:
java.io.IOException: request to write '4096' bytes exceeds size in header of '2644' bytes for entry 'Alldbtypes'
I am getting Exception at line: org.apache.commons.io.IOUtils.copyLarge(inputStream, tarStream);
private class CompressionStream extends GZIPOutputStream {
// Use compression levels from the deflator class
public CompressionStream(OutputStream out, int compressionLevel) throws IOException {
super(out);
def.setLevel(compressionLevel);
}
}
public void createTAR(){
boolean isSuccessful=false;
int count = 0;
int maxTries = 3;
while(!isSuccessful) {
InputStream inputStream =null;
FileOutputStream outputStream =null;
CompressionStream compressionStream=null;
OutputStream md5OutputStream = null;
TarArchiveOutputStream tarStream = null;
try{
inputStream = new BufferedInputStream(new FileInputStream(rawfile));
File stagingPath = new File("C:\\Workarea\\6d22b6a3-564f-42b4-be83-9e1573a718cd\\b88beb62-aa65-4ad5-b46c-4f2e9c892259.tar.gz");
boolean isDeleted = false;
if(stagingPath.exists()){
isDeleted = stagingPath.delete();
if(stagingPath.exists()){
try {
FileUtils.forceDelete(stagingPath);
}catch (IOException ex){
//ignore
}
}
}
outputStream = new FileOutputStream(stagingPath);
if (isCompressionEnabled) {
compressionStream = new
CompressionStream(outputStream, getCompressionLevel(om));
}
final MessageDigest outputDigest = MessageDigest.getInstance("MD5");
md5OutputStream = new DigestOutputStream(isCompressionEnabled ? compressionStream : outputStream, outputDigest);
tarStream = new TarArchiveOutputStream(new BufferedOutputStream(md5OutputStream));
tarStream.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
tarStream.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_STAR);
TarArchiveEntry entry = new TarArchiveEntry("Alldbtypes");
entry.setSize(getOriginalSize());
entry.setModTime(getLastModified().getMillis());
tarStream.putArchiveEntry(entry);
org.apache.commons.io.IOUtils.copyLarge(inputStream, tarStream);
inputStream.close();
tarStream.closeArchiveEntry();
tarStream.finish();
tarStream.close();
String digest = Hex.encodeHexString(outputDigest.digest());
setChecksum(digest);
setIngested(DateTime.now());
setOriginalSize(FileUtils.sizeOf(stagingPath));
isSuccessful =true;
} catch (IOException e) {
if (++count == maxTries) {
throw new RuntimeException("Exception: " + e.getMessage(), e);
}
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(Exception("MD5 hash algo not installed.");
} catch (Exception e) {
throw new RuntimeException("Exception: " + e.getMessage(), e);
} finally {
org.apache.commons.io.IOUtils.closeQuietly(inputStream);
try {
tarStream.flush();
tarStream.finish();
} catch (IOException e) {
e.printStackTrace();
}
org.apache.commons.io.IOUtils.closeQuietly(tarStream);
org.apache.commons.io.IOUtils.closeQuietly(compressionStream);
org.apache.commons.io.IOUtils.closeQuietly(md5OutputStream);
org.apache.commons.io.IOUtils.closeQuietly(outputStream);
}
}
}
Case solved. This Exception java.io.IOException: request to write '4096' bytes exceeds size in header of '2644' bytes for entry 'Alldbtypes' thrown when the size of the file that going to be zipped is incorrect.
TarArchiveEntry entry = new TarArchiveEntry("Alldbtypes");
entry.setSize(getOriginalSize());
In my code getOriginalSize() is getting updated again at the end so in retry the original size became change and original size is now zipped file size so it was throwing this Exception.
I have the following code and it's OK when creating an encrypted zip file with the given file, however, I could not open the generated zip file with unzip command and it complains invalid zip.
"The Unarchiver" could not unzip as well.
public void encrypt(String desKey, String zipFileName, String fileName) {
InputStream inputStream = null;
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream(zipFileName);
SecretKey keySpec = new SecretKeySpec(desKey.getBytes(), "DESede");
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.DECRYPT_MODE, keySpec);
InputStream cipherInputStream = new CipherInputStream(fileInputStream, cipher);
ZipInputStream zipInputStream = new ZipInputStream(cipherInputStream);
ZipEntry nextEntry = zipInputStream.getNextEntry();
inputStream = zipInputStream;
if (nextEntry == null) {
System.out.println("error");
inputStream = null;
}
fileOutputStream = new FileOutputStream(fileName);
IOUtils.copy(inputStream, fileOutputStream);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null) {
inputStream.close();
} else if (fileInputStream != null) {
fileInputStream.close();
} else if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Zipping a stream does not means that you create a zip file... If you want to create a zip file with a crypted file in it, you should create ZipEntry, add it to the ZipOutputStream and then push your encrypted data. You can have a look at http://www.oracle.com/technetwork/articles/java/compress-1565076.html wich is a good starting point.
Here are my encryption settings:
public static String encryptionAlgorithm = "AES";
public static short encryptionBitCount = 256;
public static int encryptionMessageLength = 176;
public static String hashingAlgorithm = "PBEWITHSHAAND128BITAES-CBC-BC";
//PBEWithSHA256And256BitAES-CBC-BC"PBEWithMD5AndDES";//"PBKDF2WithHmacSHA1";
public static short hashingCount = 512;
public static String cipherTransformation = "AES/CBC/PKCS5Padding";
Here is my code to decrypt:
public byte[] readMessage () throws Exception
{
byte[] iv = new byte[16];
byte[] message = new byte[EncryptionSettings.encryptionMessageLength];
try
{
// read IV from stream
if (stream.read(iv) != 16)
throw new Exception("Problem receiving full IV from stream");
}
catch (final IOException e)
{
throw new Exception("Unable to read IV from stream");
}
try
{
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
}
catch (final InvalidKeyException e)
{
throw new Exception("Invalid key");
}
catch (final InvalidAlgorithmParameterException e)
{
throw new Exception("Invalid algorithm parameter");
}
try
{
//read message from stream
if (stream.read(message) != EncryptionSettings.encryptionMessageLength)
throw new Exception("Problem receiving full encrypted message from stream");
}
catch (final IOException e)
{
throw new Exception("Unable to read message from stream");
}
try
{
return cipher.doFinal(message); //decipher message and return it.
}
catch (IllegalBlockSizeException e)
{
throw new Exception("Unable to decrypt message due to illegal block size - "
+ e.getMessage());
}
catch (BadPaddingException e)
{
throw new Exception("Unable to decrypt message due to bad padding - "
+ e.getMessage());
}
}
Here is my code to encrypt:
public void writeMessage (final byte[] message) throws Exception
{
try
{
// write iv
byte b[] = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
System.out.println(b.length);
stream.write(b);
}
catch (final InvalidParameterSpecException e)
{
throw new Exception("Unable to write IV to stream due to invalid"+
" parameter specification");
}
catch (final IOException e)
{
throw new Exception("Unable to write IV to stream");
}
try
{
// write cipher text
byte b[] = cipher.doFinal(message);
System.out.println(b.length);
stream.write(b);
}
catch (final IllegalBlockSizeException e)
{
throw new Exception("Unable to write cipher text to stream due to "+
"illegal block size");
}
catch (final BadPaddingException e)
{
throw new Exception("Unable to write cipher text to stream due to " +
"bad padding");
}
catch (final IOException e)
{
throw new Exception("Unable to write cipher text to stream");
}
}
Error: Unable to decrypt message due to bad padding - null.
I am getting a BadPaddingException when decrypting, why? The message is exactly 168 characters which is 176 after padding (divisible by 16)
From my initial comment:
A typical scenario is one where the key is different from the one used at the other side. This is the most probable cause, but you might also want to check the way you handle streams, because you really lack .close() and possibly .flush() statements. You also assume that you always can read all the data into the buffer, which may not be the case.
The key was indeed calculated incorrectly.
BadPaddingException Error in enryption/decryption
I encountered such an error, but this helped me
http://themasterofmagik.wordpress.com/2014/03/19/simple-aes-encryption-and-decryption-in-java-part1/
hope it helps you too.