Search in sources :

Example 1 with SecretkeyElement

use of org.jivesoftware.smackx.ox.element.SecretkeyElement in project Smack by igniterealtime.

the class OpenPgpManager method restoreSecretKeyServerBackup.

/**
 * Fetch a secret key backup from the server and try to restore a selected secret key from it.
 *
 * @param codeCallback callback for prompting the user to provide the secret backup code.
 * @return fingerprint of the restored secret key
 *
 * @throws InterruptedException if the thread gets interrupted.
 * @throws PubSubException.NotALeafNodeException if the private node is not a {@link LeafNode}.
 * @throws XMPPException.XMPPErrorException in case of an XMPP protocol error.
 * @throws SmackException.NotConnectedException if we are not connected.
 * @throws SmackException.NoResponseException if the server doesn't respond.
 * @throws InvalidBackupCodeException if the user-provided backup code is invalid.
 * @throws SmackException.NotLoggedInException if we are not logged in
 * @throws IOException IO is dangerous
 * @throws MissingUserIdOnKeyException if the key that is to be imported is missing a user-id with our jid
 * @throws NoBackupFoundException if no secret key backup has been found
 * @throws PGPException in case the restored secret key is damaged.
 */
public OpenPgpV4Fingerprint restoreSecretKeyServerBackup(AskForBackupCodeCallback codeCallback) throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException, InvalidBackupCodeException, SmackException.NotLoggedInException, IOException, MissingUserIdOnKeyException, NoBackupFoundException, PGPException {
    throwIfNoProviderSet();
    throwIfNotAuthenticated();
    SecretkeyElement backup = OpenPgpPubSubUtil.fetchSecretKey(pepManager);
    if (backup == null) {
        throw new NoBackupFoundException();
    }
    OpenPgpSecretKeyBackupPassphrase backupCode = codeCallback.askForBackupCode();
    PGPSecretKeyRing secretKeys = SecretKeyBackupHelper.restoreSecretKeyBackup(backup, backupCode);
    OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint(secretKeys);
    provider.getStore().importSecretKey(getJidOrThrow(), secretKeys);
    provider.getStore().importPublicKey(getJidOrThrow(), KeyRingUtils.publicKeyRingFrom(secretKeys));
    getOpenPgpSelf().trust(fingerprint);
    return new OpenPgpV4Fingerprint(secretKeys);
}
Also used : SecretkeyElement(org.jivesoftware.smackx.ox.element.SecretkeyElement) NoBackupFoundException(org.jivesoftware.smackx.ox.exception.NoBackupFoundException) OpenPgpV4Fingerprint(org.pgpainless.key.OpenPgpV4Fingerprint) PGPSecretKeyRing(org.bouncycastle.openpgp.PGPSecretKeyRing)

Example 2 with SecretkeyElement

use of org.jivesoftware.smackx.ox.element.SecretkeyElement in project Smack by igniterealtime.

the class OpenPgpPubSubUtil method fetchSecretKey.

/**
 * Fetch the latest {@link SecretkeyElement} from the private backup node.
 *
 * @see <a href="https://xmpp.org/extensions/xep-0373.html#synchro-pep">
 *      XEP-0373 §5. Synchronizing the Secret Key with a Private PEP Node</a>
 *
 * @param pepManager the PEP manager.
 * @return the secret key node or null, if it doesn't exist.
 *
 * @throws InterruptedException if the thread gets interrupted
 * @throws PubSubException.NotALeafNodeException if there is an issue with the PubSub node
 * @throws XMPPException.XMPPErrorException if there is an XMPP protocol related issue
 * @throws SmackException.NotConnectedException if we are not connected
 * @throws SmackException.NoResponseException /watch?v=7U0FzQzJzyI
 */
public static SecretkeyElement fetchSecretKey(PepManager pepManager) throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException {
    PubSubManager pm = pepManager.getPepPubSubManager();
    LeafNode secretKeyNode = pm.getOrCreateLeafNode(PEP_NODE_SECRET_KEY);
    List<PayloadItem<SecretkeyElement>> list = secretKeyNode.getItems(1);
    if (list.size() == 0) {
        LOGGER.log(Level.INFO, "No secret key published!");
        return null;
    }
    SecretkeyElement secretkeyElement = list.get(0).getPayload();
    return secretkeyElement;
}
Also used : PubSubManager(org.jivesoftware.smackx.pubsub.PubSubManager) PayloadItem(org.jivesoftware.smackx.pubsub.PayloadItem) SecretkeyElement(org.jivesoftware.smackx.ox.element.SecretkeyElement) LeafNode(org.jivesoftware.smackx.pubsub.LeafNode)

Example 3 with SecretkeyElement

use of org.jivesoftware.smackx.ox.element.SecretkeyElement in project Smack by igniterealtime.

the class SecretKeyBackupHelper method createSecretkeyElement.

/**
 * Create a {@link SecretkeyElement} which contains the secret keys which are serialized in {@code keys} and is
 * symmetrically encrypted using the {@code backupCode}.
 *
 * @see <a href="https://xmpp.org/extensions/xep-0373.html#backup-encryption">
 *     XEP-0373 §5.4 Encrypting the Secret Key Backup</a>
 *
 * @param keys serialized OpenPGP secret keys in transferable key format
 * @param backupCode passphrase for symmetric encryption
 * @return {@link SecretkeyElement}
 *
 * @throws PGPException PGP is brittle
 * @throws IOException IO is dangerous
 */
public static SecretkeyElement createSecretkeyElement(byte[] keys, OpenPgpSecretKeyBackupPassphrase backupCode) throws PGPException, IOException {
    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()));
}
Also used : SecretkeyElement(org.jivesoftware.smackx.ox.element.SecretkeyElement) ByteArrayInputStream(java.io.ByteArrayInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) ByteArrayOutputStream(java.io.ByteArrayOutputStream) EncryptionOptions(org.pgpainless.encryption_signing.EncryptionOptions) EncryptionStream(org.pgpainless.encryption_signing.EncryptionStream)

Example 4 with SecretkeyElement

use of org.jivesoftware.smackx.ox.element.SecretkeyElement in project Smack by igniterealtime.

the class OpenPgpManager method backupSecretKeyToServer.

/**
 * Upload the encrypted secret key to a private PEP node.
 * The backup is encrypted using the provided secret key passphrase.
 *
 * @see <a href="https://xmpp.org/extensions/xep-0373.html#synchro-pep">XEP-0373 §5</a>
 *
 * @param selectKeyCallback callback, which will receive the users choice of which keys will be backed up.
 * @param passphrase secret key passphrase
 *
 * @throws InterruptedException if the thread is interrupted.
 * @throws PubSubException.NotALeafNodeException if the private node is not a {@link LeafNode}.
 * @throws XMPPException.XMPPErrorException in case of an XMPP protocol error.
 * @throws SmackException.NotConnectedException if we are not connected.
 * @throws SmackException.NoResponseException if the server doesn't respond.
 * @throws SmackException.NotLoggedInException if we are not logged in.
 * @throws IOException IO is dangerous.
 * @throws SmackException.FeatureNotSupportedException if the server doesn't support the PubSub whitelist access model.
 * @throws PGPException PGP is brittle
 * @throws MissingOpenPgpKeyException in case we have no OpenPGP key pair to back up.
 */
public void backupSecretKeyToServer(SecretKeyBackupSelectionCallback selectKeyCallback, OpenPgpSecretKeyBackupPassphrase passphrase) throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException, SmackException.NotLoggedInException, IOException, SmackException.FeatureNotSupportedException, PGPException, MissingOpenPgpKeyException {
    throwIfNoProviderSet();
    throwIfNotAuthenticated();
    BareJid ownJid = connection().getUser().asBareJid();
    PGPSecretKeyRingCollection secretKeyRings = provider.getStore().getSecretKeysOf(ownJid);
    Set<OpenPgpV4Fingerprint> availableKeyPairs = new HashSet<>();
    for (PGPSecretKeyRing ring : secretKeyRings) {
        availableKeyPairs.add(new OpenPgpV4Fingerprint(ring));
    }
    Set<OpenPgpV4Fingerprint> selectedKeyPairs = selectKeyCallback.selectKeysToBackup(availableKeyPairs);
    SecretkeyElement secretKey = SecretKeyBackupHelper.createSecretkeyElement(provider, ownJid, selectedKeyPairs, passphrase);
    OpenPgpPubSubUtil.depositSecretKey(connection(), secretKey);
}
Also used : SecretkeyElement(org.jivesoftware.smackx.ox.element.SecretkeyElement) EntityBareJid(org.jxmpp.jid.EntityBareJid) BareJid(org.jxmpp.jid.BareJid) PGPSecretKeyRingCollection(org.bouncycastle.openpgp.PGPSecretKeyRingCollection) OpenPgpV4Fingerprint(org.pgpainless.key.OpenPgpV4Fingerprint) PGPSecretKeyRing(org.bouncycastle.openpgp.PGPSecretKeyRing) HashSet(java.util.HashSet)

Example 5 with SecretkeyElement

use of org.jivesoftware.smackx.ox.element.SecretkeyElement in project Smack by igniterealtime.

the class SecretKeyBackupHelperTest method createAndDecryptSecretKeyElementTest.

@Test
public void createAndDecryptSecretKeyElementTest() throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, MissingUserIdOnKeyException, MissingOpenPgpKeyException, InvalidBackupCodeException {
    // Prepare store and provider and so on...
    FileBasedOpenPgpStore store = new FileBasedOpenPgpStore(basePath);
    PainlessOpenPgpProvider provider = new PainlessOpenPgpProvider(store);
    // Generate and import key
    PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("xmpp:alice@wonderland.lit");
    BareJid jid = JidCreate.bareFrom("alice@wonderland.lit");
    provider.getStore().importSecretKey(jid, secretKeys);
    // Create encrypted backup
    OpenPgpSecretKeyBackupPassphrase backupCode = SecretKeyBackupHelper.generateBackupPassword();
    SecretkeyElement element = SecretKeyBackupHelper.createSecretkeyElement(provider, jid, Collections.singleton(new OpenPgpV4Fingerprint(secretKeys)), backupCode);
    // Decrypt backup and compare
    PGPSecretKeyRing secretKeyRing = SecretKeyBackupHelper.restoreSecretKeyBackup(element, backupCode);
    Assertions.assertArrayEquals(secretKeys.getEncoded(), secretKeyRing.getEncoded());
}
Also used : SecretkeyElement(org.jivesoftware.smackx.ox.element.SecretkeyElement) FileBasedOpenPgpStore(org.jivesoftware.smackx.ox.store.filebased.FileBasedOpenPgpStore) BareJid(org.jxmpp.jid.BareJid) OpenPgpV4Fingerprint(org.pgpainless.key.OpenPgpV4Fingerprint) PGPSecretKeyRing(org.bouncycastle.openpgp.PGPSecretKeyRing) PainlessOpenPgpProvider(org.jivesoftware.smackx.ox.crypto.PainlessOpenPgpProvider) Test(org.junit.jupiter.api.Test)

Aggregations

SecretkeyElement (org.jivesoftware.smackx.ox.element.SecretkeyElement)6 PGPSecretKeyRing (org.bouncycastle.openpgp.PGPSecretKeyRing)3 OpenPgpV4Fingerprint (org.pgpainless.key.OpenPgpV4Fingerprint)3 Test (org.junit.jupiter.api.Test)2 BareJid (org.jxmpp.jid.BareJid)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 InputStream (java.io.InputStream)1 HashSet (java.util.HashSet)1 PGPSecretKeyRingCollection (org.bouncycastle.openpgp.PGPSecretKeyRingCollection)1 XmlPullParser (org.jivesoftware.smack.xml.XmlPullParser)1 PainlessOpenPgpProvider (org.jivesoftware.smackx.ox.crypto.PainlessOpenPgpProvider)1 NoBackupFoundException (org.jivesoftware.smackx.ox.exception.NoBackupFoundException)1 FileBasedOpenPgpStore (org.jivesoftware.smackx.ox.store.filebased.FileBasedOpenPgpStore)1 LeafNode (org.jivesoftware.smackx.pubsub.LeafNode)1 PayloadItem (org.jivesoftware.smackx.pubsub.PayloadItem)1 PubSubManager (org.jivesoftware.smackx.pubsub.PubSubManager)1 EntityBareJid (org.jxmpp.jid.EntityBareJid)1 EncryptionOptions (org.pgpainless.encryption_signing.EncryptionOptions)1 EncryptionStream (org.pgpainless.encryption_signing.EncryptionStream)1