Improve key selection

This commit is contained in:
Paul Schaub 2018-07-11 18:47:06 +02:00
parent cc44b623a3
commit a470af0b73
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
3 changed files with 53 additions and 46 deletions

View File

@ -31,7 +31,6 @@ import org.jivesoftware.smack.util.stringencoder.Base64;
import org.jivesoftware.smackx.ox.element.PubkeyElement; import org.jivesoftware.smackx.ox.element.PubkeyElement;
import org.jivesoftware.smackx.ox.element.PublicKeysListElement; import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
import org.jivesoftware.smackx.ox.exception.MissingUserIdOnKeyException; 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.selection_strategy.BareJidUserId;
import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore; import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
import org.jivesoftware.smackx.ox.util.PubSubDelegate; 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.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
import org.jxmpp.jid.BareJid; import org.jxmpp.jid.BareJid;
import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint; import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.pgpainless.util.BCUtil;
public class OpenPgpContact { public class OpenPgpContact {
@ -69,26 +69,29 @@ public class OpenPgpContact {
PGPPublicKeyRingCollection anyKeys = getAnyPublicKeys(); PGPPublicKeyRingCollection anyKeys = getAnyPublicKeys();
Map<OpenPgpV4Fingerprint, Date> announced = store.getAnnouncedFingerprintsOf(jid); Map<OpenPgpV4Fingerprint, Date> announced = store.getAnnouncedFingerprintsOf(jid);
PGPPublicKeyRingCollection announcedKeysCollection = anyKeys;
BareJidUserId.PubRingSelectionStrategy userIdFilter = new BareJidUserId.PubRingSelectionStrategy(); BareJidUserId.PubRingSelectionStrategy userIdFilter = new BareJidUserId.PubRingSelectionStrategy();
AnnouncedKeys.PubKeyRingSelectionStrategy announcedFilter = new AnnouncedKeys.PubKeyRingSelectionStrategy();
for (PGPPublicKeyRing ring : (anyKeys != null ? anyKeys : Collections.<PGPPublicKeyRing>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)) { if (!userIdFilter.accept(getJid(), ring)) {
LOGGER.log(Level.WARNING, "Ignore key " + Long.toHexString(ring.getPublicKey().getKeyID()) + LOGGER.log(Level.WARNING, "Ignore key " + Long.toHexString(ring.getPublicKey().getKeyID()) +
" as it lacks the user-id \"xmpp" + getJid().toString() + "\""); " as it lacks the user-id \"xmpp" + getJid().toString() + "\"");
announcedKeysCollection = PGPPublicKeyRingCollection.removePublicKeyRing(announcedKeysCollection, ring);
continue; continue;
} }
if (!announcedFilter.accept(announced, ring)) { if (announcedKeysCollection == null) {
LOGGER.log(Level.WARNING, "Ignore key " + Long.toHexString(ring.getPublicKey().getKeyID()) + announcedKeysCollection = new PGPPublicKeyRingCollection(Collections.singleton(ring));
" as it is not announced by " + getJid().toString()); } else {
announcedKeysCollection = PGPPublicKeyRingCollection.removePublicKeyRing(announcedKeysCollection, ring); announcedKeysCollection = PGPPublicKeyRingCollection.addPublicKeyRing(announcedKeysCollection, ring);
} }
} }
return announcedKeysCollection; return announcedKeysCollection;
} }

View File

@ -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 static org.jivesoftware.smackx.ox.util.PubSubDelegate.publishPublicKey;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException; import java.security.NoSuchProviderException;
@ -79,12 +78,10 @@ import org.jivesoftware.smackx.pubsub.PubSubFeature;
import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.jxmpp.jid.BareJid; import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.EntityBareJid;
import org.pgpainless.pgpainless.PGPainless;
import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint; import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
@ -412,18 +409,41 @@ public final class OpenPgpManager extends Manager {
}; };
private void processPublicKeysListElement(BareJid contact, PublicKeysListElement listElement) { private void processPublicKeysListElement(BareJid contact, PublicKeysListElement listElement) {
OpenPgpContact openPgpContact = getOpenPgpContact(contact.asEntityBareJidIfPossible());
// TODO: Quick and dirty. Do it properly!!!
try { 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()) { for (OpenPgpV4Fingerprint fingerprint : listElement.getMetadata().keySet()) {
PGPPublicKeyRing key = contactsKeys.getPublicKeyRing(fingerprint.getKeyId()); PGPPublicKeyRing key = contactsKeys.getPublicKeyRing(fingerprint.getKeyId());
if (key == null) { 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) { } catch (PGPException | IOException e) {
LOGGER.log(Level.WARNING, "Could not read public keys of " + contact, e); LOGGER.log(Level.WARNING, "Could not read public keys of " + contact, e);
} }
*/
} }
private final IncomingChatMessageListener incomingOpenPgpMessageListener = private final IncomingChatMessageListener incomingOpenPgpMessageListener =
@ -478,22 +498,6 @@ public final class OpenPgpManager extends Manager {
Private stuff. 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 * Create a {@link PubkeyElement} which contains the OpenPGP public key of {@code owner} which belongs to
* the {@link OpenPgpV4Fingerprint} {@code fingerprint}. * the {@link OpenPgpV4Fingerprint} {@code fingerprint}.
@ -509,13 +513,10 @@ public final class OpenPgpManager extends Manager {
OpenPgpV4Fingerprint fingerprint, OpenPgpV4Fingerprint fingerprint,
Date date) Date date)
throws MissingOpenPgpPublicKeyException, IOException, PGPException { throws MissingOpenPgpPublicKeyException, IOException, PGPException {
PGPPublicKeyRingCollection publicKeyRingCollection = provider.getStore().getPublicKeysOf(owner); PGPPublicKeyRing ring = provider.getStore().getPublicKeyRing(owner, fingerprint);
if (publicKeyRingCollection != null) { if (ring != null) {
PGPPublicKeyRing keys = publicKeyRingCollection.getPublicKeyRing(fingerprint.getKeyId()); byte[] keyBytes = ring.getEncoded(true);
if (keys != null) { return createPubkeyElement(keyBytes, date);
byte[] keyBytes = keys.getEncoded(true);
return createPubkeyElement(keyBytes, date);
}
} }
throw new MissingOpenPgpPublicKeyException(owner, fingerprint); throw new MissingOpenPgpPublicKeyException(owner, fingerprint);
} }

View File

@ -37,7 +37,6 @@ import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.jxmpp.jid.BareJid; import org.jxmpp.jid.BareJid;
import org.pgpainless.pgpainless.PGPainless; import org.pgpainless.pgpainless.PGPainless;
import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint; import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.pgpainless.key.generation.type.length.RsaLength;
import org.pgpainless.pgpainless.util.BCUtil; import org.pgpainless.pgpainless.util.BCUtil;
public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore { public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore {
@ -87,15 +86,17 @@ public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore {
throw new MissingUserIdOnKeyException(owner, secretKeys.getPublicKey().getKeyID()); throw new MissingUserIdOnKeyException(owner, secretKeys.getPublicKey().getKeyID());
} }
PGPSecretKeyRing importKeys = BCUtil.removeUnassociatedKeysFromKeyRing(secretKeys, secretKeys.getPublicKey());
PGPSecretKeyRingCollection secretKeyRings = getSecretKeysOf(owner); PGPSecretKeyRingCollection secretKeyRings = getSecretKeysOf(owner);
try { try {
if (secretKeyRings != null) { if (secretKeyRings != null) {
secretKeyRings = PGPSecretKeyRingCollection.addSecretKeyRing(secretKeyRings, secretKeys); secretKeyRings = PGPSecretKeyRingCollection.addSecretKeyRing(secretKeyRings, importKeys);
} else { } else {
secretKeyRings = BCUtil.keyRingsToKeyRingCollection(secretKeys); secretKeyRings = BCUtil.keyRingsToKeyRingCollection(importKeys);
} }
} catch (IllegalArgumentException e) { } 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()); " as it is already in the key ring of " + owner.toString());
} }
this.secretKeyRingCollections.put(owner, secretKeyRings); this.secretKeyRingCollections.put(owner, secretKeyRings);
@ -110,15 +111,17 @@ public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore {
throw new MissingUserIdOnKeyException(owner, publicKeys.getPublicKey().getKeyID()); throw new MissingUserIdOnKeyException(owner, publicKeys.getPublicKey().getKeyID());
} }
PGPPublicKeyRing importKeys = BCUtil.removeUnassociatedKeysFromKeyRing(publicKeys, publicKeys.getPublicKey());
PGPPublicKeyRingCollection publicKeyRings = getPublicKeysOf(owner); PGPPublicKeyRingCollection publicKeyRings = getPublicKeysOf(owner);
try { try {
if (publicKeyRings != null) { if (publicKeyRings != null) {
publicKeyRings = PGPPublicKeyRingCollection.addPublicKeyRing(publicKeyRings, publicKeys); publicKeyRings = PGPPublicKeyRingCollection.addPublicKeyRing(publicKeyRings, importKeys);
} else { } else {
publicKeyRings = BCUtil.keyRingsToKeyRingCollection(publicKeys); publicKeyRings = BCUtil.keyRingsToKeyRingCollection(importKeys);
} }
} catch (IllegalArgumentException e) { } 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()); " as it is already in the key ring of " + owner.toString());
} }
this.publicKeyRingCollections.put(owner, publicKeyRings); this.publicKeyRingCollections.put(owner, publicKeyRings);
@ -176,6 +179,6 @@ public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore {
@Override @Override
public PGPSecretKeyRing generateKeyRing(BareJid owner) public PGPSecretKeyRing generateKeyRing(BareJid owner)
throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException { throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
return PGPainless.generateKeyRing().simpleRsaKeyRing("xmpp:" + owner.toString(), RsaLength._4096); return PGPainless.generateKeyRing().simpleEcKeyRing("xmpp:" + owner.toString());
} }
} }