// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.plugins.trustosm.util; import static org.openstreetmap.josm.tools.I18n.tr; import java.awt.Component; import java.awt.Dimension; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Provider; import java.security.SecureRandom; import java.security.Security; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Random; import java.util.Vector; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFormattedTextField; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPasswordField; import javax.swing.JTextField; import javax.swing.SpringLayout; import org.bouncycastle.bcpg.HashAlgorithmTags; import org.bouncycastle.bcpg.sig.NotationData; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openpgp.PGPEncryptedData; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPKeyPair; import org.bouncycastle.openpgp.PGPKeyRingGenerator; import org.bouncycastle.openpgp.PGPPrivateKey; import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; import org.bouncycastle.openpgp.PGPSecretKey; import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.bouncycastle.openpgp.PGPSignature; import org.bouncycastle.openpgp.PGPSignatureGenerator; import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator; import org.bouncycastle.openpgp.PGPSignatureSubpacketVector; import org.bouncycastle.openpgp.PGPUtil; import org.bouncycastle.openpgp.bc.BcPGPPublicKeyRingCollection; import org.bouncycastle.openpgp.bc.BcPGPSecretKeyRingCollection; import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor; import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor; import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder; import org.bouncycastle.openpgp.operator.PGPContentVerifierBuilderProvider; import org.bouncycastle.openpgp.operator.PGPDigestCalculator; import org.bouncycastle.openpgp.operator.PGPDigestCalculatorProvider; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair; import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder; import org.bouncycastle.util.encoders.Hex; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.data.osm.Node; import org.openstreetmap.josm.data.osm.OsmPrimitive; import org.openstreetmap.josm.data.osm.Way; import org.openstreetmap.josm.plugins.trustosm.data.TrustNode; import org.openstreetmap.josm.plugins.trustosm.data.TrustOsmPrimitive; import org.openstreetmap.josm.plugins.trustosm.data.TrustWay; import org.openstreetmap.josm.tools.GBC; import org.openstreetmap.josm.tools.ImageProvider; import com.toedter.calendar.JDateChooser; import com.toedter.calendar.JSpinnerDateEditor; public class TrustGPG { // private GnuPG gpg; private char[] password; private PGPSecretKeyRingCollection pgpSec; private PGPPublicKeyRingCollection pgpPub; private static int digest = PGPUtil.SHA1; private PGPSecretKey pgpSecKey; public boolean keepkey = false; public static final String NOTATION_DATA_KEY = "trustosm@openstreetmap.org"; public TrustGPG() { Security.addProvider(new BouncyCastleProvider()); try { readGpgFiles(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public PGPPublicKey getPublicKeyFromRing(long keyID) { try { if (pgpPub.contains(keyID)) return pgpPub.getPublicKey(keyID); else if (pgpSec.contains(keyID)) return pgpSec.getSecretKey(keyID).getPublicKey(); } catch (PGPException e) { System.err.println("Could not read a PGPPublic key from your KeyRingCollectionFile. Stacktrace:"); e.printStackTrace(); } return null; } public static String secKeytoString(PGPSecretKey k) { String keyText = "0x"+Long.toHexString(k.getKeyID()).substring(8).toUpperCase() + " "; // keyText = new String(Hex.encode(sigKey.getPublicKey().getFingerprint()),"UTF-8") + " "; Iterator<?> iter = k.getUserIDs(); if (iter.hasNext()) { keyText += (String) iter.next(); } /* iter = sigKey.getUserIDs(); while (iter.hasNext()) { keyText += (String)iter.next() + "; "; } */ return keyText.trim(); } private void readSecretKey() { // if there is no KeyRingCollection we have to create a new one if (pgpSec == null) { try { generateKey(); } catch (Exception e) { Main.error(e); Main.error("GPG Key Ring File could not be created in: "+ Main.pref.getPluginsDirectory().getPath() + "/trustosm/gnupg/secring.gpg"); } } // // we just loop through the collection till we find a key suitable for encryption, in the real // world you would probably want to be a bit smarter about this. // if (keepkey) return; final ArrayList<PGPSecretKey> sigKeys = new ArrayList<>(); // // iterate through the key rings. // Iterator<?> rIt = pgpSec.getKeyRings(); while (rIt.hasNext()) { PGPSecretKeyRing kRing = (PGPSecretKeyRing) rIt.next(); Iterator<?> kIt = kRing.getSecretKeys(); while (kIt.hasNext()) { PGPSecretKey k = (PGPSecretKey) kIt.next(); if (k.isSigningKey()) { sigKeys.add(k); } } } Iterator<PGPSecretKey> skIt = sigKeys.iterator(); final Vector<String> keys = new Vector<>(); while (skIt.hasNext()) { PGPSecretKey sigKey = skIt.next(); keys.add(secKeytoString(sigKey)); } JPanel p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS)); Dimension d = new Dimension(0, 20); JLabel head = new JLabel(tr("Select a signing key from your keyring-file:")); head.setAlignmentX(Component.LEFT_ALIGNMENT); p.add(head); final JComboBox<String> keyBox = new JComboBox<>(keys); keyBox.setAlignmentX(Component.LEFT_ALIGNMENT); p.add(keyBox); JCheckBox keepkeyBox = new JCheckBox(tr("Don''t ask again for the key")); keepkeyBox.setAlignmentX(Component.LEFT_ALIGNMENT); p.add(keepkeyBox); JButton detailsButton = new JButton(tr("Details"), ImageProvider.get("keydetails")); detailsButton.setAlignmentX(Component.LEFT_ALIGNMENT); detailsButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { PGPSecretKey sk = sigKeys.get(keyBox.getSelectedIndex()); showKeyDetails(getPublicKeyFromRing(sk.getKeyID())); } }); p.add(detailsButton); JCheckBox random = new JCheckBox(tr("Use a random key from this list")); random.setAlignmentX(Component.LEFT_ALIGNMENT); p.add(random); p.add(Box.createRigidArea(d)); JButton createButton = new JButton(tr("Create new Key"), ImageProvider.get("key")); createButton.setAlignmentX(Component.LEFT_ALIGNMENT); createButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { try { PGPSecretKey secKey = generateKey(); if (secKey != null) { keyBox.addItem(secKeytoString(secKey)); sigKeys.add(secKey); } } catch (NoSuchAlgorithmException | NoSuchProviderException | PGPException | IOException e) { Main.error(e); } } }); p.add(createButton); p.add(Box.createRigidArea(d)); int n = JOptionPane.showOptionDialog(Main.parent, p, tr("Select a Key to sign"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, ImageProvider.get("keyring"), null, null); if (n == JOptionPane.OK_OPTION) { keepkey = keepkeyBox.isSelected(); if (random.isSelected()) { Random r = new Random(); pgpSecKey = sigKeys.get(r.nextInt(sigKeys.size()-1)); } else { pgpSecKey = sigKeys.get(keyBox.getSelectedIndex()); } } else { pgpSecKey = null; } } public void readGpgFiles() throws PGPException, IOException, NoSuchAlgorithmException, NoSuchProviderException { FileInputStream pubIn; FileInputStream secIn; try { pubIn = new FileInputStream(Main.pref.getPluginsDirectory().getPath() + "/trustosm/gnupg/secring.gpg"); secIn = new FileInputStream(Main.pref.getPluginsDirectory().getPath() + "/trustosm/gnupg/pubring.gpg"); //pubIn = new FileInputStream("/tmp/secring.gpg"); //secIn = new FileInputStream("/tmp/pubring.gpg"); pgpSec = new BcPGPSecretKeyRingCollection(PGPUtil.getDecoderStream(pubIn)); pgpPub = new BcPGPPublicKeyRingCollection(PGPUtil.getDecoderStream(secIn)); } catch (FileNotFoundException e) { System.err.println("No gpg files found in "+Main.pref.getPluginsDirectory().getPath() + "/trustosm/gnupg/secring.gpg"); pgpSec = null; pgpPub = null; } } public void writeGpgFiles() throws FileNotFoundException, IOException { String path = Main.pref.getPluginsDirectory().getPath(); try (FileOutputStream pubOut = new FileOutputStream(path + "/trustosm/gnupg/pubring.gpg"); FileOutputStream secOut = new FileOutputStream(path + "/trustosm/gnupg/secring.gpg")) { pgpSec.encode(secOut); pgpPub.encode(pubOut); pubOut.flush(); secOut.flush(); } } public void getPasswordfromUser() { final JPasswordField passwordField = new JPasswordField(); JOptionPane jop = new JOptionPane(passwordField, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION, ImageProvider.get("lock")); JDialog dialog = jop.createDialog("Password:"); dialog.addComponentListener(new ComponentAdapter() { @Override public void componentShown(ComponentEvent e) { passwordField.requestFocusInWindow(); } }); dialog.setVisible(true); int result = (Integer) jop.getValue(); dialog.dispose(); if (result == JOptionPane.OK_OPTION) { password = passwordField.getPassword(); } /*final JPasswordField passwordField = new JPasswordField(10); JOptionPane.showMessageDialog(Main.parent, passwordField, "Enter password", JOptionPane.OK_OPTION, ImageProvider.get("lock")); password = passwordField.getPassword(); */ } /* public void checkTag(TrustOsmPrimitive trust, String key) { String sigtext = TrustOsmPrimitive.generateTagSigtext(trust.getOsmPrimitive(),key); TrustSignatures sigs; if ((sigs = trust.getSigsOnKey(key))!=null) for (PGPSignature sig : sigs.getSignatures()) { trust.updateTagSigStatus(key, verify(sigtext,sig)? TrustSignatures.SIG_VALID : TrustSignatures.SIG_BROKEN); } } /* public void checkAll(TrustOsmPrimitive trust) { OsmPrimitive osm = trust.getOsmPrimitive(); for (String key : osm.keySet()) { checkTag(trust, key); } if (osm instanceof Node) { checkNode((TrustNode) trust); } else if (osm instanceof Way) { /* Iterator<Node> iter = ((Way)osm).getNodes().iterator(); while (iter.hasNext()) { checkNode(trust, iter.next()); }/ } else if (osm instanceof Relation) { } } */ public void invalidIDWarning(OsmPrimitive osm) { // CHECKSTYLE.OFF: LineLength JOptionPane.showMessageDialog(Main.parent, tr("The object with the ID \"{0}\" ({1}) is newly created.\nYou can not sign it, because the signature would lose the ID-Reference after uploading it to the OSM-server.", osm.getUniqueId(), osm.toString()), tr("Signing canceled!"), JOptionPane.ERROR_MESSAGE); // CHECKSTYLE.ON: LineLength } /* public TrustOsmPrimitive signGeometry(TrustOsmPrimitive trust) { PGPSignatureSubpacketGenerator spGen = chooseAccuracy(); PGPSignature s; Node node; OsmPrimitive osm = trust.getOsmPrimitive(); if (osm.isNew()) { invalidIDWarning(osm); return trust; } if (osm instanceof Node) { s = signNode(osm,(Node)osm, spGen); if (s != null) ((TrustNode)trust).storeNodeSig(s); } else if (osm instanceof Way) { Iterator<Node> iter = ((Way)osm).getNodes().iterator(); while (iter.hasNext()) { node = iter.next(); s = signNode(osm,node,spGen); if (s != null) ((TrustNode)trust).storeNodeSig(s); } } else if (osm instanceof Relation) { } return trust; }*/ public TrustWay signWay(TrustWay trust) { PGPSignature s; Way w = (Way) trust.getOsmPrimitive(); if (w.isNew()) { invalidIDWarning(w); return trust; } /* List<Node> nodes = w.getNodes(); s = signSegment(trust,nodes); if (s != null) trust.storeSegmentSig(nodes,s); */ List<Node> wayNodes = w.getNodes(); for (int i = 0; i < wayNodes.size()-1; i++) { List<Node> nodes = new ArrayList<>(); nodes.add(wayNodes.get(i)); nodes.add(wayNodes.get(i+1)); s = signSegment(trust, nodes); if (s != null) trust.storeSegmentSig(nodes, s); } return trust; } public PGPSignature signSegment(TrustWay trust, List<Node> nodes) { Way w = (Way) trust.getOsmPrimitive(); if (w.isNew()) { invalidIDWarning(w); return null; } String tosign = TrustWay.generateSegmentSigtext(trust, nodes); PGPSignatureSubpacketGenerator spGen = chooseAccuracy(); return sign(tosign, spGen); } public PGPSignature signNode(Node node) { PGPSignatureSubpacketGenerator spGen = chooseAccuracy(); return signNode(node, spGen); } public PGPSignature signNode(Node node, PGPSignatureSubpacketGenerator spGen) { if (node.isNew()) { invalidIDWarning(node); return null; } String tosign = TrustNode.generateNodeSigtext(node); return sign(tosign, spGen); } public boolean signTag(TrustOsmPrimitive trust, String key) { OsmPrimitive osm = trust.getOsmPrimitive(); if (osm.isNew()) { invalidIDWarning(osm); return false; } PGPSignature s; String tosign = TrustOsmPrimitive.generateTagSigtext(osm, key); s = sign(tosign, chooseInformationSource()); if (s != null) { trust.storeTagSig(key, s); return true; } return false; } /** * Search in a given Signature for Tolerance information. * @return found tolerance as double or 0 if no Tolerance is given */ public static double searchTolerance(PGPSignature sig) { /** Take the first NotationData packet that seems to have Tolerance information */ for (NotationData nd : sig.getHashedSubPackets().getNotationDataOccurrences()) { if (nd.getNotationName().equals(TrustGPG.NOTATION_DATA_KEY)) { String notation = nd.getNotationValue(); Pattern p = Pattern.compile("^Tolerance:(\\d*\\.?\\d*)m"); Matcher m = p.matcher(notation); if (m.matches()) { // we found a valid Tolerance return Double.parseDouble(m.group(1)); } } } return 0; } public PGPSignatureSubpacketGenerator chooseAccuracy() { PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); JPanel p = new JPanel(new GridBagLayout()); p.add(new JLabel(tr("Please give a tolerance in meters")), GBC.eol()); JFormattedTextField meters = new JFormattedTextField(NumberFormat.getNumberInstance()); meters.setValue(Double.valueOf(10)); meters.setColumns(5); p.add(meters, GBC.std()); p.add(new JLabel(tr("meters")), GBC.eol()); int n = JOptionPane.showOptionDialog(Main.parent, p, tr("Accuracy"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null); if (n == JOptionPane.OK_OPTION) { spGen.setNotationData(false, true, TrustGPG.NOTATION_DATA_KEY, "Tolerance:"+meters.getValue()+"m"); return spGen; } return null; } public PGPSignatureSubpacketGenerator chooseInformationSource() { PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); JPanel p = new JPanel(new GridBagLayout()); p.add(new JLabel(tr("Select as much as you like:")), GBC.eol()); JCheckBox survey = new JCheckBox(tr("Survey")); p.add(survey, GBC.eol()); JCheckBox aerial = new JCheckBox(tr("Aerial Photography")); p.add(aerial, GBC.eol()); JCheckBox web = new JCheckBox(tr("Web Recherche")); p.add(web, GBC.eol()); JCheckBox trusted = new JCheckBox(tr("Trusted persons told me")); p.add(trusted, GBC.eol()); int n = JOptionPane.showOptionDialog(Main.parent, p, tr("Which source did you use?"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null); if (n == JOptionPane.OK_OPTION) { String sources = "Sources:"; if (survey.isSelected()) sources += ":survey"; if (aerial.isSelected()) sources += ":aerial"; if (web.isSelected()) sources += ":web"; if (trusted.isSelected()) sources += ":trusted"; spGen.setNotationData(false, true, TrustGPG.NOTATION_DATA_KEY, sources); return spGen; } return null; } public PGPSignature sign(String tosign) { PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); return sign(tosign, spGen); } public PGPSignature sign(String tosign, PGPSignatureSubpacketGenerator spGen) { if (spGen == null) return null; PGPSignature sig; try { readSecretKey(); if (pgpSec == null) return null; if (password == null) { getPasswordfromUser(); } Provider provider = Security.getProvider("BC"); PGPDigestCalculatorProvider digestCalculatorProvider = new JcaPGPDigestCalculatorProviderBuilder().setProvider(provider).build(); PBESecretKeyDecryptor secretKeyDecryptor = new JcePBESecretKeyDecryptorBuilder(digestCalculatorProvider) .setProvider(provider).build(password); PGPPrivateKey pgpPrivKey = pgpSecKey.extractPrivateKey(secretKeyDecryptor); int keyAlgorithm = pgpSecKey.getPublicKey().getAlgorithm(); PGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(keyAlgorithm, digest) .setProvider(provider).setDigestProvider(provider); PGPSignatureGenerator sGen = new PGPSignatureGenerator(contentSignerBuilder); sGen.init(PGPSignature.CANONICAL_TEXT_DOCUMENT, pgpPrivKey); Iterator<?> it = pgpSecKey.getPublicKey().getUserIDs(); if (it.hasNext()) { spGen.setSignerUserID(false, (String) it.next()); } sGen.setHashedSubpackets(spGen.generate()); sGen.update(tosign.getBytes(Charset.forName("UTF-8"))); sig = sGen.generate(); //System.out.println(new String(sGen.generateOnePassVersion(false).getEncoded(),Charset.forName("UTF-8"))); //writeSignatureToFile(sig, tosign, new FileOutputStream("/tmp/sigtest.asc")); //sig.encode(new BCPGOutputStream(new ArmoredOutputStream(new FileOutputStream("/tmp/sigtest.asc")))); return sig; } catch (Exception e) { System.err.println("PGP Signing Error: " + e.getMessage()); } /* String seckeys = gpg.listSecretKeys()? gpg.getResult() : "GPG-ERROR: " + gpg.getErrorString(); System.out.println("Die gelisteten keys sehen so aus:\n"+seckeys); String[] keys = seckeys.split("\n"); System.out.println("Das Array hat so viele einträge:"+keys.length); if (keys.length <= 1) { System.out.println("Auf auf zum lustigen generieren!"); generateKey(); } System.out.println("Achtung die Errorausgabe sieht so aus:\n"+gpg.getErrorString()); String sig = gpg.sign(tosign, password)? gpg.getResult() : "GPG-ERROR: " + gpg.getErrorString(); */ return null; } public boolean verify(String sigtext, PGPSignature sig) { /* if (gpg.verifySignature(sig)) { success = trust.updateSigStatus(key, gpg.getResult().equals(sigtext)? TrustSignatures.SIG_VALID : TrustSignatures.SIG_BROKEN); }*/ try { Provider provider = Security.getProvider("BC"); PGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider().setProvider(provider); sig.init(contentVerifierBuilderProvider, pgpPub.getPublicKey(sig.getKeyID())); sig.update(sigtext.getBytes(Charset.forName("UTF-8"))); return sig.verify(); } catch (Exception e) { System.err.println("PGP Verification Error: " + e.getMessage()); } return false; } // public static void writeSignatureToFile(PGPSignature sig, String clearText, FileOutputStream fout) throws Exception { // ArmoredOutputStream aOut = new ArmoredOutputStream(fout); // aOut.beginClearText(digest); // aOut.write(clearText.getBytes(Charset.forName("UTF-8"))); // aOut.write('\n'); // aOut.endClearText(); // // BCPGOutputStream bOut = new BCPGOutputStream(aOut); // sig.encode(bOut); // aOut.close(); // bOut.close(); // } // // public Map<String, String> getKeyValueFromSignature(PGPSignature sig) { // Map<String, String> tags = new HashMap<String, String>(); // try { // String sigtext = new String(sig.getEncoded(), Charset.forName("UTF-8")); // String[] kv = TrustOsmPrimitive.generateTagsFromSigtext(sigtext); // tags.put(kv[0],kv[1]); // } catch (IOException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // return tags; // } public static void showKeyDetails(PGPPublicKey key) { String userid = "Unknown"; Iterator<?> iter = key.getUserIDs(); if (iter.hasNext()) { userid = (String) iter.next(); } String fingerprint = new String(Hex.encode(key.getFingerprint()), StandardCharsets.UTF_8).toUpperCase(Locale.ENGLISH); String keyid = "0x"+Long.toHexString(key.getKeyID()).substring(8).toUpperCase(Locale.ENGLISH); String algorithm = ""; int algo = key.getAlgorithm(); switch(algo) { case PGPPublicKey.DIFFIE_HELLMAN: algorithm = "Diffie Hellman (DH)"; break; case PGPPublicKey.DSA: algorithm = "Digital Signature Algorithm (DSA)"; break; case PGPPublicKey.EC: algorithm = "Elliptic Curve (EC)"; break; case PGPPublicKey.ECDSA: algorithm = "Elliptic Curve Digital Signature Algorithm (ECDSA)"; break; case PGPPublicKey.ELGAMAL_ENCRYPT: algorithm = "Elgamal encrypt-only"; break; case PGPPublicKey.ELGAMAL_GENERAL: algorithm = "Elgamal"; break; case PGPPublicKey.RSA_ENCRYPT: algorithm = "Rivest Shamir Adleman (RSA) encrypt-only"; break; case PGPPublicKey.RSA_GENERAL: algorithm = "Rivest Shamir Adleman (RSA)"; break; case PGPPublicKey.RSA_SIGN: algorithm = "Rivest Shamir Adleman (RSA) sign-only"; break; default: algorithm = "Unknown algorithm ID: "+algo; break; } String strength = String.valueOf(key.getBitStrength()); //SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd:hh.mm.ss"); SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); String creationTime = formatter.format(key.getCreationTime()); long validSeconds = key.getValidSeconds(); String expirationTime; if (validSeconds == 0) { expirationTime = tr("never"); } else { expirationTime = formatter.format(new Date(key.getCreationTime().getTime()+validSeconds*1000)); } String[] labels = {tr("Primary user-ID: "), tr("Key-ID: "), tr("Fingerprint: "), tr("Algorithm: "), tr("Strength in bit: "), tr("Creation date: "), tr("Expiration date: ")}; String[] values = {userid, keyid, fingerprint, algorithm, strength, creationTime, expirationTime}; int numPairs = labels.length; //Create and populate the panel. JPanel p = new JPanel(new SpringLayout()); for (int i = 0; i < numPairs; i++) { JLabel l = new JLabel(labels[i], JLabel.TRAILING); p.add(l); JTextField textField = new JTextField(values[i]); textField.setEditable(false); l.setLabelFor(textField); p.add(textField); } //Lay out the panel. SpringUtilities.makeCompactGrid(p, numPairs, 2, //rows, cols 6, 6, //initX, initY 6, 6); //xPad, yPad // JPanel metaPanel = new JPanel(); // metaPanel.setLayout(new BoxLayout(metaPanel, BoxLayout.PAGE_AXIS)); // metaPanel.add(p); // JScrollPane sp = new JScrollPane(new KeySignaturesDialog(key)); // sp.setPreferredSize(new Dimension(0, 200)); // metaPanel.add(sp); JOptionPane.showMessageDialog(Main.parent, p, tr("PGP-Key details"), JOptionPane.INFORMATION_MESSAGE); } public PGPSecretKey generateKey() throws NoSuchAlgorithmException, NoSuchProviderException, PGPException, FileNotFoundException, IOException { JTextField userId = new JTextField(); NameGenerator nameGen = new NameGenerator(Main.pref.getPluginsDirectory().getPath()+"/trustosm/resources/syllables.txt"); userId.setText(nameGen.compose(3)); final String[] sizes = {"1024", "2048", "3072", "4096"}; final JComboBox<?> strengthBox = new JComboBox<Object>(sizes); strengthBox.setEnabled(false); /* final String[] curves = {"prime192v1", "prime192v2", "prime192v3", "prime239v1", "prime239v2", "prime239v3", "prime256v1", "secp224r1", "secp256r1", "secp384r1", "secp521r1", "P-224", "P-256", "P-384", "P-521", "c2pnb163v1", "c2pnb163v2", "c2pnb163v3", "c2pnb176w1", "c2tnb191v2", "c2tnb191v1", "c2tnb191v3", "c2pnb208w1", "c2tnb239v1", "c2tnb239v2", "c2tnb239v3", "c2pnb272w1", "c2pnb304w1", "c2tnb359v1", "c2pnb368w1", "c2tnb431r1", "sect163r2", "sect233r1", "sect283r1", "sect409r1", "sect571r1", "B-163", "B-233", "B-283", "B-409", "B-571", "brainpoolp160r1", "brainpoolp160t1", "brainpoolp192r1", "brainpoolp192t1", "brainpoolp224r1", "brainpoolp224t1", "brainpoolp256r1", "brainpoolp256t1", "brainpoolp320r1", "brainpoolp320t1", "brainpoolp384r1", "brainpoolp384t1", "brainpoolp512r1", "brainpoolp512t1"}; final String[] curvesizes = {"192", "192", "192", "239", "239", "239", "256", "224", "256", "384", "521", "224", "256", "384", "521", "163", "163", "163", "176", "191", "191", "191", "208", "239", "239", "239", "272", "304", "359", "368", "431", "163", "233", "283", "409", "571", "163", "233", "283", "409", "571", "160", "160", "192", "192", "224", "224", "256", "256", "320", "320", "384", "384", "512", "512"}; final JComboBox curveBox = new JComboBox(curves); curveBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { strengthBox.setSelectedIndex(((JComboBox)e.getSource()).getSelectedIndex()); }}); curveBox.setEnabled(false); */ // final String[] algos = {"DSA","RSA","ECDSA"}; final String[] algos = {"DSA", "RSA"}; final JComboBox<?> algoBox = new JComboBox<Object>(algos); algoBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JComboBox<?> cb = (JComboBox<?>) e.getSource(); String alg = (String) cb.getSelectedItem(); if (alg.equals("DSA")) { strengthBox.setSelectedItem("1024"); strengthBox.setEnabled(false); } else strengthBox.setEnabled(true); /*if (alg.equals("ECDSA")) { curveBox.setEnabled(true); strengthBox.setModel(new DefaultComboBoxModel(curvesizes)); strengthBox.setSelectedItem(curvesizes[curveBox.getSelectedIndex()]); strengthBox.setEnabled(false); } else { curveBox.setEnabled(false); strengthBox.setModel(new DefaultComboBoxModel(sizes)); strengthBox.setEnabled(true); }*/ } }); final String[] protectAlgos = {"AES_256", "AES_192", "AES_128", "BLOWFISH", "CAST5", "DES", "IDEA", "SAFER", "TRIPLE_DES", "TWOFISH", "NULL"}; int[] protAl = {PGPEncryptedData.AES_256, PGPEncryptedData.AES_192, PGPEncryptedData.AES_128, PGPEncryptedData.BLOWFISH, PGPEncryptedData.CAST5, PGPEncryptedData.DES, PGPEncryptedData.IDEA, PGPEncryptedData.SAFER, PGPEncryptedData.TRIPLE_DES, PGPEncryptedData.TWOFISH, PGPEncryptedData.NULL}; final JComboBox<?> protectBox = new JComboBox<Object>(protectAlgos); final JDateChooser cal = new JDateChooser(null, null, null, new JSpinnerDateEditor()); cal.setPreferredSize(new Dimension(130, cal.getPreferredSize().height)); final String[] labels = {tr("User-ID:"), tr("Select algorithm:"), tr("Choose Bitlength (Strength):"), tr("Encryption algorithm to protect private key:"), tr("Choose an expiry date for the key:")}; final JComponent[] values = {userId, algoBox, strengthBox, protectBox, cal}; int numPairs = labels.length; //Create and populate the panel. JPanel p = new JPanel(new SpringLayout()); for (int i = 0; i < numPairs; i++) { JLabel l = new JLabel(labels[i], JLabel.TRAILING); p.add(l); l.setLabelFor(values[i]); p.add(values[i]); } //Lay out the panel. SpringUtilities.makeCompactGrid(p, numPairs, 2, //rows, cols 6, 6, //initX, initY 16, 6); //xPad, yPad int n = JOptionPane.showOptionDialog(Main.parent, p, tr("Create a new signing key"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null); if (n != JOptionPane.OK_OPTION) return null; String algo = (String) algoBox.getSelectedItem(); KeyPairGenerator Kpg = KeyPairGenerator.getInstance(algo, "BC"); int al; /* if (algo.equals("ECDSA")) { al = PGPPublicKey.ECDSA; ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec((String)curveBox.getSelectedItem()); try { Kpg.initialize(ecSpec); } catch (InvalidAlgorithmParameterException e1) { // TODO Auto-generated catch block System.err.println("EC-Parameter not accepted"); e1.printStackTrace(); } } else {*/ Kpg.initialize(Integer.parseInt((String) strengthBox.getSelectedItem())); // // this takes a while as the key generator has to generate some DSA params // before it generates the key. // if (algo.equals("RSA")) al = PGPPublicKey.RSA_GENERAL; else al = PGPPublicKey.DSA; // } KeyPair kp = Kpg.generateKeyPair(); Date now = new Date(); PGPKeyPair pgpKp = new JcaPGPKeyPair(al, kp, now); getPasswordfromUser(); PGPSignatureSubpacketVector subPck = null; PGPSignatureSubpacketGenerator spGen = null; Date expire = cal.getDate(); if (expire != null && expire.after(now)) { spGen = new PGPSignatureSubpacketGenerator(); spGen.setKeyExpirationTime(true, (expire.getTime()-now.getTime())/1000); subPck = spGen.generate(); } Provider provider = Security.getProvider("BC"); int encAlgorithm = protAl[protectBox.getSelectedIndex()]; PGPDigestCalculator checksumCalculator = new JcaPGPDigestCalculatorProviderBuilder().build().get(HashAlgorithmTags.SHA1); PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(pgpKp.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1); PBESecretKeyEncryptor encryptor = new JcePBESecretKeyEncryptorBuilder(encAlgorithm).setProvider(provider). setSecureRandom(new SecureRandom()).build(password); PGPKeyRingGenerator keyRingGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, pgpKp, userId.getText(), checksumCalculator, subPck, null, signerBuilder, encryptor); if (pgpPub == null) { Vector<PGPPublicKeyRing> pubKeyRing = new Vector<>(1); pubKeyRing.add(keyRingGen.generatePublicKeyRing()); pgpPub = new PGPPublicKeyRingCollection(pubKeyRing); } else { pgpPub = PGPPublicKeyRingCollection.addPublicKeyRing(pgpPub, keyRingGen.generatePublicKeyRing()); } PGPSecretKeyRing secRing = keyRingGen.generateSecretKeyRing(); if (pgpSec == null) { Vector<PGPSecretKeyRing> secKeyRing = new Vector<>(1); secKeyRing.add(secRing); pgpSec = new PGPSecretKeyRingCollection(secKeyRing); } else { pgpSec = PGPSecretKeyRingCollection.addSecretKeyRing(pgpSec, secRing); } writeGpgFiles(); return secRing.getSecretKey(); } }