0

How do you decrypt a file in java and export it to a file without having to end up in an infinite loop if you have more than one user and password? Here is my code and at the end is my test file:

import java.io.*;
import java.security.*;
import java.util.ArrayList;
import javax.crypto.*;

public class Checker {
    private ArrayList<String> usersList = new ArrayList<String>();
    private ArrayList<String> passwordList = new ArrayList<String>();
    private Cipher cipher = null;
    private KeyGenerator keyGen = null;
    private Key key = null;
    private PrintStream output = System.out;
    private FileOutputStream fos = null;
    Checker() {
        try {
            cipher = Cipher.getInstance("AES");
            keyGen = KeyGenerator.getInstance("AES");
            key = keyGen.generateKey();
            output = new PrintStream(new FileOutputStream("data.txt"), true);
            fos = new FileOutputStream(new File("data.txt"));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    public void check() {
        try {
            CipherInputStream cipherIn = new CipherInputStream(new FileInputStream(new File("data.txt")), cipher);
            cipher.init(Cipher.DECRYPT_MODE, key);

            int i; 
            while((i = cipherIn.read()) != -1){
                fos.write(i);
            }
            output.close();
        } catch (FileNotFoundException e) {
            System.err.println("filepath not found!");
        } catch (IOException e) {
            System.err.println("IOException: " + e);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }

    }

    public void add(String user, String password) {
        if ( !(usersList.contains(user) || passwordList.contains(password))) {
            if(usersList.isEmpty() || passwordList.isEmpty()) {
                usersList.clear();
                passwordList.clear();
                usersList.add(user);
                passwordList.add(password);
            } else {
                usersList.add(usersList.size(), user);
                passwordList.add(usersList.size() - 1, password);
            }
        }
    }

    public void display() {
        System.out.println(usersList);
        System.out.println(passwordList);
    }

    public void save() {
        try {
            for (int x = 0; x < usersList.size(); x++) {
                output.print(usersList.get(x));
                output.print("|");
                output.println(passwordList.get(x));
            }
            CipherInputStream cipherIn = new CipherInputStream(new FileInputStream(new File("data.txt")), cipher);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            int i; 
            while ((i = cipherIn.read()) != -1) {
                fos.write(i);
            }

            output.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
    }
}

public class CheckerTest {
    public static void main(String[] args) {
        Checker checker = new Checker();
        checker.add("peter", "12345");
        checker.add("mike", "67890");
        checker.display();
        checker.save();
        checker.check();
    }
}

I know that my check() method does not work fully (it doesn't actually check if they are in the list) but I just need to decrypt the file as well as, not to have the encrypted with the decrypted data all mixed up.

Unihedron
  • 10,902
  • 13
  • 62
  • 72
Tamer
  • 1,724
  • 4
  • 16
  • 15
  • 1
    *please* don't indent code with TABs. Use 4 spaces instead. – pavium Dec 26 '09 at 08:05
  • i just copied it and pasted it from eclipse – Tamer Dec 26 '09 at 08:16
  • 1
    @Tamer - that's not an excuse. You can easily configure Eclipse to use spaces instead of TABs. – Stephen C Dec 26 '09 at 09:03
  • @Stephen C - it's an excuse if the default eclipse setting is to use TABs rather than spaces. – Alastair Pitts Dec 26 '09 at 09:05
  • The SO markdown editor autoconverts tabs to spaces when using the quick button for code block indendation. Or at least it did at some point, my Eclipse spits out only spaces and I can't be bothered to check. – Esko Dec 26 '09 at 09:11

2 Answers2

1

A few hints towards your code:

  • insert comments that describe why you do things (to help you maintain / understand it later)
  • define private final constants for the magic strings like "AES" and "data.txt" that are copied all over now (less chance of typoes and easier to change if need be)
  • use base types hiding implementation details where possible, i.e. List<String> usersList
  • instead of trying to keep the usersList and passwordsList in synch, you could also create a Map<<String>,<String>> for storing passwords for usernames.
rsp
  • 23,135
  • 6
  • 55
  • 69
0

Some remarks on your code:

  1. Don't store plaintext passwords... it's just bad.
  2. Why are you doing this:

    usersList.add(usersList.size(), user); passwordList.add(usersList.size()-1, password);

    Honestly, I don't get it. Why don't you just .add() to the according list?

  3. Why do you .clear() the lists when you have checked before that they are already empty?

  4. Why won't you let two users have the same password?

For your exporting problem (I think it won't be too hard to adapt it):

 KeyGenerator kg = KeyGenerator.getInstance("DES");
 kg.init(new SecureRandom());
 SecretKey key = kg.generateKey();
 SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
 Class spec = Class.forName("javax.crypto.spec.DESKeySpec");
 DESKeySpec ks = (DESKeySpec) skf.getKeySpec(key, spec);
 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("keyfile"));
 oos.writeObject(ks.getKey());

 Cipher c = Cipher.getInstance("DES/CFB8/NoPadding");
 c.init(Cipher.ENCRYPT_MODE, key);
 CipherOutputStream cos = new CipherOutputStream(new FileOutputStream("ciphertext"), c);
 PrintWriter pw = new PrintWriter(new OutputStreamWriter(cos));
 pw.println("Stand and unfold yourself");
 pw.close();
 oos.writeObject(c.getIV());
 oos.close();

From here: http://www.java2s.com/Tutorial/Java/0490__Security/UsingCipherOutputStream.htm

Community
  • 1
  • 1
Chris
  • 9,209
  • 16
  • 58
  • 74
  • yes i noticed that. but isn't that a strange thing to do? I mean if you have more passwords than users or vice versa is it then really clever to delete everything? And in the code as posted above, if I'm not mistaken, is no possibility to ever run into such a situation – Chris Dec 26 '09 at 09:26