mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-24 04:52:05 +01:00
Temp commit
This commit is contained in:
parent
6e7145801e
commit
a234760233
14 changed files with 258 additions and 82 deletions
|
@ -1,3 +1,19 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.bouncycastle;
|
package org.jivesoftware.smackx.ox.bouncycastle;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.jivesoftware.smackx.ox.OpenPgpMessage;
|
||||||
import org.jivesoftware.smackx.ox.OpenPgpProvider;
|
import org.jivesoftware.smackx.ox.OpenPgpProvider;
|
||||||
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
||||||
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
||||||
|
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
||||||
|
|
||||||
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.BouncyGPG;
|
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.BouncyGPG;
|
||||||
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.algorithms.PublicKeySize;
|
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.algorithms.PublicKeySize;
|
||||||
|
@ -50,14 +51,14 @@ import org.bouncycastle.util.encoders.Hex;
|
||||||
import org.bouncycastle.util.io.Streams;
|
import org.bouncycastle.util.io.Streams;
|
||||||
import org.jxmpp.jid.BareJid;
|
import org.jxmpp.jid.BareJid;
|
||||||
|
|
||||||
public class BouncycastleOpenPgpProvider implements OpenPgpProvider {
|
public class BouncyCastleOpenPgpProvider implements OpenPgpProvider {
|
||||||
|
|
||||||
private final BareJid ourJid;
|
private final BareJid ourJid;
|
||||||
private final InMemoryKeyring ourKeys;
|
private final InMemoryKeyring ourKeys;
|
||||||
private final Long ourKeyId;
|
private final Long ourKeyId;
|
||||||
private final Map<BareJid, InMemoryKeyring> theirKeys = new HashMap<>();
|
private final Map<BareJid, InMemoryKeyring> theirKeys = new HashMap<>();
|
||||||
|
|
||||||
public BouncycastleOpenPgpProvider(BareJid ourJid) throws IOException, PGPException, NoSuchAlgorithmException {
|
public BouncyCastleOpenPgpProvider(BareJid ourJid) throws IOException, PGPException, NoSuchAlgorithmException {
|
||||||
this.ourJid = ourJid;
|
this.ourJid = ourJid;
|
||||||
PGPSecretKeyRing ourKey = generateKey(ourJid).generateSecretKeyRing();
|
PGPSecretKeyRing ourKey = generateKey(ourJid).generateSecretKeyRing();
|
||||||
ourKeyId = ourKey.getPublicKey().getKeyID();
|
ourKeyId = ourKey.getPublicKey().getKeyID();
|
||||||
|
@ -87,6 +88,11 @@ public class BouncycastleOpenPgpProvider implements OpenPgpProvider {
|
||||||
contactsKeyring.addPublicKey(decoded);
|
contactsKeyring.addPublicKey(decoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processPublicKeysListElement(PublicKeysListElement listElement, BareJid from) throws Exception {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OpenPgpElement signAndEncrypt(InputStream inputStream, Set<BareJid> recipients)
|
public OpenPgpElement signAndEncrypt(InputStream inputStream, Set<BareJid> recipients)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
@ -138,6 +144,16 @@ public class BouncycastleOpenPgpProvider implements OpenPgpProvider {
|
||||||
return new OpenPgpElement(base64);
|
return new OpenPgpElement(base64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OpenPgpElement sign(InputStream inputStream) throws Exception {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OpenPgpElement encrypt(InputStream inputStream, Set<BareJid> recipients) throws Exception {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OpenPgpMessage decryptAndVerify(OpenPgpElement element, BareJid sender) throws Exception {
|
public OpenPgpMessage decryptAndVerify(OpenPgpElement element, BareJid sender) throws Exception {
|
||||||
InMemoryKeyring decryptionConfig = KeyringConfigs.forGpgExportedKeys(KeyringConfigCallbacks.withUnprotectedKeys());
|
InMemoryKeyring decryptionConfig = KeyringConfigs.forGpgExportedKeys(KeyringConfigCallbacks.withUnprotectedKeys());
|
||||||
|
@ -168,7 +184,7 @@ public class BouncycastleOpenPgpProvider implements OpenPgpProvider {
|
||||||
|
|
||||||
Streams.pipeAll(decrypted, decryptedOut);
|
Streams.pipeAll(decrypted, decryptedOut);
|
||||||
|
|
||||||
return new OpenPgpMessage(null, new String(decryptedOut.toByteArray(), Charset.forName("UTF-8")));
|
return new OpenPgpMessage(new String(decryptedOut.toByteArray(), Charset.forName("UTF-8")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
|
@ -1,3 +1,19 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.bouncycastle;
|
package org.jivesoftware.smackx.ox.bouncycastle;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
|
@ -56,6 +72,10 @@ public class FileBasedBouncyCastleIdentityStore implements BouncyCastleIdentityS
|
||||||
public PublicKeysListElement loadPubkeyList(BareJid jid) throws IOException {
|
public PublicKeysListElement loadPubkeyList(BareJid jid) throws IOException {
|
||||||
File contactsDir = contactsDir(jid);
|
File contactsDir = contactsDir(jid);
|
||||||
File source = new File(contactsDir, "pubkey_list");
|
File source = new File(contactsDir, "pubkey_list");
|
||||||
|
if (!source.exists()) {
|
||||||
|
LOGGER.log(Level.FINE, "File " + source.getAbsolutePath() + " does not exist. Returning null.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
DataInputStream dataIn = new DataInputStream(new FileInputStream(source));
|
DataInputStream dataIn = new DataInputStream(new FileInputStream(source));
|
||||||
|
|
||||||
PublicKeysListElement.Builder builder = PublicKeysListElement.builder();
|
PublicKeysListElement.Builder builder = PublicKeysListElement.builder();
|
||||||
|
|
|
@ -116,8 +116,8 @@ public class BasicEncryptionTest extends SmackTestSuite {
|
||||||
throws IOException, PGPException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException {
|
throws IOException, PGPException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException {
|
||||||
final String alice = "alice@wonderland.lit";
|
final String alice = "alice@wonderland.lit";
|
||||||
final String bob = "bob@builder.tv";
|
final String bob = "bob@builder.tv";
|
||||||
PGPKeyRingGenerator g1 = BouncycastleOpenPgpProvider.generateKey(JidCreate.bareFrom(alice));
|
PGPKeyRingGenerator g1 = BouncyCastleOpenPgpProvider.generateKey(JidCreate.bareFrom(alice));
|
||||||
PGPKeyRingGenerator g2 = BouncycastleOpenPgpProvider.generateKey(JidCreate.bareFrom(bob));
|
PGPKeyRingGenerator g2 = BouncyCastleOpenPgpProvider.generateKey(JidCreate.bareFrom(bob));
|
||||||
PGPSecretKey s1 = g1.generateSecretKeyRing().getSecretKey();
|
PGPSecretKey s1 = g1.generateSecretKeyRing().getSecretKey();
|
||||||
PGPSecretKey s2 = g2.generateSecretKeyRing().getSecretKey();
|
PGPSecretKey s2 = g2.generateSecretKeyRing().getSecretKey();
|
||||||
PGPPublicKey p1 = g1.generatePublicKeyRing().getPublicKey();
|
PGPPublicKey p1 = g1.generatePublicKeyRing().getPublicKey();
|
||||||
|
|
|
@ -37,7 +37,7 @@ import org.jxmpp.jid.BareJid;
|
||||||
import org.jxmpp.jid.Jid;
|
import org.jxmpp.jid.Jid;
|
||||||
import org.jxmpp.jid.impl.JidCreate;
|
import org.jxmpp.jid.impl.JidCreate;
|
||||||
|
|
||||||
public class BouncycastleOpenPgpProviderTest extends SmackTestSuite {
|
public class BouncyCastleOpenPgpProviderTest extends SmackTestSuite {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void encryptAndSign_decryptAndVerifyElementTest() throws Exception {
|
public void encryptAndSign_decryptAndVerifyElementTest() throws Exception {
|
||||||
|
@ -46,8 +46,8 @@ public class BouncycastleOpenPgpProviderTest extends SmackTestSuite {
|
||||||
// Create providers for alice and the cat
|
// Create providers for alice and the cat
|
||||||
BareJid alice = JidCreate.bareFrom("alice@wonderland.lit");
|
BareJid alice = JidCreate.bareFrom("alice@wonderland.lit");
|
||||||
BareJid cheshire = JidCreate.bareFrom("cheshire@wonderland.lit");
|
BareJid cheshire = JidCreate.bareFrom("cheshire@wonderland.lit");
|
||||||
BouncycastleOpenPgpProvider aliceProvider = new BouncycastleOpenPgpProvider(alice);
|
BouncyCastleOpenPgpProvider aliceProvider = new BouncyCastleOpenPgpProvider(alice);
|
||||||
BouncycastleOpenPgpProvider cheshireProvider = new BouncycastleOpenPgpProvider(cheshire);
|
BouncyCastleOpenPgpProvider cheshireProvider = new BouncyCastleOpenPgpProvider(cheshire);
|
||||||
|
|
||||||
// dry exchange keys
|
// dry exchange keys
|
||||||
PubkeyElement aliceKeys = aliceProvider.createPubkeyElement();
|
PubkeyElement aliceKeys = aliceProvider.createPubkeyElement();
|
|
@ -1,14 +1,31 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.bouncycastle;
|
package org.jivesoftware.smackx.ox.bouncycastle;
|
||||||
|
|
||||||
import static junit.framework.TestCase.assertEquals;
|
import static junit.framework.TestCase.assertEquals;
|
||||||
|
import static junit.framework.TestCase.assertNull;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
import org.jivesoftware.smack.test.util.SmackTestSuite;
|
import org.jivesoftware.smack.test.util.SmackTestSuite;
|
||||||
|
import org.jivesoftware.smack.util.FileUtils;
|
||||||
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
@ -34,36 +51,6 @@ public class FileBasedBouncyCastleIdentityStoreTest extends SmackTestSuite {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
|
||||||
public void before() {
|
|
||||||
deleteStore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void after() {
|
|
||||||
deleteStore();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteStore() {
|
|
||||||
File[] currList;
|
|
||||||
Stack<File> stack = new Stack<>();
|
|
||||||
stack.push(storePath);
|
|
||||||
while (!stack.isEmpty()) {
|
|
||||||
if (stack.lastElement().isDirectory()) {
|
|
||||||
currList = stack.lastElement().listFiles();
|
|
||||||
if (currList != null && currList.length > 0) {
|
|
||||||
for (File curr : currList) {
|
|
||||||
stack.push(curr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
stack.pop().delete();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
stack.pop().delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void writeReadPublicKeysLists() throws ParseException, IOException {
|
public void writeReadPublicKeysLists() throws ParseException, IOException {
|
||||||
BareJid jid = JidCreate.bareFrom("edward@snowden.org");
|
BareJid jid = JidCreate.bareFrom("edward@snowden.org");
|
||||||
|
@ -78,9 +65,26 @@ public class FileBasedBouncyCastleIdentityStoreTest extends SmackTestSuite {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
FileBasedBouncyCastleIdentityStore store = new FileBasedBouncyCastleIdentityStore(storePath);
|
FileBasedBouncyCastleIdentityStore store = new FileBasedBouncyCastleIdentityStore(storePath);
|
||||||
|
|
||||||
|
PublicKeysListElement shouldBeNull = store.loadPubkeyList(jid);
|
||||||
|
assertNull(shouldBeNull);
|
||||||
store.storePubkeyList(jid, list);
|
store.storePubkeyList(jid, list);
|
||||||
|
|
||||||
PublicKeysListElement retrieved = store.loadPubkeyList(jid);
|
PublicKeysListElement retrieved = store.loadPubkeyList(jid);
|
||||||
assertEquals(list.getMetadata(), retrieved.getMetadata());
|
assertEquals(list.getMetadata(), retrieved.getMetadata());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() {
|
||||||
|
deleteStore();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void after() {
|
||||||
|
deleteStore();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteStore() {
|
||||||
|
FileUtils.deleteDirectory(storePath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ public class KeyGenerationTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createSecretKey() throws Exception {
|
public void createSecretKey() throws Exception {
|
||||||
PGPSecretKey secretKey = BouncycastleOpenPgpProvider
|
PGPSecretKey secretKey = BouncyCastleOpenPgpProvider
|
||||||
.generateKey(JidCreate.bareFrom("alice@wonderland.lit"))
|
.generateKey(JidCreate.bareFrom("alice@wonderland.lit"))
|
||||||
.generateSecretKeyRing()
|
.generateSecretKeyRing()
|
||||||
.getSecretKey();
|
.getSecretKey();
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
public class CorruptedOpenPgpKeyException extends Exception {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public CorruptedOpenPgpKeyException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,12 +20,15 @@ import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.jivesoftware.smack.Manager;
|
import org.jivesoftware.smack.Manager;
|
||||||
import org.jivesoftware.smack.SmackException;
|
import org.jivesoftware.smack.SmackException;
|
||||||
import org.jivesoftware.smack.XMPPConnection;
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
import org.jivesoftware.smack.XMPPException;
|
import org.jivesoftware.smack.XMPPException;
|
||||||
import org.jivesoftware.smack.packet.Message;
|
import org.jivesoftware.smack.packet.Message;
|
||||||
|
import org.jivesoftware.smack.util.Async;
|
||||||
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||||
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
||||||
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
||||||
|
@ -33,6 +36,7 @@ import org.jivesoftware.smackx.pep.PEPListener;
|
||||||
import org.jivesoftware.smackx.pep.PEPManager;
|
import org.jivesoftware.smackx.pep.PEPManager;
|
||||||
import org.jivesoftware.smackx.pubsub.EventElement;
|
import org.jivesoftware.smackx.pubsub.EventElement;
|
||||||
import org.jivesoftware.smackx.pubsub.Item;
|
import org.jivesoftware.smackx.pubsub.Item;
|
||||||
|
import org.jivesoftware.smackx.pubsub.ItemsExtension;
|
||||||
import org.jivesoftware.smackx.pubsub.LeafNode;
|
import org.jivesoftware.smackx.pubsub.LeafNode;
|
||||||
import org.jivesoftware.smackx.pubsub.PayloadItem;
|
import org.jivesoftware.smackx.pubsub.PayloadItem;
|
||||||
import org.jivesoftware.smackx.pubsub.PubSubException;
|
import org.jivesoftware.smackx.pubsub.PubSubException;
|
||||||
|
@ -41,7 +45,9 @@ import org.jivesoftware.smackx.pubsub.PubSubManager;
|
||||||
import org.jxmpp.jid.BareJid;
|
import org.jxmpp.jid.BareJid;
|
||||||
import org.jxmpp.jid.EntityBareJid;
|
import org.jxmpp.jid.EntityBareJid;
|
||||||
|
|
||||||
public final class OpenPgpManager extends Manager implements PEPListener {
|
public final class OpenPgpManager extends Manager {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(OpenPgpManager.class.getName());
|
||||||
|
|
||||||
public static final String PEP_NODE_PUBLIC_KEYS = "urn:xmpp:openpgp:0:public-keys";
|
public static final String PEP_NODE_PUBLIC_KEYS = "urn:xmpp:openpgp:0:public-keys";
|
||||||
public static final String PEP_NODE_PUBLIC_KEYS_NOTIFY = PEP_NODE_PUBLIC_KEYS + "+notify";
|
public static final String PEP_NODE_PUBLIC_KEYS_NOTIFY = PEP_NODE_PUBLIC_KEYS + "+notify";
|
||||||
|
@ -57,7 +63,7 @@ public final class OpenPgpManager extends Manager implements PEPListener {
|
||||||
super(connection);
|
super(connection);
|
||||||
|
|
||||||
// Subscribe to public key changes
|
// Subscribe to public key changes
|
||||||
PEPManager.getInstanceFor(connection()).addPEPListener(this);
|
PEPManager.getInstanceFor(connection()).addPEPListener(metadataListener);
|
||||||
ServiceDiscoveryManager.getInstanceFor(connection())
|
ServiceDiscoveryManager.getInstanceFor(connection())
|
||||||
.addFeature(PEP_NODE_PUBLIC_KEYS_NOTIFY);
|
.addFeature(PEP_NODE_PUBLIC_KEYS_NOTIFY);
|
||||||
}
|
}
|
||||||
|
@ -73,7 +79,6 @@ public final class OpenPgpManager extends Manager implements PEPListener {
|
||||||
|
|
||||||
public void setOpenPgpProvider(OpenPgpProvider provider) {
|
public void setOpenPgpProvider(OpenPgpProvider provider) {
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void publishPublicKey() throws Exception {
|
public void publishPublicKey() throws Exception {
|
||||||
|
@ -89,6 +94,7 @@ public final class OpenPgpManager extends Manager implements PEPListener {
|
||||||
LeafNode keyNode = pm.getOrCreateLeafNode(keyNodeName);
|
LeafNode keyNode = pm.getOrCreateLeafNode(keyNodeName);
|
||||||
List<Item> items = keyNode.getItems(1);
|
List<Item> items = keyNode.getItems(1);
|
||||||
if (items.isEmpty()) {
|
if (items.isEmpty()) {
|
||||||
|
LOGGER.log(Level.FINE, "Node " + keyNodeName + " is empty. Publish.");
|
||||||
keyNode.publish(new PayloadItem<>(pubkeyElement));
|
keyNode.publish(new PayloadItem<>(pubkeyElement));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,11 +122,17 @@ public final class OpenPgpManager extends Manager implements PEPListener {
|
||||||
return fetchPubkeysList(connection().getUser().asBareJid());
|
return fetchPubkeysList(connection().getUser().asBareJid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void deletePubkeysListNode()
|
||||||
|
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
||||||
|
SmackException.NoResponseException {
|
||||||
|
PubSubManager pm = PubSubManager.getInstance(connection(), connection().getUser().asBareJid());
|
||||||
|
pm.deleteNode(PEP_NODE_PUBLIC_KEYS);
|
||||||
|
}
|
||||||
|
|
||||||
public PublicKeysListElement fetchPubkeysList(BareJid jid)
|
public PublicKeysListElement fetchPubkeysList(BareJid jid)
|
||||||
throws InterruptedException, PubSubException.NotALeafNodeException, SmackException.NoResponseException,
|
throws InterruptedException, PubSubException.NotALeafNodeException, SmackException.NoResponseException,
|
||||||
SmackException.NotConnectedException, XMPPException.XMPPErrorException,
|
SmackException.NotConnectedException, XMPPException.XMPPErrorException,
|
||||||
PubSubException.NotAPubSubNodeException
|
PubSubException.NotAPubSubNodeException {
|
||||||
{
|
|
||||||
PubSubManager pm = PubSubManager.getInstance(connection(), jid);
|
PubSubManager pm = PubSubManager.getInstance(connection(), jid);
|
||||||
|
|
||||||
LeafNode node = pm.getLeafNode(PEP_NODE_PUBLIC_KEYS);
|
LeafNode node = pm.getLeafNode(PEP_NODE_PUBLIC_KEYS);
|
||||||
|
@ -171,8 +183,30 @@ public final class OpenPgpManager extends Manager implements PEPListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean canSyncSecretKey()
|
||||||
|
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
||||||
|
SmackException.NoResponseException {
|
||||||
|
boolean pep = PEPManager.getInstanceFor(connection()).isSupported();
|
||||||
|
boolean whitelist = PubSubManager.getInstance(connection(), connection().getUser().asBareJid())
|
||||||
|
.getSupportedFeatures().containsFeature("http://jabber.org/protocol/pubsub#access-whitelist");
|
||||||
|
return pep && whitelist;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final PEPListener metadataListener = new PEPListener() {
|
||||||
@Override
|
@Override
|
||||||
public void eventReceived(EntityBareJid from, EventElement event, Message message) {
|
public void eventReceived(EntityBareJid from, final EventElement event, Message message) {
|
||||||
|
if (PEP_NODE_PUBLIC_KEYS.equals(event.getEvent().getNode())) {
|
||||||
|
LOGGER.log(Level.INFO, "Received OpenPGP metadata update from " + from);
|
||||||
|
Async.go(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
ItemsExtension items = (ItemsExtension) event.getExtensions().get(0);
|
||||||
|
PayloadItem<?> payload = (PayloadItem) items.getItems().get(0);
|
||||||
|
PublicKeysListElement listElement = (PublicKeysListElement) payload.getPayload();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}, "ProcessOXPublicKey");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ package org.jivesoftware.smackx.ox;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.jivesoftware.smackx.ox.element.CryptElement;
|
|
||||||
import org.jivesoftware.smackx.ox.element.OpenPgpContentElement;
|
import org.jivesoftware.smackx.ox.element.OpenPgpContentElement;
|
||||||
import org.jivesoftware.smackx.ox.element.SignElement;
|
import org.jivesoftware.smackx.ox.element.SignElement;
|
||||||
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
||||||
|
@ -40,9 +39,8 @@ public class OpenPgpMessage {
|
||||||
|
|
||||||
private OpenPgpContentElement openPgpContentElement;
|
private OpenPgpContentElement openPgpContentElement;
|
||||||
|
|
||||||
public OpenPgpMessage(State state, String content) {
|
public OpenPgpMessage(String content) {
|
||||||
this.element = content;
|
this.element = content;
|
||||||
this.state = state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public OpenPgpContentElement getOpenPgpContentElement() throws XmlPullParserException, IOException {
|
public OpenPgpContentElement getOpenPgpContentElement() throws XmlPullParserException, IOException {
|
||||||
|
@ -56,7 +54,10 @@ public class OpenPgpMessage {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
openPgpContentElement = OpenPgpContentElementProvider.parseOpenPgpContentElement(element);
|
openPgpContentElement = OpenPgpContentElementProvider.parseOpenPgpContentElement(element);
|
||||||
if (state == null) {
|
if (openPgpContentElement == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (openPgpContentElement instanceof SigncryptElement) {
|
if (openPgpContentElement instanceof SigncryptElement) {
|
||||||
state = State.signcrypt;
|
state = State.signcrypt;
|
||||||
} else if (openPgpContentElement instanceof SignElement) {
|
} else if (openPgpContentElement instanceof SignElement) {
|
||||||
|
@ -64,30 +65,5 @@ public class OpenPgpMessage {
|
||||||
} else {
|
} else {
|
||||||
state = State.crypt;
|
state = State.crypt;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (state) {
|
|
||||||
case signcrypt:
|
|
||||||
if (!(openPgpContentElement instanceof SigncryptElement)) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"The used OpenPGP content element does not match the mode used in the raw OpenPGP message. Content element: "
|
|
||||||
+ openPgpContentElement.getElementName() + ". Mode: " + state);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case sign:
|
|
||||||
if (!(openPgpContentElement instanceof SignElement)) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"The used OpenPGP content element does not match the mode used in the raw OpenPGP message. Content element: "
|
|
||||||
+ openPgpContentElement.getElementName() + ". Mode: " + state);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case crypt:
|
|
||||||
if (!(openPgpContentElement instanceof CryptElement)) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"The used OpenPGP content element does not match the mode used in the raw OpenPGP message. Content element: "
|
|
||||||
+ openPgpContentElement.getElementName() + ". Mode: " + state);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.ox.element.CryptElement;
|
||||||
|
import org.jivesoftware.smackx.ox.element.SignElement;
|
||||||
|
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
||||||
|
|
||||||
|
import org.jxmpp.jid.BareJid;
|
||||||
|
|
||||||
|
public interface OpenPgpMessageListener {
|
||||||
|
void signcryptElementReceived(BareJid from, SigncryptElement signcryptElement);
|
||||||
|
|
||||||
|
void signElementReceived(BareJid from, SignElement signElement);
|
||||||
|
|
||||||
|
void cryptElementReceived(BareJid from, CryptElement cryptElement);
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
||||||
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
||||||
|
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
||||||
|
|
||||||
import org.jxmpp.jid.BareJid;
|
import org.jxmpp.jid.BareJid;
|
||||||
|
|
||||||
|
@ -30,10 +31,16 @@ public interface OpenPgpProvider {
|
||||||
|
|
||||||
OpenPgpElement signAndEncrypt(InputStream inputStream, Set<BareJid> recipients) throws Exception;
|
OpenPgpElement signAndEncrypt(InputStream inputStream, Set<BareJid> recipients) throws Exception;
|
||||||
|
|
||||||
|
OpenPgpElement sign(InputStream inputStream) throws Exception;
|
||||||
|
|
||||||
|
OpenPgpElement encrypt(InputStream inputStream, Set<BareJid> recipients) throws Exception;
|
||||||
|
|
||||||
PubkeyElement createPubkeyElement() throws Exception;
|
PubkeyElement createPubkeyElement() throws Exception;
|
||||||
|
|
||||||
void processPubkeyElement(PubkeyElement element, BareJid from) throws Exception;
|
void processPubkeyElement(PubkeyElement element, BareJid from) throws Exception;
|
||||||
|
|
||||||
|
void processPublicKeysListElement(PublicKeysListElement listElement, BareJid from) throws Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the OpenPGP v4-fingerprint of our key in hexadecimal upper case.
|
* Return the OpenPGP v4-fingerprint of our key in hexadecimal upper case.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.SmackException;
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smackx.pubsub.AccessModel;
|
||||||
|
import org.jivesoftware.smackx.pubsub.ConfigureForm;
|
||||||
|
import org.jivesoftware.smackx.pubsub.LeafNode;
|
||||||
|
|
||||||
|
public class PubSubHelper {
|
||||||
|
|
||||||
|
public static void whitelist(LeafNode node)
|
||||||
|
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
||||||
|
SmackException.NoResponseException {
|
||||||
|
ConfigureForm config = node.getNodeConfiguration();
|
||||||
|
if (config.getAccessModel() != AccessModel.whitelist) {
|
||||||
|
config.setAccessModel(AccessModel.whitelist);
|
||||||
|
node.sendConfigurationForm(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void open(LeafNode node)
|
||||||
|
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
|
||||||
|
SmackException.NoResponseException {
|
||||||
|
ConfigureForm config = node.getNodeConfiguration();
|
||||||
|
if (config.getAccessModel() != AccessModel.open) {
|
||||||
|
config.setAccessModel(AccessModel.open);
|
||||||
|
node.sendConfigurationForm(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,7 +55,7 @@ public abstract class OpenPgpContentElementProvider<O extends OpenPgpContentElem
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OpenPgpContentElement parseOpenPgpContentElement(XmlPullParser parser)
|
public static OpenPgpContentElement parseOpenPgpContentElement(XmlPullParser parser)
|
||||||
throws XmlPullParserException, IOException {
|
throws XmlPullParserException {
|
||||||
try {
|
try {
|
||||||
switch (parser.getName()) {
|
switch (parser.getName()) {
|
||||||
case SigncryptElement.ELEMENT:
|
case SigncryptElement.ELEMENT:
|
||||||
|
|
Loading…
Reference in a new issue