Smack/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpContact.java

136 lines
5.9 KiB
Java
Raw Normal View History

2018-07-08 22:31:35 +02:00
/**
*
* 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.
*/
2018-07-04 16:02:03 +02:00
package org.jivesoftware.smackx.ox;
2018-05-30 22:06:09 +02:00
2018-06-13 18:39:09 +02:00
import java.io.IOException;
2018-07-10 14:48:40 +02:00
import java.util.Collections;
2018-07-08 22:31:35 +02:00
import java.util.Date;
2018-07-09 15:01:15 +02:00
import java.util.HashMap;
2018-07-08 22:31:35 +02:00
import java.util.Map;
import java.util.logging.Level;
2018-07-03 18:07:54 +02:00
import java.util.logging.Logger;
2018-05-30 22:06:09 +02:00
2018-07-09 15:01:15 +02:00
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
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;
2018-07-08 22:31:35 +02:00
import org.jivesoftware.smackx.ox.selection_strategy.BareJidUserId;
2018-07-08 19:36:44 +02:00
import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
2018-07-09 15:01:15 +02:00
import org.jivesoftware.smackx.ox.util.PubSubDelegate;
import org.jivesoftware.smackx.pubsub.PubSubException;
2018-07-05 13:44:40 +02:00
2018-07-08 19:36:44 +02:00
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
2018-07-09 15:01:15 +02:00
import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
2018-06-13 18:39:09 +02:00
import org.jxmpp.jid.BareJid;
2018-07-08 19:36:44 +02:00
import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint;
2018-07-11 18:47:06 +02:00
import org.pgpainless.pgpainless.util.BCUtil;
2018-05-30 22:06:09 +02:00
2018-07-03 18:07:54 +02:00
public class OpenPgpContact {
2018-07-08 19:36:44 +02:00
private final Logger LOGGER;
2018-05-30 22:06:09 +02:00
2018-07-08 19:36:44 +02:00
protected final BareJid jid;
protected final OpenPgpStore store;
2018-07-03 18:07:54 +02:00
2018-07-08 19:36:44 +02:00
public OpenPgpContact(BareJid jid, OpenPgpStore store) {
2018-06-20 12:45:05 +02:00
this.jid = jid;
2018-07-08 19:36:44 +02:00
this.store = store;
LOGGER = Logger.getLogger(OpenPgpContact.class.getName() + ":" + jid.toString());
2018-05-30 22:06:09 +02:00
}
2018-06-20 12:45:05 +02:00
public BareJid getJid() {
return jid;
2018-06-20 11:02:30 +02:00
}
2018-07-08 19:36:44 +02:00
public PGPPublicKeyRingCollection getAnyPublicKeys() throws IOException, PGPException {
return store.getPublicKeysOf(jid);
2018-07-03 18:07:54 +02:00
}
2018-07-08 19:36:44 +02:00
public PGPPublicKeyRingCollection getAnnouncedPublicKeys() throws IOException, PGPException {
PGPPublicKeyRingCollection anyKeys = getAnyPublicKeys();
2018-07-08 22:31:35 +02:00
Map<OpenPgpV4Fingerprint, Date> announced = store.getAnnouncedFingerprintsOf(jid);
2018-07-03 18:07:54 +02:00
2018-07-08 22:31:35 +02:00
BareJidUserId.PubRingSelectionStrategy userIdFilter = new BareJidUserId.PubRingSelectionStrategy();
2018-07-11 18:47:06 +02:00
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()));
2018-07-03 18:07:54 +02:00
2018-07-08 22:31:35 +02:00
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() + "\"");
continue;
}
2018-07-03 18:07:54 +02:00
2018-07-11 18:47:06 +02:00
if (announcedKeysCollection == null) {
announcedKeysCollection = new PGPPublicKeyRingCollection(Collections.singleton(ring));
} else {
announcedKeysCollection = PGPPublicKeyRingCollection.addPublicKeyRing(announcedKeysCollection, ring);
2018-07-03 18:07:54 +02:00
}
}
2018-07-11 18:47:06 +02:00
2018-07-08 19:36:44 +02:00
return announcedKeysCollection;
2018-06-20 11:02:30 +02:00
}
2018-07-09 15:01:15 +02:00
public void updateKeys(XMPPConnection connection) throws InterruptedException, SmackException.NotConnectedException,
SmackException.NoResponseException, XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException,
PubSubException.NotAPubSubNodeException, IOException {
PublicKeysListElement metadata = PubSubDelegate.fetchPubkeysList(connection, getJid());
if (metadata == null) {
return;
}
Map<OpenPgpV4Fingerprint, Date> fingerprintsAndDates = new HashMap<>();
for (OpenPgpV4Fingerprint fingerprint : metadata.getMetadata().keySet()) {
fingerprintsAndDates.put(fingerprint, metadata.getMetadata().get(fingerprint).getDate());
}
store.setAnnouncedFingerprintsOf(getJid(), fingerprintsAndDates);
for (OpenPgpV4Fingerprint fingerprint : metadata.getMetadata().keySet()) {
try {
PubkeyElement key = PubSubDelegate.fetchPubkey(connection, getJid(), fingerprint);
if (key == null) {
LOGGER.log(Level.WARNING, "Public key " + Long.toHexString(fingerprint.getKeyId()) +
" can not be imported: Is null");
continue;
}
PGPPublicKeyRing keyRing = new PGPPublicKeyRing(Base64.decode(key.getDataElement().getB64Data()), new BcKeyFingerprintCalculator());
store.importPublicKey(getJid(), keyRing);
} catch (PubSubException.NotAPubSubNodeException | PubSubException.NotALeafNodeException |
XMPPException.XMPPErrorException e) {
LOGGER.log(Level.WARNING, "Error fetching public key " + Long.toHexString(fingerprint.getKeyId()), e);
} catch (PGPException | IOException e) {
LOGGER.log(Level.WARNING, "Public key " + Long.toHexString(fingerprint.getKeyId()) +
" can not be imported.", e);
} catch (MissingUserIdOnKeyException e) {
LOGGER.log(Level.WARNING, "Public key " + Long.toHexString(fingerprint.getKeyId()) +
" is missing the user-id \"xmpp:" + getJid() + "\". Refuse to import it.", e);
}
}
}
2018-05-30 22:06:09 +02:00
}