Java tutorial
/* * EasyHash - command line utility for creating hashes * Copyright (C) 2013 Alexandru Geana (alegen) * * This program 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 3 of the License, or * (at your option) any later version. * * This program 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package net.alegen.datpass.library.configure; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import net.alegen.datpass.library.Profile; import net.alegen.datpass.library.crypto.CryptoManager; import net.alegen.datpass.library.crypto.CryptoManager.EncryptionOutput; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; import org.jdom2.input.SAXBuilder; import org.jdom2.output.Format; import org.jdom2.output.XMLOutputter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class XMLConfigurator implements Configurator { private static final Logger log = LoggerFactory.getLogger(Configurator.class); public static Configurator getInstance(String configFileName) { Configurator newInstance = null; try { if (configFileName == null) newInstance = new XMLConfigurator(); else newInstance = new XMLConfigurator(configFileName); } catch (IOException | JDOMException e) { return null; } return newInstance; } private final Element root; String configFileName; private XMLConfigurator() throws IOException, JDOMException { this("dpasscfg.xml"); } public XMLConfigurator(String configFileName) throws IOException, JDOMException { try { this.configFileName = configFileName; File configFile = new File(configFileName); if (!configFile.exists()) { this.root = new Element(XmlConstants.DATPASS); Document doc = new Document(this.root); XMLOutputter xmlOutput = new XMLOutputter(); xmlOutput.setFormat(Format.getPrettyFormat()); FileWriter fileWriter = new FileWriter(configFileName); xmlOutput.output(doc, fileWriter); fileWriter.flush(); fileWriter.close(); } else this.root = new SAXBuilder().build(configFile).getRootElement(); } catch (JDOMException e) { log.error("The XML configuration file is not valid. Please check for syntax errors."); throw e; } catch (IOException e) { log.error("There was a problem when trying to read the XML configuration file."); throw e; } } private Element getProfileRoot(String profileName) { Element profilesElem = this.root.getChild(XmlConstants.PROFILES); for (Element elem : profilesElem.getChildren()) if (elem.getName().equals(XmlConstants.PROFILE)) { String xmlname = elem.getAttributeValue(FieldManager.NAME_FIELD); if (xmlname != null && xmlname.equals(profileName)) return elem; } return null; } private boolean isValidField(Element element) { if (element.getChild(XmlConstants.CIPHERTEXT) != null && element.getChild(XmlConstants.ENC_SALT) != null && element.getChild(XmlConstants.ENC_IV) != null && element.getChild(XmlConstants.HMAC) != null) return true; return false; } public boolean profileExists(String profileName) { for (String profile : this.listProfiles()) if (profile.equals(profileName)) return true; return false; } @Override public Profile loadProfile(String profileName, String password) { Element xmlprofile = this.getProfileRoot(profileName); if (xmlprofile != null) { Profile profile = new Profile(profileName); for (Element xmlfield : xmlprofile.getChildren()) if (this.isValidField(xmlfield)) { EncryptionOutput encOutput = new CryptoManager.EncryptionOutput(xmlfield); String xmlhmac = xmlfield.getChild(XmlConstants.HMAC).getTextNormalize(); String genhmac = CryptoManager.getInstance().generateHmac(encOutput, password); if (xmlhmac != genhmac) return null; String plaintext = CryptoManager.getInstance().decrypt(encOutput, password); profile.setValue(xmlfield.getName(), plaintext); } return profile; } return null; } @Override public List<String> listProfiles() { List<String> profiles = new ArrayList<String>(); Element profilesElem = this.root.getChild(XmlConstants.PROFILES); if (profilesElem != null) for (Element elem : profilesElem.getChildren()) if (elem.getName() == XmlConstants.PROFILE) { String name = elem.getAttributeValue(FieldManager.NAME_FIELD); if (name != null) profiles.add(name); } return profiles; } @Override public boolean saveProfile(Profile profile, String profileKey) { String profileName = profile.getValue(FieldManager.NAME_FIELD); if (this.profileExists(profileName)) return false; if (!FieldManager.getInstance().verityProfileFields(profile)) return false; Element profilesElem = this.root.getChild(XmlConstants.PROFILES); if (profilesElem == null) { profilesElem = new Element(XmlConstants.PROFILES); this.root.addContent(profilesElem); } Element newProfileElem = new Element(XmlConstants.PROFILE); newProfileElem.setAttribute(FieldManager.NAME_FIELD, profile.getValue(FieldManager.NAME_FIELD)); for (Map.Entry<FieldManager.Field, String> field : profile.getValues().entrySet()) { if (!field.getKey().toString().equals(FieldManager.NAME_FIELD)) { Element fieldElem = new Element(field.getKey().toString()); CryptoManager.EncryptionOutput output = CryptoManager.getInstance().encrypt(field.getValue(), profileKey); String generatedHmac = CryptoManager.getInstance().generateHmac(output, profileKey); Element ciphertextElem = new Element(XmlConstants.CIPHERTEXT); ciphertextElem.setText(output.getCypherText()); fieldElem.addContent(ciphertextElem); Element encSaltElem = new Element(XmlConstants.ENC_SALT); encSaltElem.setText(output.getSalt()); fieldElem.addContent(encSaltElem); Element encIvElem = new Element(XmlConstants.ENC_IV); encIvElem.setText(output.getIV()); fieldElem.addContent(encIvElem); Element hmacElem = new Element(XmlConstants.HMAC); hmacElem.setText(generatedHmac); fieldElem.addContent(hmacElem); newProfileElem.addContent(fieldElem); } } profilesElem.addContent(newProfileElem); return true; } @Override public void removeProfile(String profileName) { Element profilesElem = this.root.getChild(XmlConstants.PROFILES); for (Element elem : profilesElem.getChildren()) { String name = elem.getAttributeValue(FieldManager.NAME_FIELD); if (name != null && name.equals(profileName)) { elem.detach(); return; } } } @Override public boolean saveConfig() { XMLOutputter xmlOutput = new XMLOutputter(); Format format = Format.getPrettyFormat(); format.setIndent(" "); xmlOutput.setFormat(format); try { xmlOutput.output(this.root.getDocument(), new FileOutputStream(configFileName)); return true; } catch (IOException e) { log.error("An IO exception occured while saving data."); return false; } } public boolean setValue(String name, String value) { if (name == null || name.isEmpty() || value == null || value.isEmpty()) return false; Element appValuesElem = this.root.getChild(XmlConstants.APP_VALUES); if (appValuesElem == null) { appValuesElem = new Element(XmlConstants.APP_VALUES); this.root.addContent(appValuesElem); } boolean elemExists = false; for (Element valueElem : appValuesElem.getChildren()) { String nameAttrib = valueElem.getAttributeValue(XmlConstants.NAME); if (nameAttrib != null && nameAttrib.equals(name)) { elemExists = true; valueElem.setText(value); break; } } if (!elemExists) { Element newElem = new Element(XmlConstants.VALUE); newElem.setAttribute(XmlConstants.NAME, name); newElem.setText(value); appValuesElem.addContent(newElem); } return true; } public String getValue(String name) { if (name == null || name.isEmpty()) throw new IllegalArgumentException(); Element appValuesElem = this.root.getChild(XmlConstants.APP_VALUES); if (appValuesElem != null) for (Element valueElem : appValuesElem.getChildren()) if (valueElem.getAttributeValue(XmlConstants.NAME).equals(name)) return valueElem.getText(); return null; } public Map<String, String> allValues() { Map<String, String> retVal = new HashMap<String, String>(); Element appValuesElem = this.root.getChild(XmlConstants.APP_VALUES); for (Element valueElem : appValuesElem.getChildren()) retVal.put(valueElem.getAttributeValue(XmlConstants.NAME), valueElem.getText()); return retVal; } public static class XmlConstants { private XmlConstants() { } public static final String DATPASS = "datpass"; public static final String PROFILES = "profiles"; public static final String PROFILE = "profile"; public static final String CIPHERTEXT = "ciphertext"; public static final String ENC_SALT = "enc-salt"; public static final String ENC_IV = "enc-iv"; public static final String HMAC = "hmac"; public static final String APP_VALUES = "app-values"; public static final String VALUE = "value"; public static final String NAME = "name"; } }