Add OxIkeyManager
This commit is contained in:
parent
474e327f42
commit
49eb137acb
|
@ -17,6 +17,8 @@ dependencies {
|
|||
api "org.igniterealtime.smack:smack-im:$smackImVersion"
|
||||
api "org.igniterealtime.smack:smack-tcp:$smackTcpVersion"
|
||||
api "org.igniterealtime.smack:smack-openpgp:$smackOpenpgpVersion"
|
||||
api "org.igniterealtime.smack:smack-omemo:$smackOmemoVersion"
|
||||
api "org.igniterealtime.smack:smack-omemo-signal:$smackOmemoSignalVersion"
|
||||
|
||||
api "org.jxmpp:jxmpp-core:1.0.1"
|
||||
api "org.jxmpp:jxmpp-jid:1.0.1"
|
||||
|
|
|
@ -8,7 +8,11 @@ import org.jivesoftware.smack.XMPPException;
|
|||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.provider.ProviderManager;
|
||||
import org.jivesoftware.smackx.ikey.element.IkeyElement;
|
||||
import org.jivesoftware.smackx.ikey.element.ProofElement;
|
||||
import org.jivesoftware.smackx.ikey.element.SignedElement;
|
||||
import org.jivesoftware.smackx.ikey.element.SubordinateListElement;
|
||||
import org.jivesoftware.smackx.ikey.element.SuperordinateElement;
|
||||
import org.jivesoftware.smackx.ikey.mechanism.IkeySignatureCreationMechanism;
|
||||
import org.jivesoftware.smackx.ikey.mechanism.IkeySignatureVerificationMechanism;
|
||||
import org.jivesoftware.smackx.ikey.provider.IkeyElementProvider;
|
||||
import org.jivesoftware.smackx.ikey.provider.SubordinateListElementProvider;
|
||||
|
@ -69,6 +73,15 @@ public final class IkeyManager extends Manager {
|
|||
.removePepEventListener(pepEventListener);
|
||||
}
|
||||
|
||||
public IkeyElement createIkeyElement(IkeySignatureCreationMechanism mechanism,
|
||||
SuperordinateElement superordinateElement,
|
||||
SubordinateListElement subordinateListElement)
|
||||
throws IOException {
|
||||
SignedElement signedElement = new SignedElement(subordinateListElement);
|
||||
ProofElement proofElement = new ProofElement(mechanism.createSignature(signedElement.getUtf8Bytes()));
|
||||
return new IkeyElement(mechanism.getType(), superordinateElement, signedElement, proofElement);
|
||||
}
|
||||
|
||||
public void publishIkeyElement(IkeyElement ikeyElement)
|
||||
throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException,
|
||||
SmackException.NotConnectedException, SmackException.NoResponseException {
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.jivesoftware.smack.packet.XmlEnvironment;
|
|||
import org.jivesoftware.smack.util.EqualsUtil;
|
||||
import org.jivesoftware.smack.util.HashCode;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||
|
||||
public class ProofElement implements NamedElement {
|
||||
|
||||
|
@ -16,6 +17,10 @@ public class ProofElement implements NamedElement {
|
|||
this.base64Sig = base64Sig;
|
||||
}
|
||||
|
||||
public ProofElement(byte[] plainBytes) {
|
||||
this(Base64.encodeToString(plainBytes));
|
||||
}
|
||||
|
||||
public String getBase64Signature() {
|
||||
return base64Sig;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package org.jivesoftware.smackx.ikey_ox;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smackx.ikey.IkeyManager;
|
||||
import org.jivesoftware.smackx.ikey.element.IkeyElement;
|
||||
import org.jivesoftware.smackx.ikey.element.SubordinateElement;
|
||||
import org.jivesoftware.smackx.ikey.element.SubordinateListElement;
|
||||
import org.jivesoftware.smackx.ikey.element.SuperordinateElement;
|
||||
import org.jivesoftware.smackx.ikey.mechanism.IkeySignatureCreationMechanism;
|
||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public final class OxIkeyManager extends Manager {
|
||||
|
||||
private static final Map<XMPPConnection, OxIkeyManager> INSTANCES = new WeakHashMap<>();
|
||||
|
||||
private final IkeyManager ikeyManager;
|
||||
|
||||
private OxIkeyManager(XMPPConnection connection) {
|
||||
super(connection);
|
||||
this.ikeyManager = IkeyManager.getInstanceFor(connection);
|
||||
}
|
||||
|
||||
public static OxIkeyManager getInstanceFor(XMPPConnection connection) {
|
||||
OxIkeyManager manager = INSTANCES.get(connection);
|
||||
if (manager == null) {
|
||||
manager = new OxIkeyManager(connection);
|
||||
INSTANCES.put(connection, manager);
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
||||
public IkeyElement createOxIkeyElement(PGPSecretKeyRing secretKeys,
|
||||
SecretKeyRingProtector keyRingProtector,
|
||||
SubordinateElement... subordinateElements) throws IOException {
|
||||
IkeySignatureCreationMechanism mechanism = new OxIkeySignatureCreationMechanism(secretKeys, keyRingProtector);
|
||||
SuperordinateElement superordinateElement = new SuperordinateElement(secretKeys.getPublicKey().getEncoded());
|
||||
SubordinateListElement subordinateListElement = new SubordinateListElement(connection().getUser().asEntityBareJid(),
|
||||
new Date(), Arrays.asList(subordinateElements));
|
||||
return ikeyManager.createIkeyElement(mechanism, superordinateElement, subordinateListElement);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package org.jivesoftware.smackx.ikey_utils;
|
||||
|
||||
import org.jivesoftware.smackx.ikey.element.SubordinateElement;
|
||||
import org.jivesoftware.smackx.omemo.internal.OmemoDevice;
|
||||
import org.jivesoftware.smackx.omemo.trust.OmemoFingerprint;
|
||||
import org.jivesoftware.smackx.ox.util.OpenPgpPubSubUtil;
|
||||
import org.jivesoftware.smackx.pubsub.PubSubUri;
|
||||
import org.jxmpp.jid.BareJid;
|
||||
import org.pgpainless.key.OpenPgpV4Fingerprint;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
public class IkeySubordinateElementCreator {
|
||||
|
||||
public static SubordinateElement createOxSubordinateElement(BareJid pubSubService, OpenPgpV4Fingerprint fingerprint, String itemId)
|
||||
throws URISyntaxException {
|
||||
String node = OpenPgpPubSubUtil.PEP_NODE_PUBLIC_KEY(fingerprint);
|
||||
PubSubUri pubSubUri = new PubSubUri(pubSubService, node, itemId, null);
|
||||
URI uri = new URI(pubSubUri.toString());
|
||||
return new SubordinateElement(uri, fingerprint.toString());
|
||||
}
|
||||
|
||||
public static SubordinateElement createOmemoSubordinateElement(BareJid pubSubService, OmemoDevice device, OmemoFingerprint fingerprint)
|
||||
throws URISyntaxException {
|
||||
PubSubUri pubSubUri = new PubSubUri(pubSubService, "urn:xmpp:omemo:1:bundles", Integer.toString(device.getDeviceId()), null);
|
||||
URI uri = new URI(pubSubUri.toString());
|
||||
return new SubordinateElement(uri, fingerprint.toString());
|
||||
}
|
||||
|
||||
public static SubordinateElement createSiacsOmemoSubordinateElement(BareJid pubSubService, OmemoDevice device, OmemoFingerprint fingerprint)
|
||||
throws URISyntaxException {
|
||||
PubSubUri pubSubUri = new PubSubUri(pubSubService, device.getBundleNodeName(), null, null);
|
||||
URI uri = new URI(pubSubUri.toString());
|
||||
return new SubordinateElement(uri, fingerprint.toString());
|
||||
}
|
||||
}
|
|
@ -44,6 +44,7 @@ public class IkeyElementTest extends MercurySmackTestSuite {
|
|||
IkeyElement ikeyElement = new IkeyElement(type, superordinate, new SignedElement(subordinates), proof);
|
||||
String xml = ikeyElement.toXML().toString();
|
||||
System.out.println(xml);
|
||||
System.out.println(subordinates.toXML().toString());
|
||||
|
||||
IkeyElement parsed = IkeyElementProvider.INSTANCE.parse(PacketParserUtils.getParserFor(xml));
|
||||
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package org.jivesoftware.smackx.ikey.element;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||
import org.jivesoftware.smackx.ikey.IkeySignatureCreator;
|
||||
import org.jivesoftware.smackx.ikey.IkeySignatureVerifier;
|
||||
import org.jivesoftware.smackx.ikey.mechanism.IkeySignatureCreationMechanism;
|
||||
import org.jivesoftware.smackx.ikey.mechanism.IkeySignatureVerificationMechanism;
|
||||
import org.jivesoftware.smackx.ikey.mechanism.IkeyType;
|
||||
import org.jivesoftware.smackx.ikey_ox.OxIkeySignatureCreationMechanism;
|
||||
import org.jivesoftware.smackx.ikey_ox.OxIkeySignatureVerificationMechanism;
|
||||
import org.jivesoftware.smackx.util.MercurySmackTestSuite;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.jxmpp.jid.impl.JidCreate;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.algorithm.KeyFlag;
|
||||
import org.pgpainless.key.collection.PGPKeyRing;
|
||||
import org.pgpainless.key.generation.KeySpec;
|
||||
import org.pgpainless.key.generation.type.ECDSA;
|
||||
import org.pgpainless.key.generation.type.curve.EllipticCurve;
|
||||
import org.pgpainless.key.protection.UnprotectedKeysProtector;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class XepTest extends MercurySmackTestSuite {
|
||||
|
||||
@Test
|
||||
public void test() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException, IOException, URISyntaxException {
|
||||
EntityBareJid jid = JidCreate.entityBareFromOrThrowUnchecked("juliet@capulet.lit");
|
||||
PGPKeyRing keyRing = PGPainless.generateKeyRing()
|
||||
.withMasterKey(KeySpec.getBuilder(ECDSA.fromCurve(EllipticCurve._P256))
|
||||
.withKeyFlags(KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
|
||||
.withDefaultAlgorithms())
|
||||
.withPrimaryUserId("xmpp:" + jid)
|
||||
.withoutPassphrase()
|
||||
.build();
|
||||
|
||||
IkeySignatureCreationMechanism signingMechanism = new OxIkeySignatureCreationMechanism(
|
||||
keyRing.getSecretKeys(), new UnprotectedKeysProtector());
|
||||
IkeySignatureCreator creator = new IkeySignatureCreator(signingMechanism);
|
||||
IkeySignatureVerificationMechanism verificationMechanism = new OxIkeySignatureVerificationMechanism(keyRing.getPublicKeys());
|
||||
IkeySignatureVerifier verifier = new IkeySignatureVerifier(verificationMechanism);
|
||||
|
||||
SuperordinateElement superordinate = new SuperordinateElement(Base64.encodeToString(keyRing.getMasterKey().getEncoded()));
|
||||
|
||||
List<SubordinateElement> subList = new ArrayList<>();
|
||||
subList.add(new SubordinateElement(
|
||||
new URI("xmpp:" + jid + "?;node=urn:xmpp:openpgp:0:public-keys:1357B01865B2503C18453D208CAC2A9678548E35;item=2020-01-21T10:46:21Z"),
|
||||
"1357B01865B2503C18453D208CAC2A9678548E35"));
|
||||
subList.add(new SubordinateElement(new URI("xmpp:" + jid + "?;node=urn:xmpp:omemo:1:bundles;item=31415"), "e64dc9166dd34db64c9247bd502c5969e365a98f3aa41c87247d120487fdd32f"));
|
||||
subList.add(new SubordinateElement(new URI("xmpp:" + jid + "?;node=eu.siacs.conversations.axolotl.bundles:31415"), "e64dc9166dd34db64c9247bd502c5969e365a98f3aa41c87247d120487fdd32f"));
|
||||
|
||||
SubordinateListElement subs = new SubordinateListElement(jid, new Date(), subList);
|
||||
|
||||
ProofElement proofElement = creator.createProofFor(subs);
|
||||
IkeyElement ikeyElement = new IkeyElement(IkeyType.OX, superordinate, new SignedElement(subs), proofElement);
|
||||
|
||||
System.out.println(subs.toXML().toString());
|
||||
System.out.println(ikeyElement.toXML().toString());
|
||||
|
||||
assertTrue(verifier.verify(ikeyElement, jid));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package org.jivesoftware.smackx.ikey_utils;
|
||||
|
||||
import org.jivesoftware.smackx.ikey.element.SubordinateElement;
|
||||
import org.jivesoftware.smackx.omemo.internal.OmemoDevice;
|
||||
import org.jivesoftware.smackx.omemo.trust.OmemoFingerprint;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.jxmpp.jid.BareJid;
|
||||
import org.jxmpp.jid.impl.JidCreate;
|
||||
import org.pgpainless.key.OpenPgpV4Fingerprint;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class IkeySubordinateElementCreatorTest {
|
||||
|
||||
@Test
|
||||
public void testOxSubordinateElementCreation() throws URISyntaxException {
|
||||
String xml = "<sub uri='xmpp:hamlet@denmark.lit?;node=urn:xmpp:openpgp:0:public-keys:1357B01865B2503C18453D208CAC2A9678548E35;item=2020-01-21T10:46:21Z' " +
|
||||
"fpr='1357B01865B2503C18453D208CAC2A9678548E35'/>";
|
||||
|
||||
BareJid pubSubService = JidCreate.bareFromOrThrowUnchecked("hamlet@denmark.lit");
|
||||
OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint("1357B01865B2503C18453D208CAC2A9678548E35");
|
||||
String itemId = "2020-01-21T10:46:21Z";
|
||||
|
||||
SubordinateElement element = IkeySubordinateElementCreator.createOxSubordinateElement(pubSubService, fingerprint, itemId);
|
||||
|
||||
assertEquals(xml, element.toXML().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOmemoSubordinateElementCreation() throws URISyntaxException {
|
||||
String xml = "<sub uri='xmpp:hamlet@denmark.lit?;node=urn:xmpp:omemo:1:bundles;item=31415' " +
|
||||
"fpr='e64dc9166dd34db64c9247bd502c5969e365a98f3aa41c87247d120487fdd32f'/>";
|
||||
|
||||
BareJid pubSubService = JidCreate.bareFromOrThrowUnchecked("hamlet@denmark.lit");
|
||||
OmemoFingerprint fingerprint = new OmemoFingerprint("e64dc9166dd34db64c9247bd502c5969e365a98f3aa41c87247d120487fdd32f");
|
||||
|
||||
SubordinateElement element = IkeySubordinateElementCreator.createOmemoSubordinateElement(pubSubService, new OmemoDevice(pubSubService, 31415), fingerprint);
|
||||
|
||||
assertEquals(xml, element.toXML().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSiacsOmemoSubordinateElementCreation() throws URISyntaxException {
|
||||
String xml = "<sub uri='xmpp:hamlet@denmark.lit?;node=eu.siacs.conversations.axolotl.bundles:31415' " +
|
||||
"fpr='e64dc9166dd34db64c9247bd502c5969e365a98f3aa41c87247d120487fdd32f'/>";
|
||||
|
||||
BareJid pubSubService = JidCreate.bareFromOrThrowUnchecked("hamlet@denmark.lit");
|
||||
OmemoFingerprint fingerprint = new OmemoFingerprint("e64dc9166dd34db64c9247bd502c5969e365a98f3aa41c87247d120487fdd32f");
|
||||
|
||||
SubordinateElement element = IkeySubordinateElementCreator.createSiacsOmemoSubordinateElement(pubSubService, new OmemoDevice(pubSubService, 31415), fingerprint);
|
||||
|
||||
assertEquals(xml, element.toXML().toString());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue