Hallo,
ich versuche gerade einen simplen Java-Texteditor zu schreiben, der Dateien Passwort-verschlüsselt speichern kann.
Leider kriege ich anscheinend die Applikation nicht dazu zu warten bis ich das Passwort eingegeben habe. Der Text wird anscheinend mit leerem Passwort verschlüsselt. Es sind bisher vier Klassen, ich füge den Code mal ein. Ich wäre sehr dankbar wenn mir jemand helfen würde oder auch nur einen Tipp geben würde.
ich versuche gerade einen simplen Java-Texteditor zu schreiben, der Dateien Passwort-verschlüsselt speichern kann.
Leider kriege ich anscheinend die Applikation nicht dazu zu warten bis ich das Passwort eingegeben habe. Der Text wird anscheinend mit leerem Passwort verschlüsselt. Es sind bisher vier Klassen, ich füge den Code mal ein. Ich wäre sehr dankbar wenn mir jemand helfen würde oder auch nur einen Tipp geben würde.
Code:
/**
* Secure Text Editor main class.
* Allows to confidentially open and save text files.
*/
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
public class SecureTextEditor extends JFrame implements ActionListener {
/** Setup open, save, and exist menu items (awt).*/
private JMenuItem jmiOpen, jmiSave, jmiExit;
/** Setup a text area (awt).*/
private JTextArea jtaFile = new JTextArea();
/** Setup a text field of length 12 (awt).*/
private JTextField jtfFilename = new JTextField(12);
/** Setup a windows title label (awt).*/
private JLabel jlblStatus = new JLabel();
/** Setup a file chooser dialog (awt).*/
private JFileChooser jFileChooser = new JFileChooser();
/** Create an Ecryptor object (custom).*/
private Encryptor enc = new Encryptor();
/** Create a PasswordReader object (custom).*/
private PasswordReader pwd = new PasswordReader();
/**
* Secure Text Editor main method.
* Call the constructor and set visual properties.
*/
public static void main(String[] args) {
SecureTextEditor frame = new SecureTextEditor();
frame.setSize(1024, 768);
frame.setVisible(true);
}
/**
* Secure Text Editor constructor.
* Build the window and its menu.
*/
public SecureTextEditor() {
/** Set the window title (awt).*/
setTitle("SecureTextEditor");
/** Setup a menu bar (awt).*/
JMenuBar mb = new JMenuBar();
setJMenuBar(mb);
/** Setup a file menu (awt).*/
JMenu fileMenu = new JMenu("File");
mb.add(fileMenu);
fileMenu.add(jmiOpen = new JMenuItem("Open"));
fileMenu.add(jmiSave = new JMenuItem("Save"));
fileMenu.add(jmiExit = new JMenuItem("Exit"));
/** Add scroll bars (awt).*/
getContentPane().add(new JScrollPane(jtaFile), BorderLayout.CENTER);
getContentPane().add(jlblStatus, BorderLayout.SOUTH);
/** Add action listeners for open, save, exit menu items (awt-event).*/
jmiOpen.addActionListener(this);
jmiSave.addActionListener(this);
jmiExit.addActionListener(this);
}
/**
* Decide which method is called according to given parameter.
* @param e an action event.
*/
public void actionPerformed(ActionEvent e) {
String actionCommand = e.getActionCommand();
if (e.getSource() instanceof JMenuItem) {
if ("Open".equals(actionCommand)) {
open();
} else if ("Save".equals(actionCommand)) {
save();
} else if ("Exit".equals(actionCommand)) {
System.exit(0);
}
}
}
/**
* Open a file chosen by a user via file chooser.
*/
private void open() {
if (jFileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
try {
open(jFileChooser.getSelectedFile());
} catch (Exception ex) {
}
}
}
/**
* Open, decrypt, and show a file according to given parameter.
* @param file a file.
*/
private void open(File file) throws Exception {
try {
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
byte[] b = new byte[in.available()];
in.read(b, 0, b.length);
String s_dec = enc.decryptToString(b, pwd.readPassword());
jtaFile.append(s_dec);
in.close();
jlblStatus.setText(file.getName() + " Opened");
} catch (IOException ex) {
jlblStatus.setText("Error opening " + file.getName());
}
}
/**
* Save a file to a file chosen by a user via file chooser.
*/
private void save() {
if (jFileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
try {
save(jFileChooser.getSelectedFile());
} catch (Exception ex) {
}
}
}
/**
* Encrypt and save a file to a file according to given parameter.
* @param file a file.
*/
private void save(File file) throws Exception {
try {
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
byte[] b = (jtfFilename.getText()).getBytes();
out.write(b, 0, b.length);
out.write(enc.encrypt(jtaFile.getText(), pwd.readPassword()));
out.close();
jlblStatus.setText(file.getName() + " Saved ");
} catch (IOException ex) {
jlblStatus.setText("Error saving " + file.getName());
}
}
}
/**
* MyJPasswordField class.
* Custom JPasswordField class.
*/
import java.awt.*;
import javax.swing.*;
public class MyJPasswordField extends JFrame {
/** Setup a password field of length 10 (swing).*/
private JPasswordField pwd = new JPasswordField(10);
/**
* Request a password from a user and store it in the attribute pwd.
*/
public MyJPasswordField() {
super("Please enter a password!");
/** Setup a panel (swing).*/
JPanel panel = new JPanel();
/** Set background color (swing).*/
panel.setBackground(Color.red);
/** Set char to be shown when typing (swing).*/
pwd.setEchoChar('#');
/** Add password field to the panel (swing).*/
panel.add(pwd);
/** Show panel (swing).*/
getContentPane().add(panel);
}
/**
* Return the password stored in the attribute pwd.
* @return password an array of char.
*/
public char[] getPassword() {
return pwd.getPassword();
}
}
/**
* PasswordReader class.
* Allows to request a password from a user.
*/
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.swing.*;
public class PasswordReader {
/**
* Decide which method is called according to given parameter.
* @return pbeKey a secret (symmetric) key.
*/
public SecretKey readPassword() throws Exception {
/** Setup and show a password field (custom).*/
MyJPasswordField mpf = new MyJPasswordField();
mpf.setSize(150, 100);
mpf.setVisible(true);
mpf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
/** Create a user-chosen password that can be used with password-based encryption (javax-crypto-spec).*/
PBEKeySpec pbeKeySpec = new PBEKeySpec(mpf.getPassword());
/**
* Setup a key factory to convert a key specification into an opaque cryptographic key (javax-crypto).
* Use MD5 and DES algorithms.
*/
SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
/** Create an opaque cryptographic key (javax-crypto).*/
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
return pbeKey;
}
}
/**
* Encryptor class.
* Password-based encryption and decryption.
*/
import java.io.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.util.*;
public class Encryptor {
/**
* Salt according to the PKCS #5 standard.
* The PBE process requires an arbitrary salt value that is combined with the user-supplied password.
* This reduces the possibility of an attacker generating a list of all possible digested passwords.
* The salt increases the number of password digests that the attacker has to pre-compute.
* A real application would NOT use a static salt.
*/
private byte[] salt = {
(byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c,
(byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99
};
/** Iteration count.*/
private int count = 20;
/**
* Encrypt a plaintext.
* @param plaintext a plaintext.
* @param encryptionKey a password.
* @return a ciphertext.
*/
public byte[] encrypt(String plaintext, SecretKey encryptionKey) throws Exception {
/** Construct a parameter set for password-based encryption as defined in the PKCS #5 standard (crypto-spec).*/
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count);
/** Provide the functionality of a cryptographic cipher for encryption and decryption.*/
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
/** Change to encrypt mode; set encryption key and parameter set.*/
pbeCipher.init(Cipher.ENCRYPT_MODE, encryptionKey, pbeParamSpec);
/** Encrypt and return ciphertext.*/
return pbeCipher.doFinal(plaintext.getBytes());
}
/**
* Decrypt a ciphertext.
* @param ciphertext a ciphertext.
* @param encryptionKey a password.
* @return a plaintext.
*/
public String decryptToString(byte[] ciphertext, SecretKey encryptionKey) throws Exception {
/** Construct a parameter set for password-based encryption as defined in the PKCS #5 standard (crypto-spec).*/
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count);
/** Provide the functionality of a cryptographic cipher for encryption and decryption.*/
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
/** Change to decrypt mode; set encryption key and parameter set.*/
pbeCipher.init(Cipher.DECRYPT_MODE, encryptionKey, pbeParamSpec);
/** Decrypt and return plaintext.*/
return new String(pbeCipher.doFinal(ciphertext));
}
}