diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpContact.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpContact.java index 013bf2f96..60210777b 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpContact.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpContact.java @@ -31,7 +31,6 @@ import org.jivesoftware.smack.util.stringencoder.Base64; import org.jivesoftware.smackx.ox.element.PubkeyElement; import org.jivesoftware.smackx.ox.element.PublicKeysListElement; import org.jivesoftware.smackx.ox.exception.MissingUserIdOnKeyException; -import org.jivesoftware.smackx.ox.selection_strategy.AnnouncedKeys; import org.jivesoftware.smackx.ox.selection_strategy.BareJidUserId; import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore; import org.jivesoftware.smackx.ox.util.PubSubDelegate; @@ -43,6 +42,7 @@ import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator; import org.jxmpp.jid.BareJid; import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint; +import org.pgpainless.pgpainless.util.BCUtil; public class OpenPgpContact { @@ -69,26 +69,29 @@ public class OpenPgpContact { PGPPublicKeyRingCollection anyKeys = getAnyPublicKeys(); Map announced = store.getAnnouncedFingerprintsOf(jid); - PGPPublicKeyRingCollection announcedKeysCollection = anyKeys; - BareJidUserId.PubRingSelectionStrategy userIdFilter = new BareJidUserId.PubRingSelectionStrategy(); - AnnouncedKeys.PubKeyRingSelectionStrategy announcedFilter = new AnnouncedKeys.PubKeyRingSelectionStrategy(); - for (PGPPublicKeyRing ring : (anyKeys != null ? anyKeys : Collections.emptyList())) { + PGPPublicKeyRingCollection announcedKeysCollection = null; + for (OpenPgpV4Fingerprint announcedFingerprint : announced.keySet()) { + PGPPublicKeyRing ring = anyKeys.getPublicKeyRing(announcedFingerprint.getKeyId()); + + if (ring == null) continue; + + ring = BCUtil.removeUnassociatedKeysFromKeyRing(ring, ring.getPublicKey(announcedFingerprint.getKeyId())); if (!userIdFilter.accept(getJid(), ring)) { LOGGER.log(Level.WARNING, "Ignore key " + Long.toHexString(ring.getPublicKey().getKeyID()) + " as it lacks the user-id \"xmpp" + getJid().toString() + "\""); - announcedKeysCollection = PGPPublicKeyRingCollection.removePublicKeyRing(announcedKeysCollection, ring); continue; } - if (!announcedFilter.accept(announced, ring)) { - LOGGER.log(Level.WARNING, "Ignore key " + Long.toHexString(ring.getPublicKey().getKeyID()) + - " as it is not announced by " + getJid().toString()); - announcedKeysCollection = PGPPublicKeyRingCollection.removePublicKeyRing(announcedKeysCollection, ring); + if (announcedKeysCollection == null) { + announcedKeysCollection = new PGPPublicKeyRingCollection(Collections.singleton(ring)); + } else { + announcedKeysCollection = PGPPublicKeyRingCollection.addPublicKeyRing(announcedKeysCollection, ring); } } + return announcedKeysCollection; } diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java index faccd3d65..3aac95fe8 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java @@ -21,7 +21,6 @@ import static org.jivesoftware.smackx.ox.util.PubSubDelegate.PEP_NODE_PUBLIC_KEY import static org.jivesoftware.smackx.ox.util.PubSubDelegate.publishPublicKey; import java.io.IOException; -import java.io.InputStream; import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; @@ -79,12 +78,10 @@ import org.jivesoftware.smackx.pubsub.PubSubFeature; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPublicKeyRing; -import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.jxmpp.jid.BareJid; import org.jxmpp.jid.EntityBareJid; -import org.pgpainless.pgpainless.PGPainless; import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint; import org.xmlpull.v1.XmlPullParserException; @@ -412,18 +409,41 @@ public final class OpenPgpManager extends Manager { }; private void processPublicKeysListElement(BareJid contact, PublicKeysListElement listElement) { - + OpenPgpContact openPgpContact = getOpenPgpContact(contact.asEntityBareJidIfPossible()); + // TODO: Quick and dirty. Do it properly!!! try { - PGPPublicKeyRingCollection contactsKeys = provider.getStore().getPublicKeysOf(contact); + openPgpContact.updateKeys(connection()); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Could not update contacts keys", e); + } + /* + try { + PGPPublicKeyRingCollection contactsKeys = openPgpContact.getAnyPublicKeys(); for (OpenPgpV4Fingerprint fingerprint : listElement.getMetadata().keySet()) { PGPPublicKeyRing key = contactsKeys.getPublicKeyRing(fingerprint.getKeyId()); if (key == null) { + try { + PubkeyElement pubkeyElement = PubSubDelegate.fetchPubkey(connection(), contact, fingerprint); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (XMPPException.XMPPErrorException e) { + e.printStackTrace(); + } catch (PubSubException.NotAPubSubNodeException e) { + e.printStackTrace(); + } catch (PubSubException.NotALeafNodeException e) { + e.printStackTrace(); + } catch (SmackException.NotConnectedException e) { + e.printStackTrace(); + } catch (SmackException.NoResponseException e) { + e.printStackTrace(); + } } } } catch (PGPException | IOException e) { LOGGER.log(Level.WARNING, "Could not read public keys of " + contact, e); } + */ } private final IncomingChatMessageListener incomingOpenPgpMessageListener = @@ -478,22 +498,6 @@ public final class OpenPgpManager extends Manager { Private stuff. */ - /** - * Process a {@link PubkeyElement}. This includes unpacking the key from the element and importing it. - * - * @param pubkeyElement {@link PubkeyElement} containing the key - * @param owner owner of the key - * @throws MissingUserIdOnKeyException if the key does not have an OpenPGP user-id of the form - * "xmpp:juliet@capulet.lit" with the owners {@link BareJid} - * @throws IOException row, row, row your byte gently down the {@link InputStream} - */ - private void processPublicKey(PubkeyElement pubkeyElement, BareJid owner) - throws MissingUserIdOnKeyException, IOException, PGPException { - byte[] base64 = pubkeyElement.getDataElement().getB64Data(); - PGPPublicKeyRing keyRing = PGPainless.readKeyRing().publicKeyRing(Base64.decode(base64)); - provider.getStore().importPublicKey(owner, keyRing); - } - /** * Create a {@link PubkeyElement} which contains the OpenPGP public key of {@code owner} which belongs to * the {@link OpenPgpV4Fingerprint} {@code fingerprint}. @@ -509,13 +513,10 @@ public final class OpenPgpManager extends Manager { OpenPgpV4Fingerprint fingerprint, Date date) throws MissingOpenPgpPublicKeyException, IOException, PGPException { - PGPPublicKeyRingCollection publicKeyRingCollection = provider.getStore().getPublicKeysOf(owner); - if (publicKeyRingCollection != null) { - PGPPublicKeyRing keys = publicKeyRingCollection.getPublicKeyRing(fingerprint.getKeyId()); - if (keys != null) { - byte[] keyBytes = keys.getEncoded(true); - return createPubkeyElement(keyBytes, date); - } + PGPPublicKeyRing ring = provider.getStore().getPublicKeyRing(owner, fingerprint); + if (ring != null) { + byte[] keyBytes = ring.getEncoded(true); + return createPubkeyElement(keyBytes, date); } throw new MissingOpenPgpPublicKeyException(owner, fingerprint); } diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/store/abstr/AbstractOpenPgpKeyStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/store/abstr/AbstractOpenPgpKeyStore.java index de977a9d1..fa511c2c7 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/store/abstr/AbstractOpenPgpKeyStore.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/store/abstr/AbstractOpenPgpKeyStore.java @@ -37,7 +37,6 @@ import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.jxmpp.jid.BareJid; import org.pgpainless.pgpainless.PGPainless; import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint; -import org.pgpainless.pgpainless.key.generation.type.length.RsaLength; import org.pgpainless.pgpainless.util.BCUtil; public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore { @@ -87,15 +86,17 @@ public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore { throw new MissingUserIdOnKeyException(owner, secretKeys.getPublicKey().getKeyID()); } + PGPSecretKeyRing importKeys = BCUtil.removeUnassociatedKeysFromKeyRing(secretKeys, secretKeys.getPublicKey()); + PGPSecretKeyRingCollection secretKeyRings = getSecretKeysOf(owner); try { if (secretKeyRings != null) { - secretKeyRings = PGPSecretKeyRingCollection.addSecretKeyRing(secretKeyRings, secretKeys); + secretKeyRings = PGPSecretKeyRingCollection.addSecretKeyRing(secretKeyRings, importKeys); } else { - secretKeyRings = BCUtil.keyRingsToKeyRingCollection(secretKeys); + secretKeyRings = BCUtil.keyRingsToKeyRingCollection(importKeys); } } catch (IllegalArgumentException e) { - LOGGER.log(Level.INFO, "Skipping secret key ring " + Long.toHexString(secretKeys.getPublicKey().getKeyID()) + + LOGGER.log(Level.INFO, "Skipping secret key ring " + Long.toHexString(importKeys.getPublicKey().getKeyID()) + " as it is already in the key ring of " + owner.toString()); } this.secretKeyRingCollections.put(owner, secretKeyRings); @@ -110,15 +111,17 @@ public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore { throw new MissingUserIdOnKeyException(owner, publicKeys.getPublicKey().getKeyID()); } + PGPPublicKeyRing importKeys = BCUtil.removeUnassociatedKeysFromKeyRing(publicKeys, publicKeys.getPublicKey()); + PGPPublicKeyRingCollection publicKeyRings = getPublicKeysOf(owner); try { if (publicKeyRings != null) { - publicKeyRings = PGPPublicKeyRingCollection.addPublicKeyRing(publicKeyRings, publicKeys); + publicKeyRings = PGPPublicKeyRingCollection.addPublicKeyRing(publicKeyRings, importKeys); } else { - publicKeyRings = BCUtil.keyRingsToKeyRingCollection(publicKeys); + publicKeyRings = BCUtil.keyRingsToKeyRingCollection(importKeys); } } catch (IllegalArgumentException e) { - LOGGER.log(Level.INFO, "Skipping public key ring " + Long.toHexString(publicKeys.getPublicKey().getKeyID()) + + LOGGER.log(Level.INFO, "Skipping public key ring " + Long.toHexString(importKeys.getPublicKey().getKeyID()) + " as it is already in the key ring of " + owner.toString()); } this.publicKeyRingCollections.put(owner, publicKeyRings); @@ -176,6 +179,6 @@ public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore { @Override public PGPSecretKeyRing generateKeyRing(BareJid owner) throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException { - return PGPainless.generateKeyRing().simpleRsaKeyRing("xmpp:" + owner.toString(), RsaLength._4096); + return PGPainless.generateKeyRing().simpleEcKeyRing("xmpp:" + owner.toString()); } }