package cologne.eck.all_peas.control;
/*
* Peafactory - Production of Password Encryption Archives
* Copyright (C) 2015 Axel von dem Bruch
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* See: http://www.gnu.org/licenses/gpl-2.0.html
* You should have received a copy of the GNU General Public License
* along with this library.
*/
/**
* Parent class of all pea frames except image pea.
*/
import java.awt.Window;
import java.io.File;
import java.util.Arrays;
import cologne.eck.all_peas.data.PeaProperties;
import cologne.eck.all_peas.gui.CursorManager;
import cologne.eck.all_peas.gui.NewPasswordDialog;
import cologne.eck.all_peas.gui.PeaDialog;
import cologne.eck.all_peas.gui.PswDialogView;
import cologne.eck.peafactory.crypto.CipherStuff;
import cologne.eck.tools.Comparator;
import cologne.eck.tools.ReadResources;
import cologne.eck.tools.UnexpectedValueException;
import cologne.eck.tools.WriteResources;
import cologne.eck.tools.Zeroizer;
/**
* Content related utilities.
*
* @author Axel von dem Bruch
*
*/
public abstract class ContentUtilities {
/**
* Encrypt and store the current content of a file with a key. The key
* is then stored encrypted as session key.
*
* @param keyMaterial the key to encrypt
* @param plainBytes the content to encrypt
* @param fileName the file to store the encrypted content
*
* @return true if content was saved successfully
*/
public final static boolean saveContent(
byte[] keyMaterial, byte[] plainBytes, String fileName) {
if (new File(fileName).isFile() == false) {
System.err.println("ContentUtilities wrong file");
return false;
}
byte[] cipherBytes = CipherStuff.getInstance().encrypt(plainBytes,
keyMaterial, // keyMaterial is overwritten
true ); // key is stored encrypted
if (cipherBytes == null) {
return false;
}
boolean success = WriteResources.write(cipherBytes,fileName, null);
return success;
}
/**
* Get a new password from a password dialog, derive a new key,
* encrypt and save the content of files with the new key.
* The new key will then be stored encrypted as session key and
* will replace a previously stored key.
* A wait cursor is set inside this function during the process.
*
* @param fileNames the names of other files to change the password,
* the content of the files must be encrypted
* with the current session key
* @param window the owner for the NewPasswordDialog
*/
public static final void changePassword(String[] fileNames, Object window){
Window win = null;
try{
win = (Window) window;
} catch (Exception e){
System.err.println(e.toString() + ", " + e.getMessage());
new UnexpectedValueException("window", "Window", "is not correct type").printDescription();
}
// get the currently used key to decrypt several encrypted files
// unfortunately the key must be present for a while... but this is
// better than storing files in plain text for a while
byte[] oldKeyMaterial = null;
if (fileNames != null) {
oldKeyMaterial = CipherStuff.getInstance().getSessionKeyCrypt().getKey();
if (PeaProperties.getWorkingMode().equals("-t")){
Comparator.checkNullVector(oldKeyMaterial);
}
}
// get the new password:
NewPasswordDialog newPswDialog = NewPasswordDialog.getInstance(window,
PeaProperties.getBundle().getString("change_password"), null,
PswDialogView.getView().getLocation());
char[] newPsw = newPswDialog.getDialogInput();
byte[] newKeyMaterial = null;
try {
// set the wait cursor:
if (win != null) {
win.setCursor(CursorManager.getWaitCursor());
}
// derive the new key from the new password, using the same salt
newKeyMaterial = PeaControl.deriveKeyFromPsw(newPsw);
if (PeaProperties.getWorkingMode().equals("-t")){
Comparator.checkNullVector(newKeyMaterial);
}
// clear the new password
if (newPsw != null){
Zeroizer.zero(newPsw);
}
// change the password for the other file names:
for (int i = 0; i < fileNames.length; i++) {
// read the encrypted content of the files
byte[] otherCipherBytes = ReadResources.readExternFile(fileNames[i]);
if (otherCipherBytes == null) {
System.err.println("ContentUtilities, password change: "
+ "Reading content of encrypted file failed: "
+ fileNames[i]);
PeaDialog.showMessage(window,
PeaProperties.getBundle().getString("cant_read_content_of_file") + ": \n"
+ fileNames[i],
PeaProperties.getBundle().getString("error"),
0);//JOptionPane.ERROR_MESSAGE
// reset the wait cursor (modal dialog may occurred):
if (win != null) {
win.setCursor(CursorManager.getWaitCursor());
}
continue;
}
if (PeaProperties.getWorkingMode().equals("-t")){
Comparator.checkNullVector(oldKeyMaterial);
}
// decrypt the encrypted content in RAM
byte[] otherPlainBytes = CipherStuff.getInstance().decrypt(
otherCipherBytes,
Arrays.copyOf(oldKeyMaterial, oldKeyMaterial.length), // use the old key to decrypt
false ); // clear the key, do not encrypt by session key
// (otherwise this would overwrite the new key)
if (otherPlainBytes == null) {
System.err.println("ContentUtilities, password change: "
+ "Decrypting content of encrypted file failed: "
+ fileNames[i]);
PeaDialog.showMessage(window, PeaProperties.getBundle().getString("decryption_failed") + ": \n"
+ fileNames[i],
PeaProperties.getBundle().getString("error"),
0);//JOptionPane.ERROR_MESSAGE
// reset the wait cursor (modal dialog may occurred):
if (win != null) {
win.setCursor(CursorManager.getWaitCursor());
} continue;
}
if (PeaProperties.getWorkingMode().equals("-t")){
Comparator.checkNullVector(newKeyMaterial);
}
// encrypt the plain text content with the new key:
// (can't use saveContent, because keyMaterial must not be stored)
byte[] newKeyCipherBytes = CipherStuff.getInstance().encrypt(otherPlainBytes,
Arrays.copyOf(newKeyMaterial, newKeyMaterial.length), // keyMaterial is overwritten
false ); // do not encrypt by session key: clear key
if (newKeyCipherBytes == null) {
System.err.println("ContentUtilities, password change: "
+ "Encrypting content of file failed: "
+ fileNames[i]);
PeaDialog.showMessage(window,
PeaProperties.getBundle().getString("encryption_failed")+ " : \n"
+ fileNames[i],
PeaProperties.getBundle().getString("error"),
0);//JOptionPane.ERROR_MESSAGE
// reset the wait cursor (modal dialog may occurred):
if (win != null) {
win.setCursor(CursorManager.getWaitCursor());
} continue;
}
boolean success = WriteResources.write(newKeyCipherBytes, fileNames[i], null);
if (success == false) {
System.err.println("ContentUtilities, password change: "
+ "Writing content of file failed: "
+ fileNames[i]);
PeaDialog.showMessage(window,
PeaProperties.getBundle().getString("cant_write_content_of_file") + ": \n"
+ fileNames[i],
PeaProperties.getBundle().getString("error"),
0);//JOptionPane.ERROR_MESSAGE
// reset the wait cursor (modal dialog may occurred):
if (win != null) {
win.setCursor(CursorManager.getWaitCursor());
} continue;
}
}
} finally {
// reset the cursor:
if (win != null) {
win.setCursor(CursorManager.getDefaultCursor());
}
}
// zeroize the old key
Zeroizer.zero(oldKeyMaterial);
// encrypt and store the new key
if (PeaProperties.getWorkingMode().equals("-t")){
Comparator.checkNullVector(newKeyMaterial);
}
CipherStuff.getInstance().getSessionKeyCrypt().storeKey(newKeyMaterial);
// zeroize the key used here
Zeroizer.zero(newKeyMaterial);
}
/**
* Change the password for one currently used content
*
* @param plainBytes the current content
* @param fileNames the name of the file of the content
* @param window the owner for the NewPasswordDialog
*/
public static final void changePassword(
byte[] plainBytes, String fileName, Object window){
NewPasswordDialog newPswDialog = NewPasswordDialog.getInstance(window,
PeaProperties.getBundle().getString("change_password"), null,
PswDialogView.getView().getLocation());
char[] newPsw = newPswDialog.getDialogInput();
byte[] keyMaterial = PeaControl.deriveKeyFromPsw(newPsw);
if (newPsw != null){
Zeroizer.zero(newPsw);
}
if (PeaProperties.getWorkingMode().equals("-t")){
Comparator.checkNullVector(keyMaterial);
}
// encrypt and save with new key - the new key is stored
saveContent(keyMaterial, plainBytes, fileName);
Zeroizer.zero(keyMaterial);
}
}