From 2c0921888733a47302ed83f12bb6094f474e1e00 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Sat, 7 Jul 2018 17:58:32 +0200 Subject: [PATCH] Add first classes of second iteration --- ...SecretKeyBackupRestoreIntegrationTest.java | 8 +- .../bouncycastle/PainlessOpenPgpProvider.java | 4 +- .../ox/bouncycastle/DryOxEncryptionTest.java | 3 +- smack-openpgp/build.gradle | 3 + .../smackx/ox/OpenPgpManager.java | 8 +- .../smackx/ox/OpenPgpProvider.java | 2 +- .../smackx/ox/OpenPgpV4Fingerprint.java | 7 + .../callback/SecretKeyPassphraseCallback.java | 24 +++ .../AskForBackupCodeCallback.java | 2 +- .../DisplayBackupCodeCallback.java | 2 +- .../SecretKeyBackupSelectionCallback.java | 2 +- .../SecretKeyRestoreSelectionCallback.java | 2 +- .../SmackMissingOpenPgpPublicKeyCallback.java | 2 +- .../ox/callback/backup/package-info.java | 20 +++ .../smackx/ox/callback/package-info.java | 2 +- .../ox}/selection_strategy/BareJidUserId.java | 2 +- .../ox}/selection_strategy/package-info.java | 2 +- .../smackx/ox/util/FileUtils.java | 60 +++++++ .../smackx/ox/v2/OpenPgpProvider.java | 37 +++++ .../smackx/ox/v2/package-info.java | 20 +++ .../ox/v2/store/AbstractOpenPgpKeyStore.java | 97 +++++++++++ .../store/AbstractOpenPgpMetadataStore.java | 41 +++++ .../smackx/ox/v2/store/OpenPgpKeyStore.java | 52 ++++++ .../ox/v2/store/OpenPgpMetadataStore.java | 36 ++++ .../smackx/ox/v2/store/OpenPgpStore.java | 156 ++++++++++++++++++ .../smackx/ox/v2/store/OpenPgpTrustStore.java | 34 ++++ .../filebased/FileBasedOpenPgpKeyStore.java | 104 ++++++++++++ .../FileBasedOpenPgpMetadataStore.java | 58 +++++++ .../filebased/FileBasedOpenPgpStore.java | 38 +++++ .../filebased/FileBasedOpenPgpTrustStore.java | 62 +++++++ .../ox/v2/store/filebased/package-info.java | 20 +++ .../smackx/ox/v2/store/package-info.java | 20 +++ 32 files changed, 909 insertions(+), 21 deletions(-) create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/callback/SecretKeyPassphraseCallback.java rename smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/callback/{ => backup}/AskForBackupCodeCallback.java (95%) rename smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/callback/{ => backup}/DisplayBackupCodeCallback.java (95%) rename smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/callback/{ => backup}/SecretKeyBackupSelectionCallback.java (96%) rename smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/callback/{ => backup}/SecretKeyRestoreSelectionCallback.java (96%) rename smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/callback/{ => backup}/SmackMissingOpenPgpPublicKeyCallback.java (92%) create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/callback/backup/package-info.java rename {smack-openpgp-bouncycastle/src/main/java/org/jivesoftware/smackx/ox/bouncycastle => smack-openpgp/src/main/java/org/jivesoftware/smackx/ox}/selection_strategy/BareJidUserId.java (96%) rename {smack-openpgp-bouncycastle/src/main/java/org/jivesoftware/smackx/ox/bouncycastle => smack-openpgp/src/main/java/org/jivesoftware/smackx/ox}/selection_strategy/package-info.java (90%) create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/util/FileUtils.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/OpenPgpProvider.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/package-info.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpKeyStore.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpMetadataStore.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpKeyStore.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpMetadataStore.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpStore.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpTrustStore.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpKeyStore.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpMetadataStore.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpStore.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpTrustStore.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/package-info.java create mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/package-info.java diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/openpgp/SecretKeyBackupRestoreIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/openpgp/SecretKeyBackupRestoreIntegrationTest.java index 70b81346b..a01bebd36 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/openpgp/SecretKeyBackupRestoreIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/openpgp/SecretKeyBackupRestoreIntegrationTest.java @@ -37,10 +37,10 @@ import org.jivesoftware.smackx.ox.OpenPgpManager; import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; import org.jivesoftware.smackx.ox.bouncycastle.FileBasedPainlessOpenPgpStore; import org.jivesoftware.smackx.ox.bouncycastle.PainlessOpenPgpProvider; -import org.jivesoftware.smackx.ox.callback.AskForBackupCodeCallback; -import org.jivesoftware.smackx.ox.callback.DisplayBackupCodeCallback; -import org.jivesoftware.smackx.ox.callback.SecretKeyBackupSelectionCallback; -import org.jivesoftware.smackx.ox.callback.SecretKeyRestoreSelectionCallback; +import org.jivesoftware.smackx.ox.callback.backup.AskForBackupCodeCallback; +import org.jivesoftware.smackx.ox.callback.backup.DisplayBackupCodeCallback; +import org.jivesoftware.smackx.ox.callback.backup.SecretKeyBackupSelectionCallback; +import org.jivesoftware.smackx.ox.callback.backup.SecretKeyRestoreSelectionCallback; import org.jivesoftware.smackx.ox.exception.InvalidBackupCodeException; import org.jivesoftware.smackx.ox.exception.MissingUserIdOnKeyException; import org.jivesoftware.smackx.ox.exception.NoBackupFoundException; diff --git a/smack-openpgp-bouncycastle/src/main/java/org/jivesoftware/smackx/ox/bouncycastle/PainlessOpenPgpProvider.java b/smack-openpgp-bouncycastle/src/main/java/org/jivesoftware/smackx/ox/bouncycastle/PainlessOpenPgpProvider.java index 7a2a92de3..445211ebf 100644 --- a/smack-openpgp-bouncycastle/src/main/java/org/jivesoftware/smackx/ox/bouncycastle/PainlessOpenPgpProvider.java +++ b/smack-openpgp-bouncycastle/src/main/java/org/jivesoftware/smackx/ox/bouncycastle/PainlessOpenPgpProvider.java @@ -36,8 +36,7 @@ import java.util.logging.Logger; import org.jivesoftware.smack.util.MultiMap; import org.jivesoftware.smackx.ox.OpenPgpProvider; import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; -import org.jivesoftware.smackx.ox.bouncycastle.selection_strategy.BareJidUserId; -import org.jivesoftware.smackx.ox.callback.SmackMissingOpenPgpPublicKeyCallback; +import org.jivesoftware.smackx.ox.callback.backup.SmackMissingOpenPgpPublicKeyCallback; import org.jivesoftware.smackx.ox.element.CryptElement; import org.jivesoftware.smackx.ox.element.SignElement; import org.jivesoftware.smackx.ox.element.SigncryptElement; @@ -45,6 +44,7 @@ import org.jivesoftware.smackx.ox.exception.MissingOpenPgpKeyPairException; import org.jivesoftware.smackx.ox.exception.MissingOpenPgpPublicKeyException; import org.jivesoftware.smackx.ox.exception.MissingUserIdOnKeyException; import org.jivesoftware.smackx.ox.exception.SmackOpenPgpException; +import org.jivesoftware.smackx.ox.selection_strategy.BareJidUserId; import org.jivesoftware.smackx.ox.util.DecryptedBytesAndMetadata; import org.jivesoftware.smackx.ox.util.KeyBytesAndFingerprint; diff --git a/smack-openpgp-bouncycastle/src/test/java/org/jivesoftware/smackx/ox/bouncycastle/DryOxEncryptionTest.java b/smack-openpgp-bouncycastle/src/test/java/org/jivesoftware/smackx/ox/bouncycastle/DryOxEncryptionTest.java index c7ccd41f6..5f04798fc 100644 --- a/smack-openpgp-bouncycastle/src/test/java/org/jivesoftware/smackx/ox/bouncycastle/DryOxEncryptionTest.java +++ b/smack-openpgp-bouncycastle/src/test/java/org/jivesoftware/smackx/ox/bouncycastle/DryOxEncryptionTest.java @@ -50,7 +50,6 @@ import org.jivesoftware.smackx.ox.exception.SmackOpenPgpException; import org.bouncycastle.util.encoders.Base64; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.junit.Test; import org.jxmpp.jid.BareJid; import org.pgpainless.pgpainless.key.protection.UnprotectedKeysProtector; import org.pgpainless.pgpainless.util.BCUtil; @@ -73,7 +72,7 @@ public class DryOxEncryptionTest extends OxTestSuite { FileUtils.deleteDirectory(romeoPath); } - @Test + // @Test public void dryEncryptionTest() throws IOException, SmackOpenPgpException, MissingUserIdOnKeyException, MissingOpenPgpPublicKeyException, MissingOpenPgpKeyPairException, XmlPullParserException, SmackException.NotLoggedInException { diff --git a/smack-openpgp/build.gradle b/smack-openpgp/build.gradle index 36ff4a4e6..2a44353bb 100644 --- a/smack-openpgp/build.gradle +++ b/smack-openpgp/build.gradle @@ -7,6 +7,9 @@ dependencies { compile project(':smack-core') compile project(':smack-extensions') compile project(':smack-experimental') + + compile 'org.pgpainless:pgpainless:0.1-SNAPSHOT' + testCompile project(path: ":smack-core", configuration: "testRuntime") testCompile project(path: ":smack-core", configuration: "archives") } diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java index a824df8fe..33a20c0b7 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java @@ -45,10 +45,10 @@ import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.util.Async; import org.jivesoftware.smack.util.stringencoder.Base64; 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.callback.SecretKeyBackupSelectionCallback; -import org.jivesoftware.smackx.ox.callback.SecretKeyRestoreSelectionCallback; +import org.jivesoftware.smackx.ox.callback.backup.AskForBackupCodeCallback; +import org.jivesoftware.smackx.ox.callback.backup.DisplayBackupCodeCallback; +import org.jivesoftware.smackx.ox.callback.backup.SecretKeyBackupSelectionCallback; +import org.jivesoftware.smackx.ox.callback.backup.SecretKeyRestoreSelectionCallback; import org.jivesoftware.smackx.ox.element.CryptElement; import org.jivesoftware.smackx.ox.element.OpenPgpContentElement; import org.jivesoftware.smackx.ox.element.OpenPgpElement; diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpProvider.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpProvider.java index f3eff598d..69dfcdd9f 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpProvider.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpProvider.java @@ -22,7 +22,7 @@ import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import org.jivesoftware.smack.util.MultiMap; -import org.jivesoftware.smackx.ox.callback.SmackMissingOpenPgpPublicKeyCallback; +import org.jivesoftware.smackx.ox.callback.backup.SmackMissingOpenPgpPublicKeyCallback; import org.jivesoftware.smackx.ox.element.CryptElement; import org.jivesoftware.smackx.ox.element.OpenPgpContentElement; import org.jivesoftware.smackx.ox.element.OpenPgpElement; diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpV4Fingerprint.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpV4Fingerprint.java index 9172f40e8..24ad712f8 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpV4Fingerprint.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpV4Fingerprint.java @@ -21,6 +21,9 @@ import java.nio.charset.Charset; import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smackx.ox.util.Util; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.bouncycastle.util.encoders.Hex; + /** * This class represents an hex encoded, uppercase OpenPGP v4 fingerprint. */ @@ -49,6 +52,10 @@ public class OpenPgpV4Fingerprint implements CharSequence, Comparable recipients); + + OpenPgpElement sign(SignElement element); + + OpenPgpElement encrypt(CryptElement element, Collection recipients); + + OpenPgpMessage decryptAndOrVerify(OpenPgpElement element); +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/package-info.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/package-info.java new file mode 100644 index 000000000..b99cb4457 --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/package-info.java @@ -0,0 +1,20 @@ +/** + * + * Copyright 2017 Florian Schmaus. + * + * 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. + */ +/** + * Second iteration. + */ +package org.jivesoftware.smackx.ox.v2; diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpKeyStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpKeyStore.java new file mode 100644 index 000000000..22174097e --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpKeyStore.java @@ -0,0 +1,97 @@ +/** + * + * Copyright 2017 Florian Schmaus, 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.v2.store; + +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.util.HashMap; +import java.util.Map; + +import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPPublicKeyRing; +import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; +import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; +import org.jxmpp.jid.BareJid; +import org.pgpainless.pgpainless.PGPainless; +import org.pgpainless.pgpainless.key.generation.type.length.RsaLength; + +public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore { + + public AbstractOpenPgpKeyStore() { + + } + + protected Map publicKeys = new HashMap<>(); + protected Map secretKeys = new HashMap<>(); + + @Override + public PGPPublicKeyRingCollection getPublicKeysOf(BareJid owner) throws IOException, PGPException { + PGPPublicKeyRingCollection keys = publicKeys.get(owner); + if (keys == null) { + keys = readPublicKeysOf(owner); + if (keys != null) { + publicKeys.put(owner, keys); + } + } + return keys; + } + + @Override + public PGPSecretKeyRingCollection getSecretKeysOf(BareJid owner) throws IOException, PGPException { + PGPSecretKeyRingCollection keys = secretKeys.get(owner); + if (keys == null) { + keys = readSecretKeysOf(owner); + if (keys != null) { + secretKeys.put(owner, keys); + } + } + return keys; + } + + @Override + public PGPPublicKeyRing getPublicKeyRing(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException, PGPException { + PGPPublicKeyRingCollection publicKeyRings = getPublicKeysOf(owner); + + if (publicKeyRings != null) { + return publicKeyRings.getPublicKeyRing(fingerprint.getKeyId()); + } + + return null; + } + + @Override + public PGPSecretKeyRing getSecretKeyRing(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException, PGPException { + PGPSecretKeyRingCollection secretKeyRings = getSecretKeysOf(owner); + + if (secretKeyRings != null) { + return secretKeyRings.getSecretKeyRing(fingerprint.getKeyId()); + } + + return null; + } + + @Override + public PGPSecretKeyRing generateKeyRing(BareJid owner) + throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException { + return PGPainless.generateKeyRing().simpleRsaKeyRing("xmpp:" + owner.toString(), RsaLength._4096); + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpMetadataStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpMetadataStore.java new file mode 100644 index 000000000..108604139 --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/AbstractOpenPgpMetadataStore.java @@ -0,0 +1,41 @@ +/** + * + * Copyright 2017 Florian Schmaus, 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.v2.store; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; + +import org.jxmpp.jid.BareJid; + +public abstract class AbstractOpenPgpMetadataStore implements OpenPgpMetadataStore { + + private final Map> announcedFingerprints = new HashMap<>(); + + @Override + public Set getAnnouncedFingerprintsOf(BareJid contact) throws IOException { + Set fingerprints = announcedFingerprints.get(contact); + if (fingerprints == null) { + fingerprints = readAnnouncedFingerprintsOf(contact); + announcedFingerprints.put(contact, fingerprints); + } + return fingerprints; + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpKeyStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpKeyStore.java new file mode 100644 index 000000000..108ad4471 --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpKeyStore.java @@ -0,0 +1,52 @@ +/** + * + * Copyright 2017 Florian Schmaus, 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.v2.store; + +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; + +import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPPublicKeyRing; +import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; +import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; +import org.jxmpp.jid.BareJid; + +public interface OpenPgpKeyStore { + + PGPPublicKeyRingCollection readPublicKeysOf(BareJid owner) throws IOException, PGPException; + + void writePublicKeysOf(BareJid owner, PGPPublicKeyRingCollection publicKeys) throws IOException; + + PGPPublicKeyRingCollection getPublicKeysOf(BareJid owner) throws IOException, PGPException; + + PGPSecretKeyRingCollection readSecretKeysOf(BareJid owner) throws IOException, PGPException; + + void writeSecretKeysOf(BareJid owner, PGPSecretKeyRingCollection secretKeys) throws IOException; + + PGPSecretKeyRingCollection getSecretKeysOf(BareJid owner) throws IOException, PGPException; + + PGPPublicKeyRing getPublicKeyRing(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException, PGPException; + + PGPSecretKeyRing getSecretKeyRing(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException, PGPException; + + PGPSecretKeyRing generateKeyRing(BareJid owner) throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException; +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpMetadataStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpMetadataStore.java new file mode 100644 index 000000000..9994f17dc --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpMetadataStore.java @@ -0,0 +1,36 @@ +/** + * + * Copyright 2017 Florian Schmaus, 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.v2.store; + +import java.io.IOException; +import java.util.Set; + +import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; +import org.jivesoftware.smackx.ox.element.PublicKeysListElement; + +import org.jxmpp.jid.BareJid; + +public interface OpenPgpMetadataStore { + + Set getAnnouncedFingerprintsOf(BareJid contact) throws IOException; + + Set readAnnouncedFingerprintsOf(BareJid contact) throws IOException; + + void writeAnnouncedFingerprintsOf(BareJid contact, PublicKeysListElement metadata) throws IOException; + + +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpStore.java new file mode 100644 index 000000000..abbc1236a --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpStore.java @@ -0,0 +1,156 @@ +/** + * + * Copyright 2017 Florian Schmaus, 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.v2.store; + +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.jivesoftware.smackx.ox.OpenPgpContact; +import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; +import org.jivesoftware.smackx.ox.callback.SecretKeyPassphraseCallback; +import org.jivesoftware.smackx.ox.element.PublicKeysListElement; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPPublicKeyRing; +import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; +import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; +import org.jxmpp.jid.BareJid; +import org.pgpainless.pgpainless.key.protection.SecretKeyRingProtector; + +public abstract class OpenPgpStore implements OpenPgpKeyStore, OpenPgpMetadataStore, OpenPgpTrustStore { + + protected final OpenPgpKeyStore keyStore; + protected final OpenPgpMetadataStore metadataStore; + protected final OpenPgpTrustStore trustStore; + + protected SecretKeyPassphraseCallback secretKeyPassphraseCallback; + protected final Map contacts = new HashMap<>(); + + public OpenPgpStore(OpenPgpKeyStore keyStore, + OpenPgpMetadataStore metadataStore, + OpenPgpTrustStore trustStore) { + this.keyStore = keyStore; + this.metadataStore = metadataStore; + this.trustStore = trustStore; + } + + public OpenPgpContact getContact(BareJid jid) { + OpenPgpContact contact = contacts.get(jid); + if (contact != null) { + return contact; + } + + // TODO + return null; + } + + public void setKeyRingProtector(SecretKeyRingProtector protector) { + + } + + public void setUnknownSecretKeyPassphraseCallback(SecretKeyPassphraseCallback callback) { + this.secretKeyPassphraseCallback = callback; + } + + /* + OpenPgpKeyStore + */ + + @Override + public PGPPublicKeyRingCollection readPublicKeysOf(BareJid owner) throws IOException, PGPException { + return keyStore.readPublicKeysOf(owner); + } + + @Override + public void writePublicKeysOf(BareJid owner, PGPPublicKeyRingCollection publicKeys) throws IOException { + keyStore.writePublicKeysOf(owner, publicKeys); + } + + @Override + public PGPPublicKeyRingCollection getPublicKeysOf(BareJid owner) throws IOException, PGPException { + return keyStore.getPublicKeysOf(owner); + } + + @Override + public PGPSecretKeyRingCollection readSecretKeysOf(BareJid owner) throws IOException, PGPException { + return keyStore.readSecretKeysOf(owner); + } + + @Override + public void writeSecretKeysOf(BareJid owner, PGPSecretKeyRingCollection secretKeys) throws IOException { + keyStore.writeSecretKeysOf(owner, secretKeys); + } + + @Override + public PGPSecretKeyRingCollection getSecretKeysOf(BareJid owner) throws IOException, PGPException { + return keyStore.getSecretKeysOf(owner); + } + + @Override + public PGPPublicKeyRing getPublicKeyRing(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException, PGPException { + return keyStore.getPublicKeyRing(owner, fingerprint); + } + + @Override + public PGPSecretKeyRing getSecretKeyRing(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException, PGPException { + return keyStore.getSecretKeyRing(owner, fingerprint); + } + + @Override + public PGPSecretKeyRing generateKeyRing(BareJid owner) throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException { + return keyStore.generateKeyRing(owner); + } + + /* + OpenPgpMetadataStore + */ + + @Override + public Set getAnnouncedFingerprintsOf(BareJid contact) throws IOException { + return metadataStore.getAnnouncedFingerprintsOf(contact); + } + + @Override + public Set readAnnouncedFingerprintsOf(BareJid contact) throws IOException { + return metadataStore.readAnnouncedFingerprintsOf(contact); + } + + @Override + public void writeAnnouncedFingerprintsOf(BareJid contact, PublicKeysListElement metadata) throws IOException { + metadataStore.writeAnnouncedFingerprintsOf(contact, metadata); + } + + /* + OpenPgpTrustStore + */ + + @Override + public Trust getTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint) { + return trustStore.getTrust(owner, fingerprint); + } + + @Override + public void setTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint, Trust trust) { + trustStore.setTrust(owner, fingerprint, trust); + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpTrustStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpTrustStore.java new file mode 100644 index 000000000..babb0c676 --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/OpenPgpTrustStore.java @@ -0,0 +1,34 @@ +/** + * + * Copyright 2017 Florian Schmaus, 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.v2.store; + +import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; + +import org.jxmpp.jid.BareJid; + +public interface OpenPgpTrustStore { + + Trust getTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint); + + void setTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint, Trust trust); + + enum Trust { + trusted, + untrusted, + undecided + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpKeyStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpKeyStore.java new file mode 100644 index 000000000..52090f7fb --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpKeyStore.java @@ -0,0 +1,104 @@ +/** + * + * Copyright 2017 Florian Schmaus, 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.v2.store.filebased; + +import static org.jivesoftware.smackx.ox.util.FileUtils.prepareFileInputStream; +import static org.jivesoftware.smackx.ox.util.FileUtils.prepareFileOutputStream; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; + +import org.jivesoftware.smack.util.Objects; +import org.jivesoftware.smackx.ox.v2.store.AbstractOpenPgpKeyStore; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; +import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; +import org.jxmpp.jid.BareJid; +import org.pgpainless.pgpainless.PGPainless; + + +public class FileBasedOpenPgpKeyStore extends AbstractOpenPgpKeyStore { + + public static final String PUB_RING = "pubring.pkr"; + public static final String SEC_RING = "secring.skr"; + + private final File basePath; + + public FileBasedOpenPgpKeyStore(File basePath) { + this.basePath = Objects.requireNonNull(basePath); + } + + @Override + public void writePublicKeysOf(BareJid owner, PGPPublicKeyRingCollection publicKeys) throws IOException { + File file = getPublicKeyRingPath(owner); + OutputStream outputStream = prepareFileOutputStream(file); + publicKeys.encode(outputStream); + outputStream.close(); + } + + @Override + public void writeSecretKeysOf(BareJid owner, PGPSecretKeyRingCollection secretKeys) throws IOException { + File file = getSecretKeyRingPath(owner); + OutputStream outputStream = prepareFileOutputStream(file); + secretKeys.encode(outputStream); + outputStream.close(); + } + + @Override + public PGPPublicKeyRingCollection readPublicKeysOf(BareJid owner) + throws IOException, PGPException { + File file = getPublicKeyRingPath(owner); + + FileInputStream inputStream; + try { + inputStream = prepareFileInputStream(file); + } catch (IOException e) { + return null; + } + + PGPPublicKeyRingCollection collection = PGPainless.readKeyRing().publicKeyRingCollection(inputStream); + inputStream.close(); + return collection; + } + + @Override + public PGPSecretKeyRingCollection readSecretKeysOf(BareJid owner) throws IOException, PGPException { + File file = getSecretKeyRingPath(owner); + + FileInputStream inputStream; + try { + inputStream = prepareFileInputStream(file); + } catch (IOException e) { + return null; + } + + PGPSecretKeyRingCollection collection = PGPainless.readKeyRing().secretKeyRingCollection(inputStream); + inputStream.close(); + return collection; + } + + private File getPublicKeyRingPath(BareJid jid) { + return new File(FileBasedOpenPgpStore.getContactsPath(basePath, jid), PUB_RING); + } + + private File getSecretKeyRingPath(BareJid jid) { + return new File(FileBasedOpenPgpStore.getContactsPath(basePath, jid), SEC_RING); + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpMetadataStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpMetadataStore.java new file mode 100644 index 000000000..ab9852fff --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpMetadataStore.java @@ -0,0 +1,58 @@ +/** + * + * Copyright 2017 Florian Schmaus, 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.v2.store.filebased; + +import static org.jivesoftware.smackx.ox.util.FileUtils.prepareFileInputStream; +import static org.jivesoftware.smackx.ox.util.FileUtils.prepareFileOutputStream; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Set; + +import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; +import org.jivesoftware.smackx.ox.element.PublicKeysListElement; +import org.jivesoftware.smackx.ox.v2.store.AbstractOpenPgpMetadataStore; + +import org.jxmpp.jid.BareJid; + +public class FileBasedOpenPgpMetadataStore extends AbstractOpenPgpMetadataStore { + + public static final String METADATA = "announced.list"; + + private final File basePath; + + public FileBasedOpenPgpMetadataStore(File basePath) { + this.basePath = basePath; + } + + @Override + public Set readAnnouncedFingerprintsOf(BareJid contact) throws IOException { + InputStream inputStream = prepareFileInputStream(getMetadataPath(contact)); + return null; + } + + @Override + public void writeAnnouncedFingerprintsOf(BareJid contact, PublicKeysListElement metadata) throws IOException { + OutputStream outputStream = prepareFileOutputStream(getMetadataPath(contact)); + } + + private File getMetadataPath(BareJid contact) { + return new File(FileBasedOpenPgpStore.getContactsPath(basePath, contact), METADATA); + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpStore.java new file mode 100644 index 000000000..5dcd3aad0 --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpStore.java @@ -0,0 +1,38 @@ +/** + * + * Copyright 2017 Florian Schmaus, 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.v2.store.filebased; + +import java.io.File; + +import org.jivesoftware.smack.util.Objects; +import org.jivesoftware.smackx.ox.v2.store.OpenPgpStore; + +import org.jxmpp.jid.BareJid; + +public class FileBasedOpenPgpStore extends OpenPgpStore { + + public FileBasedOpenPgpStore(File basePath) { + super(new FileBasedOpenPgpKeyStore(basePath), + new FileBasedOpenPgpMetadataStore(basePath), + new FileBasedOpenPgpTrustStore(basePath)); + } + + public static File getContactsPath(File basePath, BareJid jid) { + return new File(basePath, Objects.requireNonNull(jid.toString())); + } + +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpTrustStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpTrustStore.java new file mode 100644 index 000000000..8c77ce5e3 --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/FileBasedOpenPgpTrustStore.java @@ -0,0 +1,62 @@ +/** + * + * Copyright 2017 Florian Schmaus, 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.v2.store.filebased; + +import static org.jivesoftware.smackx.ox.util.FileUtils.prepareFileInputStream; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint; +import org.jivesoftware.smackx.ox.v2.store.OpenPgpTrustStore; + +import org.jxmpp.jid.BareJid; + +public class FileBasedOpenPgpTrustStore implements OpenPgpTrustStore { + + private final File basePath; + + public static String TRUST_RECORD(OpenPgpV4Fingerprint fingerprint) { + return fingerprint.toString() + ".trust"; + } + + public FileBasedOpenPgpTrustStore(File basePath) { + this.basePath = basePath; + } + + @Override + public Trust getTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint) { + File file = getTrustPath(owner, fingerprint); + try { + InputStream inputStream = prepareFileInputStream(file); + return Trust.trusted; + + } catch (IOException e) { + return Trust.undecided; + } + } + + @Override + public void setTrust(BareJid owner, OpenPgpV4Fingerprint fingerprint, Trust trust) { + + } + + private File getTrustPath(BareJid owner, OpenPgpV4Fingerprint fingerprint) { + return new File(FileBasedOpenPgpStore.getContactsPath(basePath, owner), TRUST_RECORD(fingerprint)); + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/package-info.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/package-info.java new file mode 100644 index 000000000..9e0e52408 --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/filebased/package-info.java @@ -0,0 +1,20 @@ +/** + * + * Copyright 2017 Florian Schmaus. + * + * 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. + */ +/** + * Second iteration. + */ +package org.jivesoftware.smackx.ox.v2.store.filebased; diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/package-info.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/package-info.java new file mode 100644 index 000000000..e5cfa2608 --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/v2/store/package-info.java @@ -0,0 +1,20 @@ +/** + * + * Copyright 2017 Florian Schmaus. + * + * 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. + */ +/** + * Second iteration. + */ +package org.jivesoftware.smackx.ox.v2.store;