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