Download this file

ContentUtilities.java    259 lines (236 with data), 9.3 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
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);
}
}