package org.fnppl.opensdx.security; import java.io.ByteArrayInputStream; import java.util.Arrays; import java.util.Vector; import javax.print.Doc; import org.bouncycastle.crypto.digests.SHA256Digest; import org.fnppl.opensdx.gui.Dialogs; import org.fnppl.opensdx.security.SecurityHelper.HexDecoder; import org.fnppl.opensdx.xml.Document; import org.fnppl.opensdx.xml.Element; import org.fnppl.opensdx.xml.XMLHelper; /* * Copyright (C) 2010-2015 * fine people e.V. <opensdx@fnppl.org> * Henning Thieß <ht@fnppl.org> * * http://fnppl.org */ /* * Software license * * As far as this file or parts of this file is/are software, rather than documentation, this software-license applies / shall be applied. * * This file is part of openSDX * openSDX is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * openSDX 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 Lesser General Public License * and GNU General Public License along with openSDX. * If not, see <http://www.gnu.org/licenses/>. * */ /* * Documentation license * * As far as this file or parts of this file is/are documentation, rather than software, this documentation-license applies / shall be applied. * * This file is part of openSDX. * Permission is granted to copy, distribute and/or modify this document * under the terms of the GNU Free Documentation License, Version 1.3 * or any later version published by the Free Software Foundation; * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. * A copy of the license is included in the section entitled "GNU * Free Documentation License" resp. in the file called "FDL.txt". * */ public class KeyLog { private String ipv4 = null; private String ipv6 = null; private KeyLogAction action; private byte[] sha256localproof = null; private Signature signature = null; private Vector<DataSourceStep> datapath = null; private KeyLog() { } public static KeyLog buildNewKeyLog(KeyLogAction keylogAction, String ip4, String ip6, OSDXKey signingKey) throws Exception { KeyLog kl = new KeyLog(); kl.ipv4 = ip4; kl.ipv6 = ip6; kl.action = keylogAction; kl.sha256localproof = kl.calcSha256LocalProof(); kl.signature = Signature.createSignatureFromLocalProof(kl.sha256localproof, "signature of ipv4, ipv6 and signaturebytes", signingKey); return kl; } public Result verify() throws Exception { Result v = action.verifySignature(); if (v.succeeded && signature!=null) { v = verifyLocalproofAndSignature(); } return v; } public byte[] calcSha256LocalProof() throws Exception { //localproof of ipv4, ipv6, action.signature.signaturesbytes byte[] ret = new byte[32]; //256 bit = 32 byte SHA256Digest sha256 = new org.bouncycastle.crypto.digests.SHA256Digest(); byte[] data; if (ipv4!=null && ipv4.length()>0) { data = ipv4.getBytes("UTF-8"); //System.out.println("ipv4: "+ipv4); sha256.update(data, 0,data.length); } if (ipv6!=null && ipv4.length()>0) { data = ipv6.getBytes("UTF-8"); //System.out.println("ipv6: "+ipv6); sha256.update(data, 0,data.length); } data = action.getSignatureBytes(); if (data!=null) { //System.out.println("sigbytes: "+SecurityHelper.HexDecoder.encode(data, '\0', -1)); sha256.update(data, 0,data.length); } sha256.doFinal(ret, 0); return ret; } // public static KeyLog buildNewKeyLog(String action, OSDXKey from, String toKeyID, String ip4, String ip6, Identity id) throws Exception { // KeyLog kl = new KeyLog(); // kl.action = action; // kl.datetime = System.currentTimeMillis(); // kl.ipv4 = ip4; // kl.ipv6 = ip6; // kl.fromKeyid = from.getKeyID(); // kl.toKeyid = toKeyID; // kl.id = id; // kl.datapath = new Vector<DataSourceStep>(); // kl.signoffAction(from); // kl.sha256localproof = null; // kl.signature = null; // // return kl; // } // // public static KeyLog buildNewRevocationKeyLog(String fromKeyID, String toKeyID, String message, byte[] actionproof, Signature actionSignature, String ip4, String ip6, OSDXKey serverSignoffKey) throws Exception { // KeyLog kl = new KeyLog(); // kl.action = KeyLog.REVOCATION; // kl.datetime = System.currentTimeMillis(); // kl.ipv4 = ip4; // kl.ipv6 = ip6; // kl.fromKeyid = fromKeyID; // kl.toKeyid = toKeyID; // kl.id = null; // kl.message = message; // kl.datapath = new Vector<DataSourceStep>(); // kl.actionSha256localproof = actionproof; // kl.actionSignature = actionSignature; // kl.signoffKeyServer(serverSignoffKey); // // return kl; // } // public Vector<String[]> getStatusElements() { // Vector<String[]> v = new Vector<String[]>(); // if (message!=null) { // v.add(new String[]{"message", message}); // } // if (id!=null) { // v.add(new String[]{"identnum", id.getIdentNumString()}); // v.add(new String[]{"email", id.getEmail()}); // v.add(new String[]{"mnemonic", id.getMnemonic()}); // // v.add(new String[]{"country", id.getCountry()}); // v.add(new String[]{"region", id.getRegion()}); // v.add(new String[]{"city", id.getCity()}); // v.add(new String[]{"postcode", id.getPostcode()}); // // v.add(new String[]{"company", id.getCompany()}); // v.add(new String[]{"unit", id.getUnit()}); // v.add(new String[]{"subunit", id.getSubunit()}); // v.add(new String[]{"function", id.getFunction()}); // // v.add(new String[]{"surname", id.getSurname()}); // v.add(new String[]{"middlename", id.getMiddlename()}); // v.add(new String[]{"name", id.getFirstNames()}); // // v.add(new String[]{"phone", id.getPhone()}); // v.add(new String[]{"note", id.getNote()}); // } // return v; // } private Result verifyLocalproofAndSignature() throws Exception { Element report = new Element("signature_verification_report"); if (signature == null) { report.addContent("error", "missing signature"); return Result.error(report); } if (sha256localproof == null) { report.addContent("error", "missing keyserver localproof"); return Result.error(report); } //check localproof byte[] bsha256 = calcSha256LocalProof(); if (!Arrays.equals(bsha256, sha256localproof)) { System.out.println("sha256localproof given : "+SecurityHelper.HexDecoder.encode(sha256localproof, '\0', -1)); System.out.println("sha256localproof calculated : "+SecurityHelper.HexDecoder.encode(bsha256, '\0', -1)); report.addContent("error", "verification of sha256localproof failed"); return Result.error(report); } //check signoff Result r = signature.tryVerificationMD5SHA1SHA256(bsha256); if (r.report != null) { //copy report content for (Element e : r.report.getChildren()) { report.addContent(XMLHelper.cloneElement(e)); } } else { throw new RuntimeException("signature verification DID NOT return a report!"); } if (r.succeeded) { return Result.succeeded(report); } else { return Result.error(report); } } // private void updateSha1(String field, org.bouncycastle.crypto.digests.SHA1Digest sha1) throws Exception { // if (field==null || field.length()==0) return; // byte[] k = field.getBytes("UTF-8"); // if (k.length>0) { // sha1.update(k, 0, k.length); // //System.out.println("update: "+field);//+"::"+SecurityHelper.HexDecoder.encode(k, ':', -1)); // } // } public static KeyLog fromElement(Element e) throws Exception { return fromElement(e, true); } private static KeyLog fromElement(Element e, boolean tryVerification) throws Exception { //Document.buildDocument(e).output(System.out); KeyLog kl = new KeyLog(); kl.action = KeyLogAction.fromElement(e.getChild("keylogaction")); if (e.getName().equals("keylog")) { //full keylog kl.ipv4 = e.getChildText("ipv4"); kl.ipv6 = e.getChildText("ipv6"); String sSha256 = e.getChildText("sha256localproof"); if (sSha256!=null && sSha256.length()>0) { kl.sha256localproof = SecurityHelper.HexDecoder.decode(sSha256); kl.signature = Signature.fromElement(e.getChild("signature")); //System.out.println("NO SIGNATURE FOUND"); } //System.out.println(sDate+" -> datetime::"+kl.datetime); } else { throw new RuntimeException("wrong keyname"); } //build datapath kl.datapath = new Vector<DataSourceStep>(); Element dp = e.getChild("datapath"); if (dp!=null) { Vector<Element> steps = dp.getChildren(); for (Element st : steps) if (st.getName().startsWith("step")) { DataSourceStep dst = DataSourceStep.fromElemet(st); kl.datapath.add(dst); } } if (tryVerification) { Result v = kl.verify(); //Document.buildDocument(kl.toElement(true)).output(System.out); if(!v.succeeded) { if (v.errorMessage!=null) { System.out.println(v.errorMessage); } if (v.report!=null) { Document.buildDocument(v.report).output(System.out); } throw new Exception("KeyLog: verification of localproof and signature failed."); } } return kl; } public String getActionElementString() { Element e = action.getActionElement(true); return Document.buildDocument(e).toStringCompact(); } public Element toElement(boolean showRestricted) { Element e = new Element("keylog"); e.addContent("ipv4",ipv4); e.addContent("ipv6",ipv6); e.addContent(action.toElement(showRestricted)); if (sha256localproof!=null) { e.addContent("sha256localproof", SecurityHelper.HexDecoder.encode(sha256localproof, ':', -1)); if (signature!=null) { e.addContent(signature.toElement()); } } Element edp = new Element("datapath"); if (datapath!=null) { for (int i=0;i<datapath.size();i++) { edp.addContent(datapath.get(i).toElement(i)); } } e.addContent(edp); //Document doc = Document.buildDocument(e); //doc.output(System.out); return e; } // private Vector<Element> getFullKeyLogElementsWithoutLocalProofAndDataPath() { // Vector<Element> ea = new Vector<Element>(); // ea.add(new Element("date", getDateString())); // ea.add(new Element("ipv4", ipv4)); // ea.add(new Element("ipv6", ipv6)); // ea.add(toKeyLogActionElement()); // return ea; // } // // private Vector<Element> getKeyLogActionElementsWithoutLocalProof() { // Vector<Element> ea = new Vector<Element>(); // ea.add(new Element("from_keyid",fromKeyid)); // ea.add(new Element("to_keyid",toKeyid)); // Element eAction = new Element(action); // if (message!=null) { // eAction.addContent("message",message); // } // if (id!=null) { // for (Element eIDContent : id.getContentElements(true)) { // eAction.addContent(eIDContent); // } // } // ea.add(eAction); // return ea; // } public long getSignDatetime() { return signature.getSignDatetime(); } public long getActionDatetime() { return action.getSignDatetime(); } public String getActionDatetimeString() { return SecurityHelper.getFormattedDate(action.getSignDatetime()); } public String getKeyIDFrom() { return action.getKeyIDFrom(); } public String getKeyIDTo() { return action.getKeyIDTo(); } public String getIPv4() { return ipv4; } public String getIPv6() { return ipv6; } public String getAction() { return action.getAction(); } public byte[] getActionSha256ProofComplete() { return action.getSha256localproof_complete(); } public byte[] getActionSha256ProofRestricted() { return action.getSha256localproof_restricted(); } public Signature getActionSignature() { return action.getSignature(); } public Signature getSignature() { return signature; } public byte[] getSHA256LocalProof() { return sha256localproof; } public void addDataPath(DataSourceStep step) { datapath.add(step); } public Vector<DataSourceStep> getDataPath() { return datapath; } public Identity getIdentity() { return action.getIdentity(); } public String getMessage() { return action.getMessage(); } public OSDXKey getActionSignatureKey() { return action.getSignatureKey(); } public boolean hasRestrictedFields() { return action.hasRestrictedFields(); } } //<keylog> // <date>2011-04-28 13:54:14 GMT+00:00</date> // <ipv4>127.0.0.1</ipv4> // <ipv6>127.0.0.1</ipv6> // <keylogaction> // <from_keyid>55:32:7D:CD:4E:37:D1:88:EB:02:B9:B9:5A:9F:8A:CF:45:2D:44:D3@localhost</from_keyid> // <to_keyid>D9:1C:42:50:94:E3:BF:B1:2E:86:91:07:D8:54:95:CB:C5:8F:07:71@localhost</to_keyid> // <approval> // <identity> // <identnum>0001</identnum> // <email>debug_key_0@it-is-awesome.de</email> // <sha1>BC:3A:6D:C7:F5:69:E1:39:A6:BC:6B:A5:96:A6:08:F7:E0:6F:3F:32</sha1> // </identity> // </approval> // <sha1localproof>DB:B5:D0:B4:00:26:07:83:21:1E:3A:B9:DD:E4:DA:84:4A:20:C4:61</sha1localproof> // <signature> // [of from_key] // </signature> // </keylogaction> // <sha1localproof>A2:C4:B6:96:5B:19:C6:99:D5:FD:05:72:5D:DB:B6:00:02:E0:42:AB</sha1localproof> // <signature> // [of keyserver] // </signature> // <datapath /> //</keylog>