// Hugo Haas // Convert a KeePass database into a Keyring PDB // http://larve.net/2006/KKConvert/ // Using JavaKeyringEditor classes import java.io.*; import java.util.*; public class KKConvert { private static Model model; private static Vector categories; public static String normalize(String s){ // Accents s = s.replaceAll("[èéêë]","e"); s = s.replaceAll("[ûùü]","u"); s = s.replaceAll("[ïî]","i"); s = s.replaceAll("[àâ]","a"); s = s.replaceAll("Ô","o"); s = s.replaceAll("ç","c"); s = s.replaceAll("[ÈÉÊË]","E"); s = s.replaceAll("[ÛÙ]","U"); s = s.replaceAll("[ÏÎ]","I"); s = s.replaceAll("[ÀÂ]","A"); s = s.replaceAll("Ô","O"); s = s.replaceAll("Ç","C"); return s; } private static void readPasswords(String filename) { FileReader fileReader; categories = new Vector(); try { fileReader = new FileReader(filename); } catch (Exception e) { System.err.println("Error opening password file: " + e.getMessage()); System.exit(2); return; } BufferedReader reader = new BufferedReader(fileReader); try { String line; int category = -1; boolean inComment = false; String title, username, password, comment; title = username = password = comment = null; while(true) { line = reader.readLine(); if (line == null) { break; } if (line.startsWith("*** Group: ") && line.endsWith(" ***")) { category++; String categoryName = line.substring(11, line.length() - 4); categories.add(categoryName); } else if (line.startsWith(" Title: ")) { title = normalize(line.substring(12, line.length())); title = title.replace('/','\\'); } else if (line.startsWith(" Username: ")) { username = normalize(line.substring(12, line.length())); } else if (line.startsWith(" Password: ")) { password = normalize(line.substring(12, line.length())); } else if (line.startsWith(" Comment: ")) { comment = normalize(line.substring(12, line.length())); inComment = true; } else if (line.startsWith(" ")) { comment += "\n" + normalize(line.substring(12, line.length())); } else if (inComment) { if (line.length() == 0) { inComment = false; addEntry(title, category, username, password, comment); } } }; } catch (Exception e) { return; } } private static void addEntry(String title, int category, String account, String password, String notes) { byte[] ciphertext = null; int entryId = model.getEntriesSize() + 1; int uniqueId = model.getNewUniqueId(); byte[] record = Model.toRecordFormat4(account + "\0" + password + "\0" + notes + "\0"); try { ciphertext = model.crypto.encrypt(record); } catch (Exception e) { System.err.println("Error encrypting entry: "); e.printStackTrace(); } int len = title.length() + ciphertext.length - 16 + 1; Entry entry = new Entry(entryId, title, category, Model.sliceBytes(ciphertext, 16, ciphertext.length - 16), model.crypto, category | 0x40, // ??? uniqueId, len, null); model.addEntry(entry); } public static void main(String[] args) { if (args.length != 2) { System.err.println ("Usage: KKConvert "); System.exit(1); } String source = args[0]; String target = args[1]; BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); String password = null; try { System.out.print("Enter your password: "); // FIXME: the password is displayed here password = stdin.readLine(); } catch (Exception e) { System.err.println("You need to enter a password!"); System.exit(3); } model = new Model(); try { model.loadData(target); char[] p = new char [password.length()]; password.getChars(0, password.length(), p, 0); model.crypto.setPassword(p); } catch (Exception e) { System.err.println("Error generating database:"); e.printStackTrace(); System.exit(3); } Vector v = model.getEntries(); Object[] o = v.toArray(); for(int i = 0; i < o.length; i++) { model.removeEntry(o[i]); } readPasswords(source); model.setCategories(categories); try { model.saveData(target); } catch (Exception e) { System.err.println("Error writing database:"); e.printStackTrace(); System.exit(4); } } }