1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-07-14 22:12:33 +02:00

Bump PGPainless to 0.2.0

This commit is contained in:
Paul Schaub 2021-06-05 21:27:47 +02:00
parent 4f2d8e8d4c
commit 340ef42736
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
24 changed files with 228 additions and 472 deletions

View file

@ -8,7 +8,7 @@ dependencies {
api project(':smack-extensions')
api project(':smack-experimental')
api 'org.pgpainless:pgpainless-core:0.1.0'
api 'org.pgpainless:pgpainless-core:0.2.0'
testImplementation "org.bouncycastle:bcprov-jdk15on:${bouncyCastleVersion}"

View file

@ -31,11 +31,9 @@ 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;
import org.jivesoftware.smackx.ox.selection_strategy.BareJidUserId;
import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
import org.jivesoftware.smackx.ox.store.definition.OpenPgpTrustStore;
import org.jivesoftware.smackx.ox.util.OpenPgpPubSubUtil;
@ -48,7 +46,7 @@ import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
import org.jxmpp.jid.BareJid;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.util.BCUtil;
import org.pgpainless.key.info.KeyRingInfo;
/**
* The OpenPgpContact is sort of a specialized view on the OpenPgpStore, which gives you access to the information
@ -108,17 +106,13 @@ public class OpenPgpContact {
PGPPublicKeyRingCollection anyKeys = getAnyPublicKeys();
Map<OpenPgpV4Fingerprint, Date> announced = store.getAnnouncedFingerprintsOf(jid);
BareJidUserId.PubRingSelectionStrategy userIdFilter = new BareJidUserId.PubRingSelectionStrategy();
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 (!new KeyRingInfo(ring).isUserIdValid("xmpp:" + getJid().toString())) {
LOGGER.log(Level.WARNING, "Ignore key " + Long.toHexString(ring.getPublicKey().getKeyID()) +
" as it lacks the user-id \"xmpp" + getJid().toString() + "\"");
continue;

View file

@ -79,9 +79,8 @@ import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.EntityBareJid;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.key.collection.PGPKeyRing;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.util.BCUtil;
import org.pgpainless.key.util.KeyRingUtils;
/**
* Entry point for Smacks API for OpenPGP for XMPP.
@ -296,27 +295,27 @@ public final class OpenPgpManager extends Manager {
throwIfNoProviderSet();
OpenPgpStore store = provider.getStore();
PGPKeyRing keys = generateKeyRing(ourJid);
PGPSecretKeyRing keys = generateKeyRing(ourJid);
importKeyRing(ourJid, keys);
OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint(keys.getSecretKeys());
OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint(keys);
store.setTrust(ourJid, fingerprint, OpenPgpTrustStore.Trust.trusted);
return fingerprint;
}
public PGPKeyRing generateKeyRing(BareJid ourJid)
public PGPSecretKeyRing generateKeyRing(BareJid ourJid)
throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
throwIfNoProviderSet();
PGPKeyRing keys = provider.getStore().generateKeyRing(ourJid);
PGPSecretKeyRing keys = provider.getStore().generateKeyRing(ourJid);
return keys;
}
private void importKeyRing(BareJid ourJid, PGPKeyRing keyRing) throws IOException, PGPException {
private void importKeyRing(BareJid ourJid, PGPSecretKeyRing secretKeys) throws IOException, PGPException {
try {
provider.getStore().importSecretKey(ourJid, keyRing.getSecretKeys());
provider.getStore().importPublicKey(ourJid, keyRing.getPublicKeys());
provider.getStore().importSecretKey(ourJid, secretKeys);
provider.getStore().importPublicKey(ourJid, KeyRingUtils.publicKeyRingFrom(secretKeys));
} catch (MissingUserIdOnKeyException e) {
// This should never throw, since we set our jid literally one line above this comment.
throw new AssertionError(e);
@ -515,7 +514,7 @@ public final class OpenPgpManager extends Manager {
PGPSecretKeyRing secretKeys = SecretKeyBackupHelper.restoreSecretKeyBackup(backup, backupCode);
OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint(secretKeys);
provider.getStore().importSecretKey(getJidOrThrow(), secretKeys);
provider.getStore().importPublicKey(getJidOrThrow(), BCUtil.publicKeyRingFromSecretKeyRing(secretKeys));
provider.getStore().importPublicKey(getJidOrThrow(), KeyRingUtils.publicKeyRingFrom(secretKeys));
getOpenPgpSelf().trust(fingerprint);

View file

@ -28,7 +28,6 @@ import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.jxmpp.jid.BareJid;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.util.BCUtil;
/**
* This class acts as our own OpenPGP identity. It can be seen as a special view on the {@link OpenPgpStore}, giving
@ -117,7 +116,6 @@ public class OpenPgpSelf extends OpenPgpContact {
public PGPPublicKeyRingCollection getAnnouncedPublicKeys() throws IOException, PGPException {
PGPSecretKeyRing secretKeys = getSigningKeyRing();
PGPPublicKeyRing publicKeys = getAnyPublicKeys().getPublicKeyRing(secretKeys.getPublicKey().getKeyID());
publicKeys = BCUtil.removeUnassociatedKeysFromKeyRing(publicKeys, secretKeys.getPublicKey());
return new PGPPublicKeyRingCollection(Collections.singleton(publicKeys));
}
}

View file

@ -19,6 +19,7 @@ package org.jivesoftware.smackx.ox.crypto;
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
import org.pgpainless.decryption_verification.OpenPgpMetadata;
import org.pgpainless.encryption_signing.EncryptionResult;
/**
* Bundle together an {@link OpenPgpElement} and {@link OpenPgpMetadata}.
@ -26,7 +27,7 @@ import org.pgpainless.decryption_verification.OpenPgpMetadata;
public class OpenPgpElementAndMetadata {
private final OpenPgpElement element;
private final OpenPgpMetadata metadata;
private final EncryptionResult metadata;
/**
* Constructor.
@ -34,7 +35,7 @@ public class OpenPgpElementAndMetadata {
* @param element element
* @param metadata metadata about the elements encryption
*/
public OpenPgpElementAndMetadata(OpenPgpElement element, OpenPgpMetadata metadata) {
public OpenPgpElementAndMetadata(OpenPgpElement element, EncryptionResult metadata) {
this.element = element;
this.metadata = metadata;
}
@ -49,11 +50,11 @@ public class OpenPgpElementAndMetadata {
}
/**
* Return {@link OpenPgpMetadata} about the {@link OpenPgpElement}s encryption/signatures.
* Return an {@link EncryptionResult} containing metadata about the {@link OpenPgpElement}s encryption/signatures.
*
* @return metadata TODO javadoc me please
*/
public OpenPgpMetadata getMetadata() {
public EncryptionResult getMetadata() {
return metadata;
}
}

View file

@ -19,7 +19,6 @@ package org.jivesoftware.smackx.ox.crypto;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -43,14 +42,18 @@ import org.jivesoftware.smackx.pubsub.PubSubException.NotALeafNodeException;
import org.jivesoftware.smackx.pubsub.PubSubException.NotAPubSubNodeException;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.util.io.Streams;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.DocumentSignatureType;
import org.pgpainless.decryption_verification.DecryptionStream;
import org.pgpainless.decryption_verification.MissingPublicKeyCallback;
import org.pgpainless.decryption_verification.OpenPgpMetadata;
import org.pgpainless.encryption_signing.EncryptionOptions;
import org.pgpainless.encryption_signing.EncryptionStream;
import org.pgpainless.encryption_signing.ProducerOptions;
import org.pgpainless.encryption_signing.SigningOptions;
public class PainlessOpenPgpProvider implements OpenPgpProvider {
@ -73,23 +76,26 @@ public class PainlessOpenPgpProvider implements OpenPgpProvider {
InputStream plainText = element.toInputStream();
ByteArrayOutputStream cipherText = new ByteArrayOutputStream();
ArrayList<PGPPublicKeyRingCollection> recipientKeys = new ArrayList<>();
EncryptionOptions encOpts = EncryptionOptions.encryptCommunications();
for (OpenPgpContact contact : recipients) {
PGPPublicKeyRingCollection keys = contact.getTrustedAnnouncedKeys();
if (keys == null) {
LOGGER.log(Level.WARNING, "There are no suitable keys for contact " + contact.getJid());
}
recipientKeys.add(keys);
encOpts.addRecipients(keys);
}
EncryptionStream cipherStream = PGPainless.createEncryptor().onOutputStream(cipherText)
.toRecipients(recipientKeys.toArray(new PGPPublicKeyRingCollection[] {}))
.andToSelf(self.getTrustedAnnouncedKeys())
.usingSecureAlgorithms()
.signWith(getStore().getKeyRingProtector(), self.getSigningKeyRing())
.noArmor();
encOpts.addRecipients(self.getTrustedAnnouncedKeys());
SigningOptions signOpts = new SigningOptions();
signOpts.addInlineSignature(getStore().getKeyRingProtector(), self.getSigningKeyRing(),
"xmpp:" + self.getJid().toString(), DocumentSignatureType.BINARY_DOCUMENT);
EncryptionStream cipherStream = PGPainless.encryptAndOrSign()
.onOutputStream(cipherText)
.withOptions(ProducerOptions
.signAndEncrypt(encOpts, signOpts)
.setAsciiArmor(false));
Streams.pipeAll(plainText, cipherStream);
plainText.close();
@ -109,10 +115,12 @@ public class PainlessOpenPgpProvider implements OpenPgpProvider {
InputStream plainText = element.toInputStream();
ByteArrayOutputStream cipherText = new ByteArrayOutputStream();
EncryptionStream cipherStream = PGPainless.createEncryptor().onOutputStream(cipherText)
.doNotEncrypt()
.signWith(getStore().getKeyRingProtector(), self.getSigningKeyRing())
.noArmor();
EncryptionStream cipherStream = PGPainless.encryptAndOrSign()
.onOutputStream(cipherText)
.withOptions(ProducerOptions.sign(new SigningOptions()
.addInlineSignature(getStore().getKeyRingProtector(), self.getSigningKeyRing(),
"xmpp:" + self.getJid().toString(), DocumentSignatureType.BINARY_DOCUMENT)
).setAsciiArmor(false));
Streams.pipeAll(plainText, cipherStream);
plainText.close();
@ -132,22 +140,23 @@ public class PainlessOpenPgpProvider implements OpenPgpProvider {
InputStream plainText = element.toInputStream();
ByteArrayOutputStream cipherText = new ByteArrayOutputStream();
ArrayList<PGPPublicKeyRingCollection> recipientKeys = new ArrayList<>();
EncryptionOptions encOpts = EncryptionOptions.encryptCommunications();
for (OpenPgpContact contact : recipients) {
PGPPublicKeyRingCollection keys = contact.getTrustedAnnouncedKeys();
if (keys != null) {
recipientKeys.add(keys);
} else {
LOGGER.log(Level.WARNING, "There are no suitable keys for contact " + contact.getJid().toString());
if (keys == null) {
LOGGER.log(Level.WARNING, "There are no suitable keys for contact " + contact.getJid());
}
encOpts.addRecipients(keys);
}
EncryptionStream cipherStream = PGPainless.createEncryptor().onOutputStream(cipherText)
.toRecipients(recipientKeys.toArray(new PGPPublicKeyRingCollection[] {}))
.andToSelf(self.getTrustedAnnouncedKeys())
.usingSecureAlgorithms()
.doNotSign()
.noArmor();
encOpts.addRecipients(self.getTrustedAnnouncedKeys());
EncryptionStream cipherStream = PGPainless.encryptAndOrSign()
.onOutputStream(cipherText)
.withOptions(ProducerOptions
.encrypt(encOpts)
.setAsciiArmor(false)
);
Streams.pipeAll(plainText, cipherStream);
plainText.close();
@ -172,26 +181,34 @@ public class PainlessOpenPgpProvider implements OpenPgpProvider {
sender.updateKeys(connection);
announcedPublicKeys = sender.getAnnouncedPublicKeys();
} catch (InterruptedException | NotALeafNodeException | NotAPubSubNodeException | NotConnectedException
| NoResponseException | XMPPErrorException e) {
| NoResponseException | XMPPErrorException e) {
throw new PGPException("Abort decryption due to lack of keys", e);
}
}
MissingPublicKeyCallback missingPublicKeyCallback = new MissingPublicKeyCallback() {
@Override
public PGPPublicKey onMissingPublicKeyEncountered(Long keyId) {
public PGPPublicKeyRing onMissingPublicKeyEncountered(Long keyId) {
try {
sender.updateKeys(connection);
return sender.getAnyPublicKeys().getPublicKey(keyId);
PGPPublicKeyRingCollection anyKeys = sender.getAnyPublicKeys();
for (PGPPublicKeyRing ring : anyKeys) {
if (ring.getPublicKey(keyId) != null) {
return ring;
}
}
return null;
} catch (InterruptedException | NotALeafNodeException | NotAPubSubNodeException | NotConnectedException
| NoResponseException | XMPPErrorException | IOException | PGPException e) {
| NoResponseException | XMPPErrorException | IOException | PGPException e) {
LOGGER.log(Level.WARNING, "Cannot fetch missing key " + keyId, e);
return null;
}
}
};
DecryptionStream cipherStream = PGPainless.createDecryptor().onInputStream(cipherText)
DecryptionStream cipherStream = PGPainless.decryptAndOrVerify()
.onInputStream(cipherText)
.decryptWith(getStore().getKeyRingProtector(), self.getSecretKeys())
.verifyWith(announcedPublicKeys)
.handleMissingPublicKeysWith(missingPublicKeyCallback)

View file

@ -1,45 +0,0 @@
/**
*
* 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.selection_strategy;
import java.util.Date;
import java.util.Map;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.key.selection.keyring.PublicKeyRingSelectionStrategy;
import org.pgpainless.key.selection.keyring.SecretKeyRingSelectionStrategy;
public class AnnouncedKeys {
public static class PubKeyRingSelectionStrategy extends PublicKeyRingSelectionStrategy<Map<OpenPgpV4Fingerprint, Date>> {
@Override
public boolean accept(Map<OpenPgpV4Fingerprint, Date> announcedKeys, PGPPublicKeyRing publicKeys) {
return announcedKeys.keySet().contains(new OpenPgpV4Fingerprint(publicKeys));
}
}
public static class SecKeyRingSelectionStrategy extends SecretKeyRingSelectionStrategy<Map<OpenPgpV4Fingerprint, Date>> {
@Override
public boolean accept(Map<OpenPgpV4Fingerprint, Date> announcedKeys, PGPSecretKeyRing secretKeys) {
return announcedKeys.keySet().contains(new OpenPgpV4Fingerprint(secretKeys));
}
}
}

View file

@ -1,58 +0,0 @@
/**
*
* 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.selection_strategy;
import java.util.Iterator;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.jxmpp.jid.BareJid;
import org.pgpainless.key.selection.keyring.PublicKeyRingSelectionStrategy;
import org.pgpainless.key.selection.keyring.SecretKeyRingSelectionStrategy;
public class BareJidUserId {
public static class PubRingSelectionStrategy extends PublicKeyRingSelectionStrategy<BareJid> {
@Override
public boolean accept(BareJid jid, PGPPublicKeyRing ring) {
Iterator<String> userIds = ring.getPublicKey().getUserIDs();
while (userIds.hasNext()) {
String userId = userIds.next();
if (userId.equals("xmpp:" + jid.toString())) {
return true;
}
}
return false;
}
}
public static class SecRingSelectionStrategy extends SecretKeyRingSelectionStrategy<BareJid> {
@Override
public boolean accept(BareJid jid, PGPSecretKeyRing ring) {
Iterator<String> userIds = ring.getPublicKey().getUserIDs();
while (userIds.hasNext()) {
String userId = userIds.next();
if (userId.equals("xmpp:" + jid.toString())) {
return true;
}
}
return false;
}
}
}

View file

@ -20,6 +20,7 @@ import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@ -27,7 +28,6 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smackx.ox.exception.MissingUserIdOnKeyException;
import org.jivesoftware.smackx.ox.selection_strategy.BareJidUserId;
import org.jivesoftware.smackx.ox.store.definition.OpenPgpKeyStore;
import org.bouncycastle.openpgp.PGPException;
@ -38,8 +38,7 @@ import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.jxmpp.jid.BareJid;
import org.pgpainless.PGPainless;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.key.collection.PGPKeyRing;
import org.pgpainless.util.BCUtil;
import org.pgpainless.key.info.KeyRingInfo;
public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore {
@ -157,22 +156,19 @@ public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore {
public void importSecretKey(BareJid owner, PGPSecretKeyRing secretKeys)
throws IOException, PGPException, MissingUserIdOnKeyException {
// TODO: Avoid 'new' use instance method.
if (!new BareJidUserId.SecRingSelectionStrategy().accept(owner, secretKeys)) {
if (!new KeyRingInfo(secretKeys).isUserIdValid("xmpp:" + owner.toString())) {
throw new MissingUserIdOnKeyException(owner, new OpenPgpV4Fingerprint(secretKeys));
}
PGPSecretKeyRing importKeys = BCUtil.removeUnassociatedKeysFromKeyRing(secretKeys, secretKeys.getPublicKey());
PGPSecretKeyRingCollection secretKeyRings = getSecretKeysOf(owner);
try {
if (secretKeyRings != null) {
secretKeyRings = PGPSecretKeyRingCollection.addSecretKeyRing(secretKeyRings, importKeys);
secretKeyRings = PGPSecretKeyRingCollection.addSecretKeyRing(secretKeyRings, secretKeys);
} else {
secretKeyRings = BCUtil.keyRingsToKeyRingCollection(importKeys);
secretKeyRings = new PGPSecretKeyRingCollection(Collections.singleton(secretKeys));
}
} catch (IllegalArgumentException e) {
LOGGER.log(Level.INFO, "Skipping secret key ring " + Long.toHexString(importKeys.getPublicKey().getKeyID()) +
LOGGER.log(Level.INFO, "Skipping secret key ring " + Long.toHexString(secretKeys.getPublicKey().getKeyID()) +
" as it is already in the key ring of " + owner.toString());
}
this.secretKeyRingCollections.put(owner, secretKeyRings);
@ -182,21 +178,19 @@ public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore {
@Override
public void importPublicKey(BareJid owner, PGPPublicKeyRing publicKeys) throws IOException, PGPException, MissingUserIdOnKeyException {
if (!new BareJidUserId.PubRingSelectionStrategy().accept(owner, publicKeys)) {
if (!new KeyRingInfo(publicKeys).isUserIdValid("xmpp:" + owner.toString())) {
throw new MissingUserIdOnKeyException(owner, new OpenPgpV4Fingerprint(publicKeys));
}
PGPPublicKeyRing importKeys = BCUtil.removeUnassociatedKeysFromKeyRing(publicKeys, publicKeys.getPublicKey());
PGPPublicKeyRingCollection publicKeyRings = getPublicKeysOf(owner);
try {
if (publicKeyRings != null) {
publicKeyRings = PGPPublicKeyRingCollection.addPublicKeyRing(publicKeyRings, importKeys);
publicKeyRings = PGPPublicKeyRingCollection.addPublicKeyRing(publicKeyRings, publicKeys);
} else {
publicKeyRings = BCUtil.keyRingsToKeyRingCollection(importKeys);
publicKeyRings = new PGPPublicKeyRingCollection(Collections.singleton(publicKeys));
}
} catch (IllegalArgumentException e) {
LOGGER.log(Level.FINE, "Skipping public key ring " + Long.toHexString(importKeys.getPublicKey().getKeyID()) +
LOGGER.log(Level.FINE, "Skipping public key ring " + Long.toHexString(publicKeys.getPublicKey().getKeyID()) +
" as it is already in the key ring of " + owner.toString(), e);
}
this.publicKeyRingCollections.put(owner, publicKeyRings);
@ -252,8 +246,8 @@ public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore {
}
@Override
public PGPKeyRing generateKeyRing(BareJid owner)
public PGPSecretKeyRing generateKeyRing(BareJid owner)
throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
return PGPainless.generateKeyRing().simpleEcKeyRing("xmpp:" + owner.toString());
return PGPainless.generateKeyRing().modernKeyRing("xmpp:" + owner.toString(), null);
}
}

View file

@ -41,7 +41,6 @@ import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.jxmpp.jid.BareJid;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.key.collection.PGPKeyRing;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.key.protection.UnprotectedKeysProtector;
@ -123,7 +122,7 @@ public abstract class AbstractOpenPgpStore implements OpenPgpStore {
}
@Override
public PGPKeyRing generateKeyRing(BareJid owner) throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
public PGPSecretKeyRing generateKeyRing(BareJid owner) throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
return keyStore.generateKeyRing(owner);
}

View file

@ -32,7 +32,6 @@ import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.jxmpp.jid.BareJid;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.key.collection.PGPKeyRing;
public interface OpenPgpKeyStore {
@ -113,7 +112,7 @@ public interface OpenPgpKeyStore {
void deleteSecretKeyRing(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException, PGPException;
/**
* Generate a new {@link PGPKeyRing} for {@code owner}.
* Generate a new {@link PGPSecretKeyRing} for {@code owner}.
* The key will have a user-id containing the users {@link BareJid} (eg. "xmpp:juliet@capulet.lit").
* This method MUST NOT return null.
*
@ -126,7 +125,7 @@ public interface OpenPgpKeyStore {
* @throws NoSuchProviderException in case there is no suitable {@link java.security.Provider} registered.
* @throws InvalidAlgorithmParameterException in case an invalid algorithms configuration is used.
*/
PGPKeyRing generateKeyRing(BareJid owner) throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException;
PGPSecretKeyRing generateKeyRing(BareJid owner) throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException;
/**
* Import a {@link PGPSecretKeyRing} of {@code owner}.

View file

@ -16,8 +16,10 @@
*/
package org.jivesoftware.smackx.ox.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;
import org.jivesoftware.smack.util.StringUtils;
@ -31,9 +33,15 @@ import org.jivesoftware.smackx.ox.exception.MissingOpenPgpKeyException;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.util.io.Streams;
import org.jxmpp.jid.BareJid;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
import org.pgpainless.decryption_verification.DecryptionStream;
import org.pgpainless.encryption_signing.EncryptionOptions;
import org.pgpainless.encryption_signing.EncryptionStream;
import org.pgpainless.encryption_signing.ProducerOptions;
import org.pgpainless.exception.MissingDecryptionMethodException;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.util.Passphrase;
@ -72,21 +80,21 @@ public class SecretKeyBackupHelper {
* not accessible.
*/
public static SecretkeyElement createSecretkeyElement(OpenPgpProvider provider,
BareJid owner,
Set<OpenPgpV4Fingerprint> fingerprints,
OpenPgpSecretKeyBackupPassphrase backupCode)
BareJid owner,
Set<OpenPgpV4Fingerprint> fingerprints,
OpenPgpSecretKeyBackupPassphrase backupCode)
throws PGPException, IOException, MissingOpenPgpKeyException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
for (OpenPgpV4Fingerprint fingerprint : fingerprints) {
PGPSecretKeyRing key = provider.getStore().getSecretKeyRing(owner, fingerprint);
if (key == null) {
throw new MissingOpenPgpKeyException(owner, fingerprint);
}
PGPSecretKeyRing key = provider.getStore().getSecretKeyRing(owner, fingerprint);
if (key == null) {
throw new MissingOpenPgpKeyException(owner, fingerprint);
}
byte[] bytes = key.getEncoded();
buffer.write(bytes);
byte[] bytes = key.getEncoded();
buffer.write(bytes);
}
return createSecretkeyElement(buffer.toByteArray(), backupCode);
}
@ -108,9 +116,21 @@ public class SecretKeyBackupHelper {
public static SecretkeyElement createSecretkeyElement(byte[] keys,
OpenPgpSecretKeyBackupPassphrase backupCode)
throws PGPException, IOException {
byte[] encrypted = PGPainless.encryptWithPassword(keys, new Passphrase(backupCode.toString().toCharArray()),
SymmetricKeyAlgorithm.AES_256);
return new SecretkeyElement(Base64.encode(encrypted));
InputStream keyStream = new ByteArrayInputStream(keys);
ByteArrayOutputStream cryptOut = new ByteArrayOutputStream();
EncryptionOptions encOpts = new EncryptionOptions()
.addPassphrase(Passphrase.fromPassword(backupCode.toString()));
encOpts.overrideEncryptionAlgorithm(SymmetricKeyAlgorithm.AES_256);
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign()
.onOutputStream(cryptOut)
.withOptions(ProducerOptions.encrypt(encOpts)
.setAsciiArmor(false));
Streams.pipeAll(keyStream, encryptionStream);
encryptionStream.close();
return new SecretkeyElement(Base64.encode(cryptOut.toByteArray()));
}
/**
@ -127,14 +147,23 @@ public class SecretKeyBackupHelper {
public static PGPSecretKeyRing restoreSecretKeyBackup(SecretkeyElement backup, OpenPgpSecretKeyBackupPassphrase backupCode)
throws InvalidBackupCodeException, IOException, PGPException {
byte[] encrypted = Base64.decode(backup.getB64Data());
InputStream encryptedIn = new ByteArrayInputStream(encrypted);
ByteArrayOutputStream plaintextOut = new ByteArrayOutputStream();
byte[] decrypted;
try {
decrypted = PGPainless.decryptWithPassword(encrypted, new Passphrase(backupCode.toString().toCharArray()));
} catch (IOException | PGPException e) {
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
.onInputStream(encryptedIn)
.decryptWith(Passphrase.fromPassword(backupCode.toString()))
.doNotVerify()
.build();
Streams.pipeAll(decryptionStream, plaintextOut);
decryptionStream.close();
} catch (MissingDecryptionMethodException e) {
throw new InvalidBackupCodeException("Could not decrypt secret key backup. Possibly wrong passphrase?", e);
}
byte[] decrypted = plaintextOut.toByteArray();
return PGPainless.readKeyRing().secretKeyRing(decrypted);
}
}

View file

@ -49,6 +49,7 @@ import org.bouncycastle.openpgp.PGPException;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.Jid;
import org.pgpainless.decryption_verification.OpenPgpMetadata;
import org.pgpainless.encryption_signing.EncryptionResult;
import org.pgpainless.key.OpenPgpV4Fingerprint;
/**
@ -217,7 +218,7 @@ public final class OXInstantMessagingManager extends Manager {
* @param contact contact capable of OpenPGP for XMPP: Instant Messaging.
* @param body message body.
*
* @return {@link OpenPgpMetadata} about the messages encryption + signatures.
* @return {@link EncryptionResult} containing metadata about the messages encryption + signatures.
*
* @throws InterruptedException if the thread is interrupted
* @throws IOException IO is dangerous
@ -225,7 +226,7 @@ public final class OXInstantMessagingManager extends Manager {
* @throws SmackException.NotLoggedInException if we are not logged in
* @throws PGPException PGP is brittle
*/
public OpenPgpMetadata sendOxMessage(OpenPgpContact contact, CharSequence body)
public EncryptionResult sendOxMessage(OpenPgpContact contact, CharSequence body)
throws InterruptedException, IOException,
SmackException.NotConnectedException, SmackException.NotLoggedInException, PGPException {
MessageBuilder messageBuilder = connection()
@ -234,7 +235,7 @@ public final class OXInstantMessagingManager extends Manager {
.to(contact.getJid());
Message.Body mBody = new Message.Body(null, body.toString());
OpenPgpMetadata metadata = addOxMessage(messageBuilder, contact, Collections.<ExtensionElement>singletonList(mBody));
EncryptionResult metadata = addOxMessage(messageBuilder, contact, Collections.<ExtensionElement>singletonList(mBody));
Message message = messageBuilder.build();
ChatManager.getInstanceFor(connection()).chatWith(contact.getJid().asEntityBareJidIfPossible()).send(message);
@ -249,13 +250,13 @@ public final class OXInstantMessagingManager extends Manager {
* @param contact recipient of the message
* @param payload payload which will be encrypted and signed
*
* @return {@link OpenPgpMetadata} about the messages encryption + metadata.
* @return {@link EncryptionResult} containing metadata about the messages encryption + metadata.
*
* @throws SmackException.NotLoggedInException in case we are not logged in
* @throws PGPException in case something goes wrong during encryption
* @throws IOException IO is dangerous (we need to read keys)
*/
public OpenPgpMetadata addOxMessage(MessageBuilder messageBuilder, OpenPgpContact contact, List<ExtensionElement> payload)
public EncryptionResult addOxMessage(MessageBuilder messageBuilder, OpenPgpContact contact, List<ExtensionElement> payload)
throws SmackException.NotLoggedInException, PGPException, IOException {
return addOxMessage(messageBuilder, Collections.singleton(contact), payload);
}
@ -267,13 +268,13 @@ public final class OXInstantMessagingManager extends Manager {
* @param recipients recipients of the message
* @param payload payload which will be encrypted and signed
*
* @return metadata about the messages encryption + signatures.
* @return {@link EncryptionResult} containing metadata about the messages encryption + signatures.
*
* @throws SmackException.NotLoggedInException in case we are not logged in
* @throws PGPException in case something goes wrong during encryption
* @throws IOException IO is dangerous (we need to read keys)
*/
public OpenPgpMetadata addOxMessage(MessageBuilder messageBuilder, Set<OpenPgpContact> recipients, List<ExtensionElement> payload)
public EncryptionResult addOxMessage(MessageBuilder messageBuilder, Set<OpenPgpContact> recipients, List<ExtensionElement> payload)
throws SmackException.NotLoggedInException, IOException, PGPException {
OpenPgpElementAndMetadata openPgpElementAndMetadata = signAndEncrypt(recipients, payload);

View file

@ -16,12 +16,11 @@
*/
package org.jivesoftware.smackx.ox;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNotNull;
import static org.jivesoftware.smack.test.util.XmlAssertUtil.assertXmlSimilar;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
@ -35,7 +34,6 @@ import org.jivesoftware.smack.test.util.SmackTestSuite;
import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.ox.element.CryptElement;
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
import org.jivesoftware.smackx.ox.element.SignElement;
@ -180,7 +178,7 @@ public class OpenPgpElementTest extends SmackTestSuite {
}
@Test
public void openPgpContentElementProvider_invalidElementTest() throws IOException, XmlPullParserException {
public void openPgpContentElementProvider_invalidElementTest() {
String invalidElementXML = "<payload>" +
"<body xmlns='jabber:client' xml:lang='en'>This is a secret message.</body>" +
"</payload>";

View file

@ -16,8 +16,8 @@
*/
package org.jivesoftware.smackx.ox;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.jivesoftware.smackx.ox.util.SecretKeyBackupHelper;

View file

@ -16,12 +16,13 @@
*/
package org.jivesoftware.smackx.ox;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertNull;
import static junit.framework.TestCase.assertTrue;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.File;
import java.io.IOException;
@ -36,7 +37,6 @@ import java.util.HashMap;
import java.util.Map;
import org.jivesoftware.smack.test.util.SmackTestSuite;
import org.jivesoftware.smackx.ox.callback.SecretKeyPassphraseCallback;
import org.jivesoftware.smackx.ox.exception.MissingUserIdOnKeyException;
import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
@ -56,8 +56,8 @@ import org.junit.runners.Parameterized;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.JidTestUtil;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.key.collection.PGPKeyRing;
import org.pgpainless.key.protection.UnprotectedKeysProtector;
import org.pgpainless.key.util.KeyRingUtils;
import org.pgpainless.util.Passphrase;
@RunWith(Parameterized.class)
@ -128,15 +128,16 @@ public class OpenPgpStoreTest extends SmackTestSuite {
assertNull(openPgpStoreInstance1.getSecretKeysOf(alice));
assertNull(openPgpStoreInstance1.getPublicKeysOf(alice));
PGPKeyRing keys = openPgpStoreInstance1.generateKeyRing(alice);
openPgpStoreInstance1.importSecretKey(alice, keys.getSecretKeys());
openPgpStoreInstance1.importPublicKey(alice, keys.getPublicKeys());
PGPSecretKeyRing keys = openPgpStoreInstance1.generateKeyRing(alice);
OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint(keys);
openPgpStoreInstance1.importSecretKey(alice, keys);
openPgpStoreInstance1.importPublicKey(alice, KeyRingUtils.publicKeyRingFrom(keys));
assertNotNull(openPgpStoreInstance1.getSecretKeysOf(alice));
assertNotNull(openPgpStoreInstance1.getPublicKeysOf(alice));
openPgpStoreInstance1.deleteSecretKeyRing(alice, new OpenPgpV4Fingerprint(keys.getSecretKeys()));
openPgpStoreInstance1.deletePublicKeyRing(alice, new OpenPgpV4Fingerprint(keys.getSecretKeys()));
openPgpStoreInstance1.deleteSecretKeyRing(alice, fingerprint);
openPgpStoreInstance1.deletePublicKeyRing(alice, fingerprint);
assertNull(openPgpStoreInstance1.getPublicKeysOf(alice));
assertNull(openPgpStoreInstance1.getSecretKeysOf(alice));
@ -154,24 +155,23 @@ public class OpenPgpStoreTest extends SmackTestSuite {
public void t02_key_importKeysTest() throws IOException, PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException, MissingUserIdOnKeyException {
// Test for nullity of all possible values.
PGPKeyRing keys = openPgpStoreInstance1.generateKeyRing(alice);
PGPSecretKeyRing secretKeys = keys.getSecretKeys();
PGPPublicKeyRing publicKeys = keys.getPublicKeys();
PGPSecretKeyRing secretKeys = openPgpStoreInstance1.generateKeyRing(alice);
PGPPublicKeyRing publicKeys = KeyRingUtils.publicKeyRingFrom(secretKeys);
assertNotNull(secretKeys);
assertNotNull(publicKeys);
OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint(secretKeys);
OpenPgpContact cAlice = openPgpStoreInstance1.getOpenPgpContact(alice);
assertNull(cAlice.getAnyPublicKeys());
OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint(publicKeys);
assertEquals(fingerprint, new OpenPgpV4Fingerprint(secretKeys));
assertNull(openPgpStoreInstance1.getPublicKeysOf(alice));
assertNull(openPgpStoreInstance1.getSecretKeysOf(alice));
openPgpStoreInstance1.importPublicKey(alice, publicKeys);
assertTrue(Arrays.equals(publicKeys.getEncoded(), openPgpStoreInstance1.getPublicKeysOf(alice).getEncoded()));
assertArrayEquals(publicKeys.getEncoded(), openPgpStoreInstance1.getPublicKeysOf(alice).getEncoded());
assertNotNull(openPgpStoreInstance1.getPublicKeyRing(alice, fingerprint));
assertNull(openPgpStoreInstance1.getSecretKeysOf(alice));
@ -180,17 +180,17 @@ public class OpenPgpStoreTest extends SmackTestSuite {
// Import keys a second time -> No change expected.
openPgpStoreInstance1.importPublicKey(alice, publicKeys);
assertTrue(Arrays.equals(publicKeys.getEncoded(), openPgpStoreInstance1.getPublicKeysOf(alice).getEncoded()));
assertArrayEquals(publicKeys.getEncoded(), openPgpStoreInstance1.getPublicKeysOf(alice).getEncoded());
openPgpStoreInstance1.importSecretKey(alice, secretKeys);
assertTrue(Arrays.equals(secretKeys.getEncoded(), openPgpStoreInstance1.getSecretKeysOf(alice).getEncoded()));
assertArrayEquals(secretKeys.getEncoded(), openPgpStoreInstance1.getSecretKeysOf(alice).getEncoded());
openPgpStoreInstance1.importSecretKey(alice, secretKeys);
assertNotNull(openPgpStoreInstance1.getSecretKeysOf(alice));
assertTrue(Arrays.equals(secretKeys.getEncoded(), openPgpStoreInstance1.getSecretKeysOf(alice).getEncoded()));
assertArrayEquals(secretKeys.getEncoded(), openPgpStoreInstance1.getSecretKeysOf(alice).getEncoded());
assertNotNull(openPgpStoreInstance1.getSecretKeyRing(alice, fingerprint));
assertTrue(Arrays.equals(secretKeys.getEncoded(), openPgpStoreInstance1.getSecretKeyRing(alice, fingerprint).getEncoded()));
assertTrue(Arrays.equals(publicKeys.getEncoded(), openPgpStoreInstance1.getPublicKeyRing(alice, fingerprint).getEncoded()));
assertArrayEquals(secretKeys.getEncoded(), openPgpStoreInstance1.getSecretKeyRing(alice, fingerprint).getEncoded());
assertArrayEquals(publicKeys.getEncoded(), openPgpStoreInstance1.getPublicKeyRing(alice, fingerprint).getEncoded());
// Clean up
openPgpStoreInstance1.deletePublicKeyRing(alice, fingerprint);
@ -198,27 +198,27 @@ public class OpenPgpStoreTest extends SmackTestSuite {
}
@Test
public void t04_key_wrongBareJidOnSecretKeyImportTest() throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, IOException, MissingUserIdOnKeyException {
PGPSecretKeyRing secretKeys = openPgpStoreInstance1.generateKeyRing(alice).getSecretKeys();
public void t04_key_wrongBareJidOnSecretKeyImportTest() throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
PGPSecretKeyRing secretKeys = openPgpStoreInstance1.generateKeyRing(alice);
assertThrows(MissingUserIdOnKeyException.class, () ->
openPgpStoreInstance1.importSecretKey(bob, secretKeys));
openPgpStoreInstance1.importSecretKey(bob, secretKeys));
}
@Test
public void t05_key_wrongBareJidOnPublicKeyImportTest() throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, IOException, MissingUserIdOnKeyException {
PGPPublicKeyRing publicKeys = openPgpStoreInstance1.generateKeyRing(alice).getPublicKeys();
public void t05_key_wrongBareJidOnPublicKeyImportTest() throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
PGPSecretKeyRing secretKeys = openPgpStoreInstance1.generateKeyRing(alice);
PGPPublicKeyRing publicKeys = KeyRingUtils.publicKeyRingFrom(secretKeys);
assertThrows(MissingUserIdOnKeyException.class, () ->
openPgpStoreInstance1.importPublicKey(bob, publicKeys));
openPgpStoreInstance1.importPublicKey(bob, publicKeys));
}
@Test
public void t06_key_keyReloadTest() throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, IOException, MissingUserIdOnKeyException {
PGPKeyRing keys = openPgpStoreInstance1.generateKeyRing(alice);
PGPSecretKeyRing secretKeys = keys.getSecretKeys();
PGPSecretKeyRing secretKeys = openPgpStoreInstance1.generateKeyRing(alice);
OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint(secretKeys);
PGPPublicKeyRing publicKeys = keys.getPublicKeys();
PGPPublicKeyRing publicKeys = KeyRingUtils.publicKeyRingFrom(secretKeys);
openPgpStoreInstance1.importSecretKey(alice, secretKeys);
openPgpStoreInstance1.importPublicKey(alice, publicKeys);
@ -235,24 +235,23 @@ public class OpenPgpStoreTest extends SmackTestSuite {
@Test
public void t07_multipleKeysTest() throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, IOException, MissingUserIdOnKeyException {
PGPKeyRing one = openPgpStoreInstance1.generateKeyRing(alice);
PGPKeyRing two = openPgpStoreInstance1.generateKeyRing(alice);
PGPSecretKeyRing one = openPgpStoreInstance1.generateKeyRing(alice);
PGPSecretKeyRing two = openPgpStoreInstance1.generateKeyRing(alice);
OpenPgpV4Fingerprint fingerprint1 = new OpenPgpV4Fingerprint(one.getSecretKeys());
OpenPgpV4Fingerprint fingerprint2 = new OpenPgpV4Fingerprint(two.getSecretKeys());
OpenPgpV4Fingerprint fingerprint1 = new OpenPgpV4Fingerprint(one);
OpenPgpV4Fingerprint fingerprint2 = new OpenPgpV4Fingerprint(two);
openPgpStoreInstance1.importSecretKey(alice, one.getSecretKeys());
openPgpStoreInstance1.importSecretKey(alice, two.getSecretKeys());
openPgpStoreInstance1.importPublicKey(alice, one.getPublicKeys());
openPgpStoreInstance1.importPublicKey(alice, two.getPublicKeys());
openPgpStoreInstance1.importSecretKey(alice, one);
openPgpStoreInstance1.importSecretKey(alice, two);
openPgpStoreInstance1.importPublicKey(alice, KeyRingUtils.publicKeyRingFrom(one));
openPgpStoreInstance1.importPublicKey(alice, KeyRingUtils.publicKeyRingFrom(two));
assertTrue(Arrays.equals(one.getSecretKeys().getEncoded(), openPgpStoreInstance1.getSecretKeyRing(alice, fingerprint1).getEncoded()));
assertTrue(Arrays.equals(two.getSecretKeys().getEncoded(), openPgpStoreInstance1.getSecretKeyRing(alice, fingerprint2).getEncoded()));
assertArrayEquals(one.getEncoded(), openPgpStoreInstance1.getSecretKeyRing(alice, fingerprint1).getEncoded());
assertArrayEquals(two.getEncoded(), openPgpStoreInstance1.getSecretKeyRing(alice, fingerprint2).getEncoded());
assertTrue(Arrays.equals(one.getSecretKeys().getEncoded(), openPgpStoreInstance1.getSecretKeysOf(alice).getSecretKeyRing(fingerprint1.getKeyId()).getEncoded()));
assertArrayEquals(one.getEncoded(), openPgpStoreInstance1.getSecretKeysOf(alice).getSecretKeyRing(fingerprint1.getKeyId()).getEncoded());
assertTrue(Arrays.equals(one.getPublicKeys().getEncoded(),
openPgpStoreInstance1.getPublicKeyRing(alice, fingerprint1).getEncoded()));
assertArrayEquals(KeyRingUtils.publicKeyRingFrom(one).getEncoded(), openPgpStoreInstance1.getPublicKeyRing(alice, fingerprint1).getEncoded());
// Cleanup
openPgpStoreInstance1.deletePublicKeyRing(alice, fingerprint1);
@ -320,8 +319,8 @@ public class OpenPgpStoreTest extends SmackTestSuite {
assertFalse(openPgpStoreInstance2.getAnnouncedFingerprintsOf(alice).isEmpty());
assertEquals(map, openPgpStoreInstance2.getAnnouncedFingerprintsOf(alice));
openPgpStoreInstance1.setAnnouncedFingerprintsOf(alice, Collections.<OpenPgpV4Fingerprint, Date>emptyMap());
openPgpStoreInstance2.setAnnouncedFingerprintsOf(alice, Collections.<OpenPgpV4Fingerprint, Date>emptyMap());
openPgpStoreInstance1.setAnnouncedFingerprintsOf(alice, Collections.emptyMap());
openPgpStoreInstance2.setAnnouncedFingerprintsOf(alice, Collections.emptyMap());
}
@Test

View file

@ -16,9 +16,9 @@
*/
package org.jivesoftware.smackx.ox;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNull;
import static junit.framework.TestCase.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.File;
import java.io.IOException;
@ -35,7 +35,6 @@ import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.test.util.SmackTestSuite;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.ox.crypto.OpenPgpElementAndMetadata;
import org.jivesoftware.smackx.ox.crypto.PainlessOpenPgpProvider;
import org.jivesoftware.smackx.ox.element.CryptElement;
@ -46,6 +45,8 @@ import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
import org.jivesoftware.smackx.ox.store.filebased.FileBasedOpenPgpStore;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.jupiter.api.Test;
@ -53,8 +54,8 @@ import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.JidTestUtil;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.key.collection.PGPKeyRing;
import org.pgpainless.key.protection.UnprotectedKeysProtector;
import org.pgpainless.key.util.KeyRingUtils;
public class PainlessOpenPgpProviderTest extends SmackTestSuite {
@ -88,17 +89,19 @@ public class PainlessOpenPgpProviderTest extends SmackTestSuite {
PainlessOpenPgpProvider aliceProvider = new PainlessOpenPgpProvider(aliceStore);
PainlessOpenPgpProvider bobProvider = new PainlessOpenPgpProvider(bobStore);
PGPKeyRing aliceKeys = aliceStore.generateKeyRing(alice);
PGPKeyRing bobKeys = bobStore.generateKeyRing(bob);
PGPSecretKeyRing aliceKeys = aliceStore.generateKeyRing(alice);
PGPSecretKeyRing bobKeys = bobStore.generateKeyRing(bob);
PGPPublicKeyRing alicePubKeys = KeyRingUtils.publicKeyRingFrom(aliceKeys);
PGPPublicKeyRing bobPubKeys = KeyRingUtils.publicKeyRingFrom(bobKeys);
OpenPgpV4Fingerprint aliceFingerprint = new OpenPgpV4Fingerprint(aliceKeys.getPublicKeys());
OpenPgpV4Fingerprint bobFingerprint = new OpenPgpV4Fingerprint(bobKeys.getPublicKeys());
OpenPgpV4Fingerprint aliceFingerprint = new OpenPgpV4Fingerprint(aliceKeys);
OpenPgpV4Fingerprint bobFingerprint = new OpenPgpV4Fingerprint(bobKeys);
aliceStore.importSecretKey(alice, aliceKeys.getSecretKeys());
bobStore.importSecretKey(bob, bobKeys.getSecretKeys());
aliceStore.importSecretKey(alice, aliceKeys);
bobStore.importSecretKey(bob, bobKeys);
aliceStore.setAnnouncedFingerprintsOf(alice, Collections.singletonMap(new OpenPgpV4Fingerprint(aliceKeys.getPublicKeys()), new Date()));
bobStore.setAnnouncedFingerprintsOf(bob, Collections.singletonMap(new OpenPgpV4Fingerprint(bobKeys.getPublicKeys()), new Date()));
aliceStore.setAnnouncedFingerprintsOf(alice, Collections.singletonMap(aliceFingerprint, new Date()));
bobStore.setAnnouncedFingerprintsOf(bob, Collections.singletonMap(bobFingerprint, new Date()));
OpenPgpSelf aliceSelf = new OpenPgpSelf(alice, aliceStore);
aliceSelf.trust(aliceFingerprint);
@ -107,11 +110,11 @@ public class PainlessOpenPgpProviderTest extends SmackTestSuite {
// Exchange keys
aliceStore.importPublicKey(bob, bobKeys.getPublicKeys());
bobStore.importPublicKey(alice, aliceKeys.getPublicKeys());
aliceStore.importPublicKey(bob, bobPubKeys);
bobStore.importPublicKey(alice, alicePubKeys);
aliceStore.setAnnouncedFingerprintsOf(bob, Collections.singletonMap(new OpenPgpV4Fingerprint(bobKeys.getPublicKeys()), new Date()));
bobStore.setAnnouncedFingerprintsOf(alice, Collections.singletonMap(new OpenPgpV4Fingerprint(aliceKeys.getPublicKeys()), new Date()));
aliceStore.setAnnouncedFingerprintsOf(bob, Collections.singletonMap(bobFingerprint, new Date()));
bobStore.setAnnouncedFingerprintsOf(alice, Collections.singletonMap(aliceFingerprint, new Date()));
OpenPgpContact aliceForBob = new OpenPgpContact(alice, bobStore);
aliceForBob.trust(aliceFingerprint);
@ -121,7 +124,7 @@ public class PainlessOpenPgpProviderTest extends SmackTestSuite {
// Prepare message
Message.Body body = new Message.Body(null, "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
List<ExtensionElement> payload = Collections.<ExtensionElement>singletonList(body);
List<ExtensionElement> payload = Collections.singletonList(body);
OpenPgpElementAndMetadata encrypted;
@ -141,7 +144,7 @@ public class PainlessOpenPgpProviderTest extends SmackTestSuite {
OpenPgpV4Fingerprint decryptionFingerprint = decrypted.getMetadata().getDecryptionFingerprint();
assertTrue(bobSelf.getSecretKeys().contains(decryptionFingerprint.getKeyId()));
assertTrue(decrypted.getMetadata().getVerifiedSignatureKeyFingerprints().contains(aliceFingerprint));
assertTrue(decrypted.getMetadata().containsVerifiedSignatureFrom(alicePubKeys));
assertEquals(OpenPgpMessage.State.signcrypt, decrypted.getState());
SigncryptElement decryptedSignCrypt = (SigncryptElement) decrypted.getOpenPgpContentElement();
@ -172,7 +175,7 @@ public class PainlessOpenPgpProviderTest extends SmackTestSuite {
test sign
*/
SignElement signElement = new SignElement(Collections.<Jid>singleton(bob), new Date(), payload);
SignElement signElement = new SignElement(Collections.singleton(bob), new Date(), payload);