diff --git a/settings.gradle b/settings.gradle index b97085392..ee70118ed 100644 --- a/settings.gradle +++ b/settings.gradle @@ -29,3 +29,4 @@ include 'smack-core', 'smack-repl', 'smack-openpgp', 'smack-openpgp-bouncycastle' + diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpInitializer.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpInitializer.java new file mode 100644 index 000000000..47ad314ff --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpInitializer.java @@ -0,0 +1,27 @@ +/** + * + * 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.initializer.UrlInitializer; + +public class OpenPgpInitializer extends UrlInitializer { + + @Override + protected String getProvidersUri() { + return "classpath:org.jivesoftware.smackx.ox/openpgp.providers"; + } +} 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 cb7a5f682..0148195d3 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 @@ -1,6 +1,6 @@ /** * - * Copyright 2017 Florian Schmaus. + * 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. @@ -17,10 +17,48 @@ package org.jivesoftware.smackx.ox; import java.io.InputStream; +import java.util.Map; +import java.util.WeakHashMap; -public class OpenPgpManager { +import org.jivesoftware.smack.Manager; +import org.jivesoftware.smack.XMPPConnection; + +import org.jxmpp.jid.BareJid; + +public final class OpenPgpManager extends Manager { + + public static final String PEP_NODE_PUBLIC_KEYS = "urn:xmpp:openpgp:0:public-keys"; + + public static String PEP_NODE_PUBLIC_KEY(String id) { + return PEP_NODE_PUBLIC_KEYS + ":" + id; + } + + private static final Map INSTANCES = new WeakHashMap<>(); + + private OpenPgpManager(XMPPConnection connection) { + super(connection); + } + + public static OpenPgpManager getInstanceFor(XMPPConnection connection) { + OpenPgpManager manager = INSTANCES.get(connection); + if (manager == null) { + manager = new OpenPgpManager(connection); + INSTANCES.put(connection, manager); + } + return manager; + } + + public static String bareJidToIdentity(BareJid jid) { + return "xmpp:" + jid.toString(); + } public static OpenPgpMessage toOpenPgpMessage(InputStream is) { return null; } + + public void publishPublicKey() { + // Check if key available at data node + // If not, publish key to data node + // Publish ID to metadata node + } } diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpMessage.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpMessage.java index 4824b62a3..58bcdc61d 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpMessage.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpMessage.java @@ -23,6 +23,7 @@ import org.jivesoftware.smackx.ox.element.OpenPgpContentElement; import org.jivesoftware.smackx.ox.element.SignElement; import org.jivesoftware.smackx.ox.element.SigncryptElement; import org.jivesoftware.smackx.ox.provider.OpenPgpContentElementProvider; + import org.xmlpull.v1.XmlPullParserException; public class OpenPgpMessage { 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 4fb9b044b..1fd7631b9 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 @@ -20,6 +20,6 @@ import java.io.InputStream; public interface OpenPgpProvider { - public OpenPgpMessage toOpenPgpMessage(InputStream is); + OpenPgpMessage toOpenPgpMessage(InputStream is); } diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/CryptElement.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/CryptElement.java index 8342dfa85..4fbea2818 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/CryptElement.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/CryptElement.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017 Florian Schmaus. + * 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. @@ -18,27 +18,39 @@ package org.jivesoftware.smackx.ox.element; import java.util.Date; import java.util.List; +import java.util.Set; import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.util.XmlStringBuilder; + import org.jxmpp.jid.Jid; +/** + * This class describes an OpenPGP content element which is encrypted, but not signed. + */ public class CryptElement extends EncryptedOpenPgpContentElement { public static final String ELEMENT = "crypt"; - public CryptElement(List to, String rpad, Date timestamp, List payload) { + public CryptElement(Set to, String rpad, Date timestamp, List payload) { super(to, rpad, timestamp, payload); } + public CryptElement(Set to, List payload) { + super(to, payload); + } + @Override public String getElementName() { return ELEMENT; } @Override - public CharSequence toXML() { - // TODO Auto-generated method stub - return null; + public XmlStringBuilder toXML(String enclosingNamespace) { + XmlStringBuilder xml = new XmlStringBuilder(this).rightAngleBracket(); + addCommonXml(xml); + xml.closeElement(this); + return xml; } } diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/EncryptedOpenPgpContentElement.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/EncryptedOpenPgpContentElement.java index 7f29f5a60..483fc6e82 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/EncryptedOpenPgpContentElement.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/EncryptedOpenPgpContentElement.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017 Florian Schmaus. + * 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. @@ -16,22 +16,43 @@ */ package org.jivesoftware.smackx.ox.element; +import java.security.SecureRandom; import java.util.Date; import java.util.List; +import java.util.Set; import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.XmlStringBuilder; + import org.jxmpp.jid.Jid; public abstract class EncryptedOpenPgpContentElement extends OpenPgpContentElement { + public static final String ELEM_RPAD = "rpad"; + private final String rpad; - protected EncryptedOpenPgpContentElement(List to, String rpad, Date timestamp, List payload) { + protected EncryptedOpenPgpContentElement(Set to, String rpad, Date timestamp, List payload) { super(to, timestamp, payload); this.rpad = rpad; } + protected EncryptedOpenPgpContentElement(Set to, List payload) { + super(to, new Date(), payload); + this.rpad = createRandomPadding(); + } + + public String getRandomPadding() { + return rpad; + } + + private static String createRandomPadding() { + SecureRandom secRan = new SecureRandom(); + int len = secRan.nextInt(256); // TODO: Find suitable value. + return StringUtils.randomString(len); + } + @Override protected void addCommonXml(XmlStringBuilder xml) { super.addCommonXml(xml); diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/OpenPgpContentElement.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/OpenPgpContentElement.java index b0ec65464..49b3ea14b 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/OpenPgpContentElement.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/OpenPgpContentElement.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017 Florian Schmaus. + * 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. @@ -18,27 +18,39 @@ package org.jivesoftware.smackx.ox.element; import java.util.Date; import java.util.List; +import java.util.Set; import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.util.XmlStringBuilder; + import org.jxmpp.jid.Jid; import org.jxmpp.util.XmppDateTime; +/** + * This class describes an OpenPGP content element. It defines the elements and fields that OpenPGP content elements + * do have in common. + */ public abstract class OpenPgpContentElement implements ExtensionElement { - private final List to; + public static final String ELEM_TO = "to"; + public static final String ATTR_JID = "jid"; + public static final String ELEM_TIME = "time"; + public static final String ATTR_STAMP = "stamp"; + public static final String ELEM_PAYLOAD = "payload"; + + private final Set to; private final Date timestamp; private final List payload; private String timestampString; - protected OpenPgpContentElement(List to, Date timestamp, List payload) { + protected OpenPgpContentElement(Set to, Date timestamp, List payload) { this.to = to; this.timestamp = timestamp; this.payload = payload; } - public final List getTo() { + public final Set getTo() { return to; } @@ -63,16 +75,16 @@ public abstract class OpenPgpContentElement implements ExtensionElement { protected void addCommonXml(XmlStringBuilder xml) { for (Jid toJid : to) { - xml.halfOpenElement("to").attribute("jid", toJid).closeEmptyElement(); + xml.halfOpenElement(ELEM_TO).attribute(ATTR_JID, toJid).closeEmptyElement(); } ensureTimestampStringSet(); - xml.halfOpenElement("time").attribute("stamp", timestampString).closeEmptyElement(); + xml.halfOpenElement(ELEM_TIME).attribute(ATTR_STAMP, timestampString).closeEmptyElement(); - xml.openElement("payload"); + xml.openElement(ELEM_PAYLOAD); for (ExtensionElement element : payload) { - xml.append(element.toXML()); + xml.append(element.toXML(getNamespace())); } - xml.closeElement("payload"); + xml.closeElement(ELEM_PAYLOAD); } } diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/OpenPgpElement.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/OpenPgpElement.java index 9f057aa65..4f21db051 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/OpenPgpElement.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/OpenPgpElement.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017 Florian Schmaus. + * 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. @@ -21,15 +21,17 @@ import java.io.IOException; import java.io.InputStream; import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smack.util.stringencoder.Base64; import org.jivesoftware.smackx.ox.OpenPgpManager; import org.jivesoftware.smackx.ox.OpenPgpMessage; + import org.xmlpull.v1.XmlPullParserException; public class OpenPgpElement implements ExtensionElement { public static final String ELEMENT = "openpgp"; - public static final String NAMESPACE = "urn:xmpp:openpg:0"; + public static final String NAMESPACE = "urn:xmpp:openpgp:0"; private final String base64EncodedOpenPgpMessage; @@ -72,12 +74,13 @@ public class OpenPgpElement implements ExtensionElement { } @Override - public CharSequence toXML() { - // TODO Auto-generated method stub - return null; + public XmlStringBuilder toXML(String enclosingNamespace) { + XmlStringBuilder xml = new XmlStringBuilder(this); + xml.rightAngleBracket().append(base64EncodedOpenPgpMessage).closeElement(this); + return xml; } - private final void ensureOpenPgpMessageBytesSet() { + private void ensureOpenPgpMessageBytesSet() { if (openPgpMessageBytes != null) return; openPgpMessageBytes = Base64.decode(base64EncodedOpenPgpMessage); diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/PubkeyElement.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/PubkeyElement.java new file mode 100644 index 000000000..e18335710 --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/PubkeyElement.java @@ -0,0 +1,97 @@ +/** + * + * 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.element; + +import java.nio.charset.Charset; +import java.util.Date; + +import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.packet.NamedElement; +import org.jivesoftware.smack.util.Objects; +import org.jivesoftware.smack.util.XmlStringBuilder; + +public class PubkeyElement implements ExtensionElement { + + public static final String NAMESPACE = OpenPgpElement.NAMESPACE; + public static final String ELEMENT = "pubkey"; + public static final String ATTR_DATE = "date"; + + private final PubkeyDataElement dataElement; + private final Date date; + + public PubkeyElement(PubkeyDataElement dataElement, Date date) { + this.dataElement = Objects.requireNonNull(dataElement); + this.date = date; + } + + public PubkeyDataElement getDataElement() { + return dataElement; + } + + public Date getDate() { + return date; + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + @Override + public String getElementName() { + return ELEMENT; + } + + @Override + public XmlStringBuilder toXML(String enclosingNamespace) { + XmlStringBuilder xml = new XmlStringBuilder(this) + .optAttribute(ATTR_DATE, date) + .rightAngleBracket() + .element(getDataElement()) + .closeElement(this); + return xml; + } + + public static class PubkeyDataElement implements NamedElement { + + public static final String ELEMENT = "data"; + + private final byte[] b64Data; + + public PubkeyDataElement(byte[] b64Data) { + this.b64Data = b64Data; + } + + public byte[] getB64Data() { + return b64Data; + } + + @Override + public String getElementName() { + return ELEMENT; + } + + @Override + public XmlStringBuilder toXML(String enclosingNamespace) { + XmlStringBuilder xml = new XmlStringBuilder(this) + .rightAngleBracket() + .append(new String(b64Data, Charset.forName("UTF-8"))) + .closeElement(this); + return xml; + } + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/PublicKeysListElement.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/PublicKeysListElement.java new file mode 100644 index 000000000..a2fb4d7c6 --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/PublicKeysListElement.java @@ -0,0 +1,147 @@ +/** + * + * 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.element; + +import java.util.Collections; +import java.util.Date; +import java.util.Map; +import java.util.TreeMap; + +import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.packet.NamedElement; +import org.jivesoftware.smack.util.Objects; +import org.jivesoftware.smack.util.XmlStringBuilder; + +public final class PublicKeysListElement implements ExtensionElement { + + public static final String NAMESPACE = OpenPgpElement.NAMESPACE; + public static final String ELEMENT = "public-keys-list"; + + private final Map metadata; + + private PublicKeysListElement(TreeMap metadata) { + this.metadata = Collections.unmodifiableMap(metadata); + } + + public static Builder builder() { + return new Builder(); + } + + public TreeMap getMetadata() { + return new TreeMap<>(metadata); + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + @Override + public String getElementName() { + return ELEMENT; + } + + @Override + public XmlStringBuilder toXML(String enclosingNamespace) { + XmlStringBuilder xml = new XmlStringBuilder(this).rightAngleBracket(); + for (PubkeyMetadataElement metadataElement : metadata.values()) { + xml.element(metadataElement); + } + xml.closeElement(this); + return xml; + } + + public static final class Builder { + + private final TreeMap metadata = new TreeMap<>(); + + private Builder() { + // Empty + } + + public Builder addMetadata(PubkeyMetadataElement key) { + metadata.put(key.getV4Fingerprint(), key); + return this; + } + + public PublicKeysListElement build() { + return new PublicKeysListElement(metadata); + } + } + + public static class PubkeyMetadataElement implements NamedElement { + + public static final String ELEMENT = "pubkey-metadata"; + public static final String ATTR_V4_FINGERPRINT = "v4-fingerprint"; + public static final String ATTR_DATE = "date"; + + private final String v4_fingerprint; + private final Date date; + + public PubkeyMetadataElement(String v4_fingerprint, Date date) { + this.v4_fingerprint = Objects.requireNonNull(v4_fingerprint); + this.date = Objects.requireNonNull(date); + + if (v4_fingerprint.length() != 40) { + throw new IllegalArgumentException("OpenPGP v4 fingerprint must be 40 characters long."); + } + } + + public String getV4Fingerprint() { + return v4_fingerprint; + } + + public Date getDate() { + return date; + } + + @Override + public String getElementName() { + return ELEMENT; + } + + @Override + public XmlStringBuilder toXML(String enclosingNamespace) { + XmlStringBuilder xml = new XmlStringBuilder(this) + .attribute(ATTR_V4_FINGERPRINT, getV4Fingerprint()) + .attribute(ATTR_DATE, date).closeEmptyElement(); + return xml; + } + + @Override + public int hashCode() { + return getV4Fingerprint().hashCode() + 3 * getDate().hashCode(); + } + + @Override + public boolean equals(Object o) { + if (o == null) { + return false; + } + + if (!(o instanceof PubkeyMetadataElement)) { + return false; + } + + if (o == this) { + return true; + } + + return hashCode() == o.hashCode(); + } + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/SecretkeyElement.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/SecretkeyElement.java new file mode 100644 index 000000000..a331d4ab6 --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/SecretkeyElement.java @@ -0,0 +1,57 @@ +/** + * + * 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.element; + +import java.nio.charset.Charset; + +import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.util.XmlStringBuilder; + +public class SecretkeyElement implements ExtensionElement { + + public static final String NAMESPACE = OpenPgpElement.NAMESPACE; + public static final String ELEMENT = "secretkey"; + + private final byte[] b64Data; + + public SecretkeyElement(byte[] b64Data) { + this.b64Data = b64Data; + } + + public byte[] getB64Data() { + return b64Data; + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + + @Override + public String getElementName() { + return ELEMENT; + } + + @Override + public XmlStringBuilder toXML(String enclosingNamespace) { + XmlStringBuilder xml = new XmlStringBuilder(this) + .rightAngleBracket() + .append(new String(b64Data, Charset.forName("UTF-8"))) + .closeElement(this); + return xml; + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/SignElement.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/SignElement.java index 553bdf3be..04bf47161 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/SignElement.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/SignElement.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017 Florian Schmaus. + * 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. @@ -18,13 +18,16 @@ package org.jivesoftware.smackx.ox.element; import java.util.Date; import java.util.List; +import java.util.Set; import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.util.XmlStringBuilder; + import org.jxmpp.jid.Jid; public class SignElement extends OpenPgpContentElement { - public SignElement(List to, Date timestamp, List payload) { + public SignElement(Set to, Date timestamp, List payload) { super(to, timestamp, payload); } @@ -36,9 +39,11 @@ public class SignElement extends OpenPgpContentElement { } @Override - public CharSequence toXML() { - // TODO Auto-generated method stub - return null; + public XmlStringBuilder toXML(String enclosingNamespace) { + XmlStringBuilder xml = new XmlStringBuilder(this).rightAngleBracket(); + addCommonXml(xml); + xml.closeElement(this); + return xml; } } diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/SigncryptElement.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/SigncryptElement.java index e8f9c9616..e6759e712 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/SigncryptElement.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/SigncryptElement.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017 Florian Schmaus. + * 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. @@ -18,27 +18,36 @@ package org.jivesoftware.smackx.ox.element; import java.util.Date; import java.util.List; +import java.util.Set; import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.util.XmlStringBuilder; + import org.jxmpp.jid.Jid; public class SigncryptElement extends EncryptedOpenPgpContentElement { public static final String ELEMENT = "signcrypt"; - public SigncryptElement(List to, String rpad, Date timestamp, List payload) { + public SigncryptElement(Set to, String rpad, Date timestamp, List payload) { super(to, rpad, timestamp, payload); } + public SigncryptElement(Set to, List payload) { + super(to, payload); + } + @Override public String getElementName() { return ELEMENT; } @Override - public CharSequence toXML() { - // TODO Auto-generated method stub - return null; + public XmlStringBuilder toXML(String enclosingNamespace) { + XmlStringBuilder xml = new XmlStringBuilder(this).rightAngleBracket(); + addCommonXml(xml); + xml.closeElement(this); + return xml; } } diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/CryptElementProvider.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/CryptElementProvider.java index 28010eb00..c9d3ef9ff 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/CryptElementProvider.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/CryptElementProvider.java @@ -17,12 +17,16 @@ package org.jivesoftware.smackx.ox.provider; import org.jivesoftware.smackx.ox.element.CryptElement; + import org.xmlpull.v1.XmlPullParser; public class CryptElementProvider extends OpenPgpContentElementProvider { + public static final CryptElementProvider TEST_INSTANCE = new CryptElementProvider(); + @Override - public CryptElement parse(XmlPullParser parser, int initialDepth) throws Exception { + public CryptElement parse(XmlPullParser parser, int initialDepth) + throws Exception { OpenPgpContentElementData data = parseOpenPgpContentElementData(parser, initialDepth); return new CryptElement(data.to, data.rpad, data.timestamp, data.payload); diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/OpenPgpContentElementProvider.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/OpenPgpContentElementProvider.java index c3ae74991..79c32bc7b 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/OpenPgpContentElementProvider.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/OpenPgpContentElementProvider.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017 Florian Schmaus. + * 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. @@ -16,50 +16,127 @@ */ package org.jivesoftware.smackx.ox.provider; +import static org.xmlpull.v1.XmlPullParser.END_TAG; +import static org.xmlpull.v1.XmlPullParser.START_TAG; + import java.io.IOException; import java.util.Date; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.provider.ExtensionElementProvider; +import org.jivesoftware.smack.provider.ProviderManager; import org.jivesoftware.smack.util.PacketParserUtils; +import org.jivesoftware.smackx.ox.element.CryptElement; +import org.jivesoftware.smackx.ox.element.EncryptedOpenPgpContentElement; import org.jivesoftware.smackx.ox.element.OpenPgpContentElement; +import org.jivesoftware.smackx.ox.element.SignElement; +import org.jivesoftware.smackx.ox.element.SigncryptElement; + import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.util.XmppDateTime; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; public abstract class OpenPgpContentElementProvider extends ExtensionElementProvider { + private static final Logger LOGGER = Logger.getLogger(OpenPgpContentElementProvider.class.getName()); + public static OpenPgpContentElement parseOpenPgpContentElement(String element) throws XmlPullParserException, IOException { XmlPullParser parser = PacketParserUtils.getParserFor(element); return parseOpenPgpContentElement(parser); } - public static OpenPgpContentElement parseOpenPgpContentElement(XmlPullParser parser) { + public static OpenPgpContentElement parseOpenPgpContentElement(XmlPullParser parser) + throws IOException, XmlPullParserException { + // TODO return null; } @Override public abstract O parse(XmlPullParser parser, int initialDepth) throws Exception; - protected static OpenPgpContentElementData parseOpenPgpContentElementData(XmlPullParser parser, int initialDepth) { - List to = new LinkedList<>(); + protected static OpenPgpContentElementData parseOpenPgpContentElementData(XmlPullParser parser, int initialDepth) + throws Exception { + Set to = new HashSet<>(); Date timestamp = null; String rpad = null; List payload = new LinkedList<>(); + outerloop: while (true) { + int tag = parser.next(); + String name = parser.getName(); + switch (tag) { + case START_TAG: + switch (name) { + + case OpenPgpContentElement.ELEM_TIME: + String stamp = parser.getAttributeValue("", OpenPgpContentElement.ATTR_STAMP); + timestamp = XmppDateTime.parseDate(stamp); + break; + + case OpenPgpContentElement.ELEM_TO: + String jid = parser.getAttributeValue("", OpenPgpContentElement.ATTR_JID); + to.add(JidCreate.bareFrom(jid)); + break; + + case EncryptedOpenPgpContentElement.ELEM_RPAD: + rpad = parser.nextText(); + break; + + case OpenPgpContentElement.ELEM_PAYLOAD: + innerloop: while (true) { + int ptag = parser.next(); + String pname = parser.getName(); + String pns = parser.getNamespace(); + switch (ptag) { + + case START_TAG: + ExtensionElementProvider provider = + ProviderManager.getExtensionProvider(pname, pns); + if (provider == null) { + LOGGER.log(Level.INFO, "No provider found for " + pname + " " + pns); + continue innerloop; + } + payload.add(provider.parse(parser)); + break; + + case END_TAG: + break innerloop; + } + } + break; + } + break; + + case END_TAG: + switch (name) { + case CryptElement.ELEMENT: + case SigncryptElement.ELEMENT: + case SignElement.ELEMENT: + break outerloop; + } + break; + } + } + return new OpenPgpContentElementData(to, timestamp, rpad, payload); } - protected final static class OpenPgpContentElementData { - protected final List to; + protected static final class OpenPgpContentElementData { + protected final Set to; protected final Date timestamp; protected final String rpad; protected final List payload; - private OpenPgpContentElementData(List to, Date timestamp, String rpad, List payload) { + private OpenPgpContentElementData(Set to, Date timestamp, String rpad, List payload) { this.to = to; this.timestamp = timestamp; this.rpad = rpad; diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/OpenPgpElementProvider.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/OpenPgpElementProvider.java index 984ee630b..e5c72c8ad 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/OpenPgpElementProvider.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/OpenPgpElementProvider.java @@ -18,10 +18,13 @@ package org.jivesoftware.smackx.ox.provider; import org.jivesoftware.smack.provider.ExtensionElementProvider; import org.jivesoftware.smackx.ox.element.OpenPgpElement; + import org.xmlpull.v1.XmlPullParser; public class OpenPgpElementProvider extends ExtensionElementProvider { + public static final OpenPgpElementProvider TEST_INSTANCE = new OpenPgpElementProvider(); + @Override public OpenPgpElement parse(XmlPullParser parser, int initialDepth) throws Exception { String base64EncodedOpenPgpMessage = parser.nextText(); diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/PubkeyElementProvider.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/PubkeyElementProvider.java new file mode 100644 index 000000000..a96bfa892 --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/PubkeyElementProvider.java @@ -0,0 +1,53 @@ +/** + * + * 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.provider; + +import static org.xmlpull.v1.XmlPullParser.START_TAG; + +import java.nio.charset.Charset; +import java.util.Date; + +import org.jivesoftware.smack.provider.ExtensionElementProvider; +import org.jivesoftware.smackx.ox.element.PubkeyElement; + +import org.jxmpp.util.XmppDateTime; +import org.xmlpull.v1.XmlPullParser; + +public class PubkeyElementProvider extends ExtensionElementProvider { + + public static final PubkeyElementProvider TEST_INSTANCE = new PubkeyElementProvider(); + + @Override + public PubkeyElement parse(XmlPullParser parser, int initialDepth) throws Exception { + String dateString = parser.getAttributeValue(null, PubkeyElement.ATTR_DATE); + Date date = dateString != null ? XmppDateTime.parseXEP0082Date(dateString) : null; + while (true) { + int tag = parser.next(); + String name = parser.getName(); + if (tag == START_TAG) { + switch (name) { + case PubkeyElement.PubkeyDataElement.ELEMENT: + String data = parser.nextText(); + if (data != null) { + byte[] bytes = data.getBytes(Charset.forName("UTF-8")); + return new PubkeyElement(new PubkeyElement.PubkeyDataElement(bytes), date); + } + } + } + } + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/PublicKeysListElementProvider.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/PublicKeysListElementProvider.java new file mode 100644 index 000000000..3058f160f --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/PublicKeysListElementProvider.java @@ -0,0 +1,65 @@ +/** + * + * 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.provider; + +import static org.xmlpull.v1.XmlPullParser.END_TAG; +import static org.xmlpull.v1.XmlPullParser.START_TAG; + +import java.util.Date; + +import org.jivesoftware.smack.provider.ExtensionElementProvider; +import org.jivesoftware.smackx.ox.element.PublicKeysListElement; + +import org.jxmpp.util.XmppDateTime; +import org.xmlpull.v1.XmlPullParser; + +public final class PublicKeysListElementProvider extends ExtensionElementProvider { + + public static final PublicKeysListElementProvider TEST_INSTANCE = new PublicKeysListElementProvider(); + + @Override + public PublicKeysListElement parse(XmlPullParser parser, int initialDepth) throws Exception { + + PublicKeysListElement.Builder builder = PublicKeysListElement.builder(); + + while (true) { + + int tag = parser.nextTag(); + String name = parser.getName(); + + switch (tag) { + case START_TAG: + + if (PublicKeysListElement.PubkeyMetadataElement.ELEMENT.equals(name)) { + String finger = parser.getAttributeValue(null, + PublicKeysListElement.PubkeyMetadataElement.ATTR_V4_FINGERPRINT); + String dt = parser.getAttributeValue(null, + PublicKeysListElement.PubkeyMetadataElement.ATTR_DATE); + Date date = XmppDateTime.parseXEP0082Date(dt); + builder.addMetadata(new PublicKeysListElement.PubkeyMetadataElement(finger, date)); + } + break; + + case END_TAG: + + if (name.equals(PublicKeysListElement.ELEMENT)) { + return builder.build(); + } + } + } + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/SecretkeyElementProvider.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/SecretkeyElementProvider.java new file mode 100644 index 000000000..04b75096c --- /dev/null +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/SecretkeyElementProvider.java @@ -0,0 +1,35 @@ +/** + * + * 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.provider; + +import java.nio.charset.Charset; + +import org.jivesoftware.smack.provider.ExtensionElementProvider; +import org.jivesoftware.smackx.ox.element.SecretkeyElement; + +import org.xmlpull.v1.XmlPullParser; + +public class SecretkeyElementProvider extends ExtensionElementProvider { + + public static final SecretkeyElementProvider TEST_INSTANCE = new SecretkeyElementProvider(); + + @Override + public SecretkeyElement parse(XmlPullParser parser, int initialDepth) throws Exception { + String data = parser.nextText(); + return new SecretkeyElement(data.getBytes(Charset.forName("UTF-8"))); + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/SignElementProvider.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/SignElementProvider.java index 5a21c73cc..346bae899 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/SignElementProvider.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/SignElementProvider.java @@ -20,11 +20,13 @@ import java.util.logging.Logger; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.ox.element.SignElement; + import org.xmlpull.v1.XmlPullParser; public class SignElementProvider extends OpenPgpContentElementProvider { private static final Logger LOGGER = Logger.getLogger(SigncryptElementProvider.class.getName()); + public static final SignElementProvider TEST_INSTANCE = new SignElementProvider(); @Override public SignElement parse(XmlPullParser parser, int initialDepth) throws Exception { diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/SigncryptElementProvider.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/SigncryptElementProvider.java index 68a0aaf03..f850bf89a 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/SigncryptElementProvider.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/SigncryptElementProvider.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017 Florian Schmaus. + * 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. @@ -17,10 +17,13 @@ package org.jivesoftware.smackx.ox.provider; import org.jivesoftware.smackx.ox.element.SigncryptElement; + import org.xmlpull.v1.XmlPullParser; public class SigncryptElementProvider extends OpenPgpContentElementProvider { + public static final SigncryptElementProvider TEST_INSTANCE = new SigncryptElementProvider(); + @Override public SigncryptElement parse(XmlPullParser parser, int initialDepth) throws Exception { OpenPgpContentElementData data = parseOpenPgpContentElementData(parser, initialDepth); diff --git a/smack-openpgp/src/main/resources/org.jivesoftware.smackx.ox/openpgp.providers b/smack-openpgp/src/main/resources/org.jivesoftware.smackx.ox/openpgp.providers new file mode 100644 index 000000000..27e02d11d --- /dev/null +++ b/smack-openpgp/src/main/resources/org.jivesoftware.smackx.ox/openpgp.providers @@ -0,0 +1,28 @@ + + + + + + + openpgp + urn:xmpp:openpgp:0 + org.jivesoftware.smackx.ox.provider.OpenPgpElementProvider + + + + + pubkey + urn:xmpp:openpgp:0 + org.jivesoftware.smackx.ox.provider.PubkeyElementProvider + + + secretkey + urn:xmpp:openpgp:0 + org.jivesoftware.smackx.ox.provider.SecretkeyElementProvider + + + public-keys-list + urn:xmpp:openpgp:0 + org.jivesoftware.smackx.ox.provider.PublicKeysListElementProvider + + diff --git a/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/OpenPgpElementTest.java b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/OpenPgpElementTest.java new file mode 100644 index 000000000..cf2ea6c0c --- /dev/null +++ b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/OpenPgpElementTest.java @@ -0,0 +1,178 @@ +/** + * + * 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 static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertNotNull; +import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.test.util.SmackTestSuite; +import org.jivesoftware.smack.test.util.TestUtils; +import org.jivesoftware.smackx.ox.element.CryptElement; +import org.jivesoftware.smackx.ox.element.OpenPgpElement; +import org.jivesoftware.smackx.ox.element.SignElement; +import org.jivesoftware.smackx.ox.element.SigncryptElement; +import org.jivesoftware.smackx.ox.provider.CryptElementProvider; +import org.jivesoftware.smackx.ox.provider.OpenPgpElementProvider; +import org.jivesoftware.smackx.ox.provider.SignElementProvider; +import org.jivesoftware.smackx.ox.provider.SigncryptElementProvider; + +import org.junit.Test; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; +import org.xmlpull.v1.XmlPullParser; + +public class OpenPgpElementTest extends SmackTestSuite { + + private final Set recipients; + + // 2014-07-10T15:06:00.000+00:00 + private static final Date testDate = new Date(1405004760000L); + + public OpenPgpElementTest() throws XmppStringprepException { + super(); + Set jids = new HashSet<>(); + jids.add(JidCreate.bareFrom("alice@wonderland.lit")); + jids.add(JidCreate.bareFrom("bob@builder.lit")); + this.recipients = Collections.unmodifiableSet(jids); + } + + @Test + public void providerTest() throws Exception { + String expected = + "" + + "BASE64_OPENPGP_MESSAGE" + + ""; + + OpenPgpElement element = new OpenPgpElement("BASE64_OPENPGP_MESSAGE"); + + assertXMLEqual(expected, element.toXML(null).toString()); + + XmlPullParser parser = TestUtils.getParser(expected); + OpenPgpElement parsed = OpenPgpElementProvider.TEST_INSTANCE.parse(parser); + } + + @Test + public void simplifiedConstructorTest() { + ArrayList payload = new ArrayList<>(); + payload.add(new Message.Body("de", "Hallo Welt!")); + CryptElement element = new CryptElement(recipients, payload); + + assertNotNull(element.getRandomPadding()); + assertNotNull(element.getTimestamp()); + } + + @Test + public void signElementProviderTest() throws Exception { + String expected = + "" + + "" + + "" + + ""; + + List payload = new ArrayList<>(); + payload.add(new Message.Body("en", "Hello World!")); + SignElement element = new SignElement(recipients, testDate, payload); + + assertXMLEqual(expected, element.toXML(null).toString()); + + XmlPullParser parser = TestUtils.getParser(expected); + SignElement parsed = SignElementProvider.TEST_INSTANCE.parse(parser); + + assertEquals(element.getTimestamp(), parsed.getTimestamp()); + assertEquals(element.getTo(), parsed.getTo()); + assertEquals(element.getPayload(), parsed.getPayload()); + } + + @Test + public void cryptElementProviderTest() throws Exception { + String expected = + "" + + "" + + ""; + List payload = new ArrayList<>(); + payload.add(new Message.Body("en", "The cake is a lie.")); + Set to = new HashSet<>(); + to.add(JidCreate.bareFrom("alice@wonderland.lit")); + CryptElement element = new CryptElement(to, + "f0rm1l4n4-mT8y33j!Y%fRSrcd^ZE4Q7VDt1L%WEgR!kv", + testDate, + payload); + + assertXMLEqual(expected, element.toXML(null).toString()); + + XmlPullParser parser = TestUtils.getParser(expected); + CryptElement parsed = CryptElementProvider.TEST_INSTANCE.parse(parser); + + assertEquals(element.getTimestamp(), parsed.getTimestamp()); + assertEquals(element.getTo(), parsed.getTo()); + assertEquals(element.getPayload(), parsed.getPayload()); + assertEquals(element.getRandomPadding(), parsed.getRandomPadding()); + } + + @Test + public void signcryptElementProviderTest() throws Exception { + String expected = + "" + + "" + + ""; + + List payload = new ArrayList<>(); + payload.add(new Message.Body("en", "This is a secret message.")); + Set jids = new HashSet<>(); + jids.add(JidCreate.bareFrom("juliet@example.org")); + SigncryptElement element = new SigncryptElement(jids, + "f0rm1l4n4-mT8y33j!Y%fRSrcd^ZE4Q7VDt1L%WEgR!kv", + testDate, payload); + + assertXMLEqual(expected, element.toXML(null).toString()); + + XmlPullParser parser = TestUtils.getParser(expected); + SigncryptElement parsed = SigncryptElementProvider.TEST_INSTANCE.parse(parser); + + assertEquals(element.getTimestamp(), parsed.getTimestamp()); + assertEquals(element.getTo(), parsed.getTo()); + assertEquals(element.getPayload(), parsed.getPayload()); + assertEquals(element.getRandomPadding(), parsed.getRandomPadding()); + } + + +} diff --git a/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/PubkeyElementTest.java b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/PubkeyElementTest.java new file mode 100644 index 000000000..8553ce5bf --- /dev/null +++ b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/PubkeyElementTest.java @@ -0,0 +1,59 @@ +/** + * + * 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 static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertTrue; +import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; + +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Date; + +import org.jivesoftware.smack.test.util.SmackTestSuite; +import org.jivesoftware.smack.test.util.TestUtils; +import org.jivesoftware.smackx.ox.element.PubkeyElement; +import org.jivesoftware.smackx.ox.provider.PubkeyElementProvider; + +import org.junit.Test; +import org.jxmpp.util.XmppDateTime; +import org.xmlpull.v1.XmlPullParser; + +public class PubkeyElementTest extends SmackTestSuite { + + @Test + public void providerTest() throws Exception { + String expected = + "" + + "" + + "BASE64_OPENPGP_PUBLIC_KEY" + + "" + + ""; + + Date date = XmppDateTime.parseXEP0082Date("2018-01-21T10:46:21.000+00:00"); + byte[] key = "BASE64_OPENPGP_PUBLIC_KEY".getBytes(Charset.forName("UTF-8")); + PubkeyElement element = new PubkeyElement(new PubkeyElement.PubkeyDataElement(key), date); + + assertXMLEqual(expected, element.toXML(null).toString()); + + XmlPullParser parser = TestUtils.getParser(expected); + PubkeyElement parsed = PubkeyElementProvider.TEST_INSTANCE.parse(parser); + + assertEquals(element.getDate(), parsed.getDate()); + assertTrue(Arrays.equals(element.getDataElement().getB64Data(), parsed.getDataElement().getB64Data())); + } +} diff --git a/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/PublicKeysListElementTest.java b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/PublicKeysListElementTest.java new file mode 100644 index 000000000..ed7893e4d --- /dev/null +++ b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/PublicKeysListElementTest.java @@ -0,0 +1,93 @@ +/** + * + * 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 static junit.framework.TestCase.assertEquals; + +import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; + +import java.util.Date; + +import org.jivesoftware.smack.test.util.SmackTestSuite; +import org.jivesoftware.smack.test.util.TestUtils; +import org.jivesoftware.smackx.ox.element.PublicKeysListElement; +import org.jivesoftware.smackx.ox.provider.PublicKeysListElementProvider; + +import org.junit.Test; +import org.jxmpp.util.XmppDateTime; +import org.xmlpull.v1.XmlPullParser; + +public class PublicKeysListElementTest extends SmackTestSuite { + + @Test + public void providerTest() throws Exception { + String expected = + "" + + "" + + "" + + ""; + + Date date1 = XmppDateTime.parseDate("2018-03-01T15:26:12.000+00:00"); + Date date2 = XmppDateTime.parseDate("1953-05-16T12:00:00.000+00:00"); + PublicKeysListElement.PubkeyMetadataElement child1 = + new PublicKeysListElement.PubkeyMetadataElement( + "1357B01865B2503C18453D208CAC2A9678548E35", date1); + PublicKeysListElement.PubkeyMetadataElement child2 = + new PublicKeysListElement.PubkeyMetadataElement( + "67819B343B2AB70DED9320872C6464AF2A8E4C02", date2); + + PublicKeysListElement element = PublicKeysListElement.builder() + .addMetadata(child1) + .addMetadata(child2) + .build(); + + assertXMLEqual(expected, element.toXML(null).toString()); + + XmlPullParser parser = TestUtils.getParser(expected); + PublicKeysListElement parsed = PublicKeysListElementProvider.TEST_INSTANCE.parse(parser); + + assertEquals(element.getMetadata(), parsed.getMetadata()); + } + + @Test + public void listBuilderRefusesDuplicatesTest() { + PublicKeysListElement.Builder builder = PublicKeysListElement.builder(); + String fp40 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN"; + Date oneDate = new Date(12337883234L); + Date otherDate = new Date(8888348384L); + + // Check if size of metadata is one after insert. + builder.addMetadata(new PublicKeysListElement.PubkeyMetadataElement(fp40, oneDate)); + assertEquals(builder.build().getMetadata().size(), 1); + + // Check if size is still one after inserting element with same fp. + builder.addMetadata(new PublicKeysListElement.PubkeyMetadataElement(fp40, otherDate)); + assertEquals(builder.build().getMetadata().size(), 1); + } + + @Test(expected = IllegalArgumentException.class) + public void metadataFingerprintLengthTest() { + PublicKeysListElement.PubkeyMetadataElement element = + new PublicKeysListElement.PubkeyMetadataElement("thisIsNotTheCorrectLength", new Date()); + } +} diff --git a/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/SecretkeyElementTest.java b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/SecretkeyElementTest.java new file mode 100644 index 000000000..4e802aebc --- /dev/null +++ b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/SecretkeyElementTest.java @@ -0,0 +1,52 @@ +/** + * + * 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 static junit.framework.TestCase.assertTrue; +import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; + +import java.nio.charset.Charset; +import java.util.Arrays; + +import org.jivesoftware.smack.test.util.SmackTestSuite; +import org.jivesoftware.smack.test.util.TestUtils; +import org.jivesoftware.smackx.ox.element.SecretkeyElement; +import org.jivesoftware.smackx.ox.provider.SecretkeyElementProvider; + +import org.junit.Test; +import org.xmlpull.v1.XmlPullParser; + +public class SecretkeyElementTest extends SmackTestSuite { + + @Test + public void providerTest() throws Exception { + String expected = + "" + + "BASE64_OPENPGP_ENCRYPTED_SECRET_KEY" + + ""; + byte[] key = "BASE64_OPENPGP_ENCRYPTED_SECRET_KEY".getBytes(Charset.forName("UTF-8")); + + SecretkeyElement element = new SecretkeyElement(key); + + assertXMLEqual(expected, element.toXML(null).toString()); + + XmlPullParser parser = TestUtils.getParser(expected); + SecretkeyElement parsed = SecretkeyElementProvider.TEST_INSTANCE.parse(parser); + + assertTrue(Arrays.equals(element.getB64Data(), parsed.getB64Data())); + } +}