1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-11-27 06:22:07 +01:00

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.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<OpenPgpV4Fingerprint, Date> 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.<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)) {
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;
}

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 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,14 +513,11 @@ 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);
PGPPublicKeyRing ring = provider.getStore().getPublicKeyRing(owner, fingerprint);
if (ring != null) {
byte[] keyBytes = ring.getEncoded(true);
return createPubkeyElement(keyBytes, date);
}
}
throw new MissingOpenPgpPublicKeyException(owner, fingerprint);
}

View file

@ -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());
}
}