Update OpenPgp fingerprints of contacts

This commit is contained in:
Paul Schaub 2018-07-03 11:29:51 +02:00
parent 613c5d869a
commit 6c9e41c1b2
3 changed files with 62 additions and 21 deletions

View File

@ -26,6 +26,7 @@ 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;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -140,15 +141,6 @@ public final class OpenPgpManager extends Manager {
this.provider = provider; this.provider = provider;
} }
/**
* Return the registered {@link OpenPgpProvider}.
*
* @return provider.
*/
OpenPgpProvider getOpenPgpProvider() {
return provider;
}
/** /**
* Generate a fresh OpenPGP key pair, given we don't have one already. * Generate a fresh OpenPGP key pair, given we don't have one already.
* Publish the public key to the Public Key Node and update the Public Key Metadata Node with our keys fingerprint. * Publish the public key to the Public Key Node and update the Public Key Metadata Node with our keys fingerprint.
@ -231,12 +223,9 @@ public final class OpenPgpManager extends Manager {
* @throws SmackOpenPgpException if something happens while gathering fingerprints. * @throws SmackOpenPgpException if something happens while gathering fingerprints.
* @throws InterruptedException * @throws InterruptedException
* @throws XMPPException.XMPPErrorException * @throws XMPPException.XMPPErrorException
* @throws SmackException.NotConnectedException
* @throws SmackException.NoResponseException
*/ */
public OpenPgpContact getOpenPgpContact(EntityBareJid jid) public OpenPgpContact getOpenPgpContact(EntityBareJid jid)
throws SmackOpenPgpException, InterruptedException, XMPPException.XMPPErrorException, throws SmackOpenPgpException, InterruptedException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, SmackException.NoResponseException,
SmackException.NotLoggedInException { SmackException.NotLoggedInException {
throwIfNotAuthenticated(); throwIfNotAuthenticated();
@ -245,7 +234,7 @@ public final class OpenPgpManager extends Manager {
if (openPgpContact == null) { if (openPgpContact == null) {
OpenPgpFingerprints theirKeys = determineContactsKeys(jid); OpenPgpFingerprints theirKeys = determineContactsKeys(jid);
OpenPgpFingerprints ourKeys = determineContactsKeys(connection().getUser().asBareJid()); OpenPgpFingerprints ourKeys = determineContactsKeys(connection().getUser().asBareJid());
openPgpContact = new OpenPgpContact(getOpenPgpProvider(), jid, ourKeys, theirKeys); openPgpContact = new OpenPgpContact(provider, jid, ourKeys, theirKeys);
openPgpCapableContacts.put(jid, openPgpContact); openPgpCapableContacts.put(jid, openPgpContact);
} }
@ -434,20 +423,37 @@ public final class OpenPgpManager extends Manager {
provider.getStore().setAnnouncedKeysFingerprints(contact, announcedKeys); provider.getStore().setAnnouncedKeysFingerprints(contact, announcedKeys);
Set<OpenPgpV4Fingerprint> missingKeys = listElement.getMetadata().keySet(); Set<OpenPgpV4Fingerprint> availableKeys = Collections.emptySet();
try { try {
missingKeys.removeAll(provider.getStore().getAvailableKeysFingerprints(contact).keySet()); availableKeys = new HashSet<>(provider.getStore().getAvailableKeysFingerprints(contact).keySet());
} catch (SmackOpenPgpException e) {
LOGGER.log(Level.WARNING, "Could not determine available keys", e);
}
Set<OpenPgpV4Fingerprint> missingKeys = listElement.getMetadata().keySet();
Map<OpenPgpV4Fingerprint, Throwable> unfetchable = new HashMap<>();
try {
missingKeys.removeAll(availableKeys);
for (OpenPgpV4Fingerprint missing : missingKeys) { for (OpenPgpV4Fingerprint missing : missingKeys) {
try { try {
PubkeyElement pubkeyElement = fetchPubkey(connection(), contact, missing); PubkeyElement pubkeyElement = fetchPubkey(connection(), contact, missing);
processPublicKey(pubkeyElement, contact); if (pubkeyElement != null) {
processPublicKey(pubkeyElement, contact);
availableKeys.add(missing);
}
} catch (Exception e) { } catch (Exception e) {
LOGGER.log(Level.WARNING, "Error fetching missing OpenPGP key " + missing.toString(), e); LOGGER.log(Level.WARNING, "Error fetching missing OpenPGP key " + missing.toString(), e);
unfetchable.put(missing, e);
} }
} }
} catch (Exception e) { } catch (Exception e) {
LOGGER.log(Level.WARNING, "Error processing OpenPGP metadata update from " + contact + ".", e); LOGGER.log(Level.WARNING, "Error processing OpenPGP metadata update from " + contact + ".", e);
} }
OpenPgpFingerprints fingerprints = new OpenPgpFingerprints(contact, announcedKeys.keySet(), availableKeys, unfetchable);
for (OpenPgpContact openPgpContact : openPgpCapableContacts.values()) {
openPgpContact.onFingerprintsChanged(contact, fingerprints);
}
} }
private final IncomingChatMessageListener incomingOpenPgpMessageListener = private final IncomingChatMessageListener incomingOpenPgpMessageListener =
@ -464,8 +470,7 @@ public final class OpenPgpManager extends Manager {
try { try {
contact = getOpenPgpContact(from); contact = getOpenPgpContact(from);
} catch (SmackOpenPgpException | InterruptedException | XMPPException.XMPPErrorException | } catch (SmackOpenPgpException | InterruptedException | XMPPException.XMPPErrorException |
SmackException.NotLoggedInException | SmackException.NotConnectedException | SmackException.NotLoggedInException e) {
SmackException.NoResponseException e) {
LOGGER.log(Level.WARNING, "Could not begin encrypted chat with " + from, e); LOGGER.log(Level.WARNING, "Could not begin encrypted chat with " + from, e);
return; return;
} }

View File

@ -37,17 +37,18 @@ import org.jivesoftware.smackx.ox.element.SigncryptElement;
import org.jivesoftware.smackx.ox.exception.MissingOpenPgpKeyPairException; import org.jivesoftware.smackx.ox.exception.MissingOpenPgpKeyPairException;
import org.jivesoftware.smackx.ox.exception.MissingOpenPgpPublicKeyException; import org.jivesoftware.smackx.ox.exception.MissingOpenPgpPublicKeyException;
import org.jivesoftware.smackx.ox.exception.SmackOpenPgpException; import org.jivesoftware.smackx.ox.exception.SmackOpenPgpException;
import org.jivesoftware.smackx.ox.listener.internal.FingerprintsChangedListener;
import org.jivesoftware.smackx.ox.util.DecryptedBytesAndMetadata; import org.jivesoftware.smackx.ox.util.DecryptedBytesAndMetadata;
import org.jxmpp.jid.BareJid; import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.Jid; import org.jxmpp.jid.Jid;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
public class OpenPgpContact { public class OpenPgpContact implements FingerprintsChangedListener {
private final BareJid jid; private final BareJid jid;
private final OpenPgpFingerprints contactsFingerprints; private OpenPgpFingerprints contactsFingerprints;
private final OpenPgpFingerprints ourFingerprints; private OpenPgpFingerprints ourFingerprints;
private final OpenPgpProvider cryptoProvider; private final OpenPgpProvider cryptoProvider;
private final OpenPgpV4Fingerprint singingKey; private final OpenPgpV4Fingerprint singingKey;
@ -167,4 +168,13 @@ public class OpenPgpContact {
return fingerprints; return fingerprints;
} }
@Override
public void onFingerprintsChanged(BareJid contact, OpenPgpFingerprints newFingerprints) {
if (ourFingerprints.getJid().equals(contact)) {
this.ourFingerprints = newFingerprints;
} else if (contactsFingerprints.getJid().equals(contact)) {
this.contactsFingerprints = newFingerprints;
}
}
} }

View File

@ -0,0 +1,26 @@
/**
*
* Copyright 2018 Paul Schaub.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.ox.listener.internal;
import org.jivesoftware.smackx.ox.chat.OpenPgpFingerprints;
import org.jxmpp.jid.BareJid;
public interface FingerprintsChangedListener {
void onFingerprintsChanged(BareJid contact, OpenPgpFingerprints newFingerprints);
}