Implement restoring secret key

This commit is contained in:
Paul Schaub 2018-05-23 15:21:10 +02:00
parent 878ac56ed0
commit 653f318d37
3 changed files with 61 additions and 2 deletions

View File

@ -42,6 +42,7 @@ import org.jivesoftware.smackx.ox.element.SigncryptElement;
import org.jivesoftware.smackx.ox.exception.CorruptedOpenPgpKeyException;
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.BouncyGPG;
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.algorithms.PGPHashAlgorithms;
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.algorithms.PGPSymmetricEncryptionAlgorithms;
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.algorithms.PublicKeySize;
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.KeyringConfigCallbacks;
@ -52,13 +53,16 @@ import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.Keyring
import org.bouncycastle.bcpg.HashAlgorithmTags;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPKeyRingGenerator;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor;
import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
import org.bouncycastle.openpgp.operator.PGPDigestCalculatorProvider;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.io.Streams;
@ -67,8 +71,8 @@ import org.jxmpp.jid.BareJid;
public class BouncyCastleOpenPgpProvider implements OpenPgpProvider {
private final BareJid ourJid;
private final InMemoryKeyring ourKeys;
private final Long ourKeyId;
private InMemoryKeyring ourKeys;
private Long ourKeyId;
private final Map<BareJid, InMemoryKeyring> theirKeys = new HashMap<>();
public BouncyCastleOpenPgpProvider(BareJid ourJid) throws IOException, PGPException, NoSuchAlgorithmException {
@ -146,6 +150,44 @@ public class BouncyCastleOpenPgpProvider implements OpenPgpProvider {
}
@Override
public void restoreSecretKeyElement(SecretkeyElement secretkeyElement, String password)
throws CorruptedOpenPgpKeyException {
byte[] encoded = Base64.decode(secretkeyElement.getB64Data());
try {
PGPDigestCalculatorProvider calculatorProvider = new JcaPGPDigestCalculatorProviderBuilder()
.setProvider(BouncyGPG.getProvider())
.build();
InMemoryKeyring keyring = KeyringConfigs.forGpgExportedKeys(
KeyringConfigCallbacks.withPassword(password));
keyring.addSecretKey(encoded);
for (PGPSecretKeyRing r : keyring.getSecretKeyRings()) {
PGPSecretKey s = r.getSecretKey();
PGPPrivateKey privateKey = s.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder(calculatorProvider).build(password.toCharArray()));
PGPPublicKey publicKey = s.getPublicKey();
PGPSecretKey secretKey = new PGPSecretKey(
privateKey,
publicKey,
calculatorProvider.get(PGPHashAlgorithms.SHA1.getAlgorithmId()),
true,
null);
InMemoryKeyring newKeyring = KeyringConfigs.forGpgExportedKeys(
KeyringConfigCallbacks.withUnprotectedKeys());
newKeyring.addSecretKey(secretKey.getEncoded());
newKeyring.addPublicKey(secretKey.getPublicKey().getEncoded());
ourKeys = newKeyring;
ourKeyId = secretKey.getKeyID();
}
} catch (PGPException | IOException e) {
e.printStackTrace();
}
}
@Override
public OpenPgpElement signAndEncrypt(SigncryptElement element, Set<BareJid> recipients)
throws Exception {

View File

@ -31,6 +31,7 @@ import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.util.Async;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.ox.callback.AskForBackupCodeCallback;
import org.jivesoftware.smackx.ox.callback.DisplayBackupCodeCallback;
import org.jivesoftware.smackx.ox.element.PubkeyElement;
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
@ -296,6 +297,20 @@ public final class OpenPgpManager extends Manager {
callback.displayBackupCode(password);
}
public void fetchSecretKey(AskForBackupCodeCallback callback)
throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, SmackException.NoResponseException, CorruptedOpenPgpKeyException {
PubSubManager pm = PubSubManager.getInstance(connection());
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;
}
SecretkeyElement secretkeyElement = list.get(0).getPayload();
provider.restoreSecretKeyElement(secretkeyElement, callback.askForBackupCode());
}
/**
* Return the upper-case hex encoded OpenPGP v4 fingerprint of our key pair.
*

View File

@ -154,4 +154,6 @@ public interface OpenPgpProvider {
String getFingerprint() throws CorruptedOpenPgpKeyException;
SecretkeyElement createSecretkeyElement(String password) throws CorruptedOpenPgpKeyException;
void restoreSecretKeyElement(SecretkeyElement secretkeyElement, String password) throws CorruptedOpenPgpKeyException;
}