Wip: Use xep-0285 as replacement for xmlsec

This commit is contained in:
Paul Schaub 2020-09-21 11:33:17 +02:00
parent 58740c4a69
commit a2cad37e48
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
19 changed files with 554 additions and 78 deletions

View File

@ -21,9 +21,6 @@ dependencies {
api "org.jxmpp:jxmpp-core:1.0.1"
api "org.jxmpp:jxmpp-jid:1.0.1"
api "org.apache.santuario:xmlsec:2.2.0"
testImplementation "org.igniterealtime.smack:smack-java7:$smackJava7Version"
// RxJava2

View File

@ -1,8 +1,6 @@
package org.jivesoftware.smackx.ikey;
import org.apache.xml.security.c14n.CanonicalizationException;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.c14n.InvalidCanonicalizerException;
import org.apache.xml.security.parser.XMLParserException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.jivesoftware.smack.Manager;
@ -10,13 +8,10 @@ import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.util.Async;
import org.jivesoftware.smackx.ikey.element.IkeyElement;
import org.jivesoftware.smackx.ikey.mechanism.IkeySignatureVerificationMechanism;
import org.jivesoftware.smackx.ikey.util.IkeyConstants;
import org.jivesoftware.smackx.ikey.util.UnsupportedSignatureAlgorithmException;
import org.jivesoftware.smackx.ikey.util.canonicalization.ElementCanonicalizer;
import org.jivesoftware.smackx.ikey.util.canonicalization.XmlSecElementCanonicalizer;
import org.jivesoftware.smackx.ikey_ox.OxIkeySignatureVerificationMechanism;
import org.jivesoftware.smackx.pep.PepEventListener;
import org.jivesoftware.smackx.pep.PepManager;
@ -41,15 +36,9 @@ public final class IkeyManager extends Manager {
private static final Map<XMPPConnection, IkeyManager> INSTANCES = new WeakHashMap<>();
private IkeyStore store;
private final ElementCanonicalizer canonicalizer;
private IkeyManager(XMPPConnection connection) {
super(connection);
try {
this.canonicalizer = new XmlSecElementCanonicalizer(Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N11_OMIT_COMMENTS));
} catch (InvalidCanonicalizerException e) {
throw new AssertionError(e);
}
}
public static synchronized IkeyManager getInstanceFor(XMPPConnection connection) {
@ -106,7 +95,7 @@ public final class IkeyManager extends Manager {
}
private void processIkeyElement(EntityBareJid from, IkeyElement element)
throws XMLParserException, IOException, CanonicalizationException, UnsupportedSignatureAlgorithmException {
throws IOException, UnsupportedSignatureAlgorithmException {
if (isFromTheFuture(element)) {
LOGGER.log(Level.WARNING, "Received ikey element appears to be from the future: " + element.getSubordinates().getTimestamp());
return;
@ -126,9 +115,9 @@ public final class IkeyManager extends Manager {
}
private boolean verifyIkeyElement(EntityBareJid from, IkeyElement element)
throws XMLParserException, IOException, CanonicalizationException, UnsupportedSignatureAlgorithmException {
throws IOException, UnsupportedSignatureAlgorithmException {
IkeySignatureVerificationMechanism verificationMechanism = getSignatureVerificationMechanismFor(element);
IkeySignatureVerifier verifier = new IkeySignatureVerifier(verificationMechanism, canonicalizer);
IkeySignatureVerifier verifier = new IkeySignatureVerifier(verificationMechanism);
return verifier.verify(element, from);
}
@ -168,7 +157,7 @@ public final class IkeyManager extends Manager {
public void onPepEvent(EntityBareJid from, IkeyElement event, String id, Message carrierMessage) {
try {
processIkeyElement(from, event);
} catch (XMLParserException | CanonicalizationException | IOException | UnsupportedSignatureAlgorithmException e) {
} catch (IOException | UnsupportedSignatureAlgorithmException e) {
LOGGER.log(Level.WARNING, "Error:", e);
}
}

View File

@ -1,7 +1,5 @@
package org.jivesoftware.smackx.ikey;
import org.apache.xml.security.c14n.CanonicalizationException;
import org.apache.xml.security.parser.XMLParserException;
import org.bouncycastle.util.encoders.Base64;
import org.jivesoftware.smackx.ikey.element.IkeyElement;
import org.jivesoftware.smackx.ikey.mechanism.IkeySignatureVerificationMechanism;
@ -21,7 +19,7 @@ public class IkeySignatureVerifier {
}
public boolean verify(IkeyElement element, EntityBareJid owner)
throws XMLParserException, IOException, CanonicalizationException {
throws IOException {
throwIfMismatchingMechanism(element);
throwIfMismatchingOwnerJid(element, owner);

View File

@ -22,13 +22,11 @@ public class IkeyElement implements ExtensionElement {
private final IkeyType type;
private final SuperordinateElement superordinate;
private final SubordinateListElement subordinates;
private final ProofElement proof;
public IkeyElement(IkeyType type, SuperordinateElement superordinate, SubordinateListElement subordinates, ProofElement proof) {
public IkeyElement(IkeyType type, SuperordinateElement superordinate, SubordinateListElement subordinates) {
this.type = type;
this.superordinate = superordinate;
this.subordinates = subordinates;
this.proof = proof;
}
public IkeyType getType() {
@ -43,10 +41,6 @@ public class IkeyElement implements ExtensionElement {
return subordinates;
}
public ProofElement getProof() {
return proof;
}
@Override
public String getNamespace() {
return NAMESPACE;
@ -64,7 +58,6 @@ public class IkeyElement implements ExtensionElement {
.rightAngleBracket()
.append(getSuperordinate())
.append(getSubordinates())
.append(getProof())
.closeElement(this);
}
@ -75,7 +68,6 @@ public class IkeyElement implements ExtensionElement {
.append(getType())
.append(getSuperordinate())
.append(getSubordinates())
.append(getProof())
.build();
}
@ -85,7 +77,6 @@ public class IkeyElement implements ExtensionElement {
.append(getElementName(), o.getElementName())
.append(getType(), o.getType())
.append(getSuperordinate(), o.getSuperordinate())
.append(getSubordinates(), o.getSubordinates())
.append(getProof(), o.getProof()));
.append(getSubordinates(), o.getSubordinates()));
}
}

View File

@ -16,16 +16,13 @@ public class SubordinateListElement implements NamedElement {
public static final String NAMESPACE = IkeyConstants.NAMESPACE;
public static final String ELEMENT = "subordinates";
public static final String ATTR_STAMP = "stamp";
public static final String ATTR_JID = "jid";
private final List<SubordinateElement> subordinates;
private final EntityBareJid jid;
private final Date timestamp;
public SubordinateListElement(EntityBareJid jid, Date timestamp, List<SubordinateElement> subordinates) {
public SubordinateListElement(EntityBareJid jid, List<SubordinateElement> subordinates) {
this.jid = jid;
this.timestamp = timestamp;
this.subordinates = Objects.requireNonNullNorEmpty(subordinates, "List of subordinates MUST NOT be null nor empty.");
}
@ -33,10 +30,6 @@ public class SubordinateListElement implements NamedElement {
return jid;
}
public Date getTimestamp() {
return timestamp;
}
public List<SubordinateElement> getSubordinates() {
return subordinates;
}
@ -50,7 +43,6 @@ public class SubordinateListElement implements NamedElement {
public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
return new XmlStringBuilder(this)
.attribute(ATTR_JID, getJid())
.attribute(ATTR_STAMP, getTimestamp())
.rightAngleBracket()
.append(getSubordinates())
.closeElement(this);
@ -61,7 +53,6 @@ public class SubordinateListElement implements NamedElement {
return HashCode.builder()
.append(getElementName())
.append(getJid())
.append(getTimestamp())
.append(getSubordinates())
.build();
}
@ -71,7 +62,6 @@ public class SubordinateListElement implements NamedElement {
return EqualsUtil.equals(this, other, (e, o) -> e
.append(getElementName(), o.getElementName())
.append(getJid(), o.getJid())
.append(getTimestamp(), o.getTimestamp())
.append(getSubordinates(), o.getSubordinates()));
}
}

View File

@ -0,0 +1,20 @@
package org.jivesoftware.smackx.signed.xep0285;
import org.bouncycastle.openpgp.PGPSignature;
import org.jivesoftware.smackx.signed.xep0285.element.DataElement;
import org.jivesoftware.smackx.signed.xep0285.element.PlainElement;
import org.jivesoftware.smackx.signed.xep0285.element.SignatureElement;
import org.jivesoftware.smackx.signed.xep0285.element.SignedElement;
import org.jivesoftware.smackx.signed.xep0285.signing.Signer;
import java.io.IOException;
public class EncapsulatingSignatureManager {
public static SignedElement createSignedElement(PlainElement plainElement, Signer signer) throws IOException {
DataElement dataElement = DataElement.fromPlainElement(plainElement);
PGPSignature signature = signer.createSignature(dataElement.getUtf8Bytes());
SignatureElement signatureElement = SignatureElement.fromBytes(signer.getAlgorithmName(signature), signature.getEncoded());
return new SignedElement(signatureElement, dataElement);
}
}

View File

@ -0,0 +1,58 @@
package org.jivesoftware.smackx.signed.xep0285.element;
import org.jivesoftware.smack.packet.NamedElement;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smack.util.stringencoder.Base64;
import java.nio.charset.StandardCharsets;
public final class DataElement implements NamedElement {
public static final String ELEMENT = "data";
private final String base64Content;
private final String utf8Content;
private DataElement(String utf8Content, String base64Content) {
this.utf8Content = utf8Content;
this.base64Content = base64Content;
}
public static DataElement fromUtf8Content(String utf8Content) {
return new DataElement(utf8Content, Base64.encodeToString(utf8Content.getBytes(StandardCharsets.UTF_8)));
}
public static DataElement fromBase64Content(String base64Content) {
return new DataElement(Base64.decodeToString(base64Content), base64Content);
}
public static DataElement fromPlainElement(PlainElement element) {
return fromUtf8Content(element.toXML().toString());
}
public String getUtf8Content() {
return utf8Content;
}
public byte[] getUtf8Bytes() {
return getUtf8Content().getBytes(StandardCharsets.UTF_8);
}
public String getBase64Content() {
return base64Content;
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
return new XmlStringBuilder(this)
.rightAngleBracket()
.append(getBase64Content())
.closeElement(this);
}
}

View File

@ -0,0 +1,92 @@
package org.jivesoftware.smackx.signed.xep0285.element;
import org.jivesoftware.smack.packet.ExtensionElement;
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;
import java.nio.charset.StandardCharsets;
import java.util.Date;
public final class PlainElement implements ExtensionElement {
public static final String ELEMENT = "plain";
public static final String NAMESPACE = "urn:xmpp:signed:0";
public static final String ATTR_TIMESTAMP = "timestamp";
private final String utf8Content;
private final String base64Content;
private final Date timestamp;
private PlainElement(String utf8Content, String base64Content, Date timestamp) {
this.utf8Content = utf8Content;
this.base64Content = base64Content;
this.timestamp = timestamp;
}
public static PlainElement fromExtensionElement(ExtensionElement element) {
return fromUtf8String(element.toXML().toString(), new Date());
}
public static PlainElement fromUtf8String(String utf8, Date timestamp) {
return new PlainElement(utf8, Base64.encodeToString(utf8.getBytes(StandardCharsets.UTF_8)), timestamp);
}
public static PlainElement fromBase64String(String base64, Date timestamp) {
return new PlainElement(Base64.decodeToString(base64), base64, timestamp);
}
public String getBase64Content() {
return base64Content;
}
public String getUtf8Content() {
return utf8Content;
}
public byte[] asUtf8Bytes() {
return toXML().toString().getBytes(StandardCharsets.UTF_8);
}
public Date getTimestamp() {
return timestamp;
}
@Override
public String getNamespace() {
return NAMESPACE;
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
return new XmlStringBuilder(this)
.attribute(ATTR_TIMESTAMP, getTimestamp())
.rightAngleBracket()
.append(getBase64Content())
.closeElement(this);
}
@Override
public boolean equals(Object other) {
return EqualsUtil.equals(this, other, (e, o) -> e
.append(getElementName(), o.getElementName())
.append(getBase64Content(), o.getBase64Content())
.append(getTimestamp(), o.getTimestamp()));
}
@Override
public int hashCode() {
return HashCode.builder()
.append(getElementName())
.append(getBase64Content())
.append(getTimestamp())
.build();
}
}

View File

@ -0,0 +1,56 @@
package org.jivesoftware.smackx.signed.xep0285.element;
import org.jivesoftware.smack.packet.NamedElement;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smack.util.stringencoder.Base64;
public final class SignatureElement implements NamedElement {
public static final String ELEMENT = "signature";
public static final String ATTR_ALGORITHM = "algorithm";
private final String algorithm;
private final byte[] bytes;
private final String base64Content;
private SignatureElement(String algorithm, byte[] bytes, String base64Content) {
this.algorithm = algorithm;
this.bytes = bytes;
this.base64Content = base64Content;
}
public static SignatureElement fromBytes(String algorithm, byte[] bytes) {
return new SignatureElement(algorithm, bytes, Base64.encodeToString(bytes));
}
public static SignatureElement fromBase64Content(String algorithm, String base64Content) {
return new SignatureElement(algorithm, Base64.decode(base64Content), base64Content);
}
public String getAlgorithm() {
return algorithm;
}
public String getBase64Content() {
return base64Content;
}
public byte[] getBytes() {
return bytes.clone();
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
return new XmlStringBuilder(this)
.attribute(ATTR_ALGORITHM, getAlgorithm())
.rightAngleBracket()
.append(getBase64Content())
.closeElement(this);
}
}

View File

@ -0,0 +1,45 @@
package org.jivesoftware.smackx.signed.xep0285.element;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.util.XmlStringBuilder;
public class SignedElement implements ExtensionElement {
public static final String ELEMENT = "signed";
private final SignatureElement signature;
private final DataElement data;
public SignedElement(SignatureElement signature, DataElement data) {
this.signature = signature;
this.data = data;
}
public SignatureElement getSignature() {
return signature;
}
public DataElement getData() {
return data;
}
@Override
public String getNamespace() {
return PlainElement.NAMESPACE;
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
return new XmlStringBuilder(this)
.rightAngleBracket()
.append(getSignature())
.append(getData())
.closeElement(this);
}
}

View File

@ -0,0 +1,20 @@
package org.jivesoftware.smackx.signed.xep0285.provider;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.signed.xep0285.element.PlainElement;
import java.io.IOException;
public class PlainElementProvider extends ExtensionElementProvider<PlainElement> {
@Override
public PlainElement parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment)
throws XmlPullParserException, IOException, SmackParsingException {
String timestamp = ParserUtils.getRequiredAttribute(parser, PlainElement.ATTR_TIMESTAMP);
return PlainElement.fromBase64String(parser.nextText(), ParserUtils.getDateFromXep82String(timestamp));
}
}

View File

@ -0,0 +1,45 @@
package org.jivesoftware.smackx.signed.xep0285.provider;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.signed.xep0285.element.DataElement;
import org.jivesoftware.smackx.signed.xep0285.element.SignatureElement;
import org.jivesoftware.smackx.signed.xep0285.element.SignedElement;
import java.io.IOException;
public class SignedElementProvider extends ExtensionElementProvider<SignedElement> {
@Override
public SignedElement parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment)
throws XmlPullParserException, IOException {
SignatureElement signature = null;
DataElement data = null;
XmlPullParser.TagEvent tag;
String name;
do {
tag = parser.nextTag();
name = parser.getName();
if (tag == XmlPullParser.TagEvent.START_ELEMENT) {
switch (name) {
case SignatureElement.ELEMENT:
String algorithm = ParserUtils.getRequiredAttribute(parser, SignatureElement.ATTR_ALGORITHM);
signature = SignatureElement.fromBase64Content(algorithm, parser.nextText());
break;
case DataElement.ELEMENT:
data = DataElement.fromBase64Content(parser.nextText());
break;
}
}
} while (parser.getDepth() != initialDepth);
return new SignedElement(Objects.requireNonNull(signature), Objects.requireNonNull(data));
}
}

View File

@ -0,0 +1,74 @@
package org.jivesoftware.smackx.signed.xep0285.signing;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.util.io.Streams;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.HashAlgorithm;
import org.pgpainless.algorithm.PublicKeyAlgorithm;
import org.pgpainless.decryption_verification.OpenPgpMetadata;
import org.pgpainless.encryption_signing.EncryptionStream;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class OpenPGPSigner implements Signer {
private final SecretKeyRingProtector protector;
private final PGPSecretKeyRing secretKey;
public OpenPGPSigner(PGPSecretKeyRing secretKey, SecretKeyRingProtector protector) {
this.protector = protector;
this.secretKey = secretKey;
}
@Override
public PGPSignature createSignature(byte[] data) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
try {
EncryptionStream signer = PGPainless.createEncryptor().onOutputStream(outputStream)
.doNotEncrypt()
.createDetachedSignature()
.signWith(protector, secretKey)
.noArmor();
Streams.pipeAll(inputStream, signer);
signer.close();
inputStream.close();
outputStream.close();
OpenPgpMetadata metadata = signer.getResult();
return metadata.getSignatures().iterator().next();
} catch (PGPException e) {
throw new IOException(e);
}
}
@Override
public String getAlgorithmName(PGPSignature signature) {
PublicKeyAlgorithm signAlgo = PublicKeyAlgorithm.fromId(signature.getKeyAlgorithm());
String signAlgoName;
switch (signAlgo) {
case RSA_GENERAL:
case RSA_ENCRYPT:
case RSA_SIGN:
signAlgoName = "RSA";
break;
case DSA:
signAlgoName = "DSA";
break;
case ECDSA:
signAlgoName = "ECDSA";
break;
default:
throw new IllegalArgumentException("Signature was signed with unknown signature algorithm: " + signature.getKeyAlgorithm());
}
signAlgoName += HashAlgorithm.fromId(signature.getHashAlgorithm());
return signAlgoName;
}
}

View File

@ -0,0 +1,12 @@
package org.jivesoftware.smackx.signed.xep0285.signing;
import org.bouncycastle.openpgp.PGPSignature;
import java.io.IOException;
public interface Signer {
PGPSignature createSignature(byte[] data) throws IOException;
String getAlgorithmName(PGPSignature signature);
}

View File

@ -3,7 +3,13 @@ package org.jivesoftware.smackx.util;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.util.stringencoder.Base64;
import org.jivesoftware.smack.xml.SmackXmlParser;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.security.Security;
public class MercurySmackTestSuite {
@ -35,4 +41,39 @@ public class MercurySmackTestSuite {
Security.addProvider(new BouncyCastleProvider());
}
public static XmlPullParser getParser(String string) {
return getParser(string, null);
}
public static XmlPullParser getParser(String string, String startTag) {
return getParser(new StringReader(string), startTag);
}
private static XmlPullParser getParser(Reader reader, String startTag) {
XmlPullParser parser;
try {
parser = SmackXmlParser.newXmlParser(reader);
if (startTag == null) {
while (parser.getEventType() != XmlPullParser.Event.START_ELEMENT) {
parser.next();
}
return parser;
}
boolean found = false;
while (!found) {
if ((parser.next() == XmlPullParser.Event.START_ELEMENT) && parser.getName().equals(startTag))
found = true;
}
if (!found)
throw new IllegalArgumentException("Can not find start tag '" + startTag + "'");
} catch (XmlPullParserException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
return parser;
}
}

View File

@ -59,38 +59,4 @@ public class IkeyElementTest extends MercurySmackTestSuite {
return new SubordinateListElement(jid, date, Arrays.asList(subordinateElements));
}
public static XmlPullParser getParser(String string) {
return getParser(string, null);
}
public static XmlPullParser getParser(String string, String startTag) {
return getParser(new StringReader(string), startTag);
}
private static XmlPullParser getParser(Reader reader, String startTag) {
XmlPullParser parser;
try {
parser = SmackXmlParser.newXmlParser(reader);
if (startTag == null) {
while (parser.getEventType() != XmlPullParser.Event.START_ELEMENT) {
parser.next();
}
return parser;
}
boolean found = false;
while (!found) {
if ((parser.next() == XmlPullParser.Event.START_ELEMENT) && parser.getName().equals(startTag))
found = true;
}
if (!found)
throw new IllegalArgumentException("Can not find start tag '" + startTag + "'");
} catch (XmlPullParserException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
return parser;
}
}

View File

@ -0,0 +1,42 @@
package org.jivesoftware.smackx.signed.xep0285;
import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.signed.xep0285.element.PlainElement;
import org.jivesoftware.smackx.signed.xep0285.provider.PlainElementProvider;
import org.jivesoftware.smackx.util.MercurySmackTestSuite;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class PlainElementTest extends MercurySmackTestSuite {
@Test
public void test() throws XmlPullParserException, IOException, SmackParsingException {
String plain = "<message xmlns=\"jabber:client\" " +
"from=\"juliet@capulet.net/balcony\" " +
"to=\"romeo@montegue.net\" " +
"type=\"chat\">" +
"<thread>c6373824-a307-40dd-8fe0-bad6e7299ad0</thread>" +
"<body>Wherefore art thou, Romeo?</body>" +
"</message>";
String example2 = "<plain xmlns=\"urn:xmpp:signed:0\" " +
"timestamp=\"2010-06-29T02:15:21.012+00:00\">" +
"PG1lc3NhZ2UgeG1sbnM9ImphYmJlcjpjbGllbnQiIGZyb209Imp1bGlldEBjYXB" +
"1bGV0Lm5ldC9iYWxjb255IiB0bz0icm9tZW9AbW9udGVndWUubmV0IiB0eXBlPS" +
"JjaGF0Ij48dGhyZWFkPmM2MzczODI0LWEzMDctNDBkZC04ZmUwLWJhZDZlNzI5O" +
"WFkMDwvdGhyZWFkPjxib2R5PldoZXJlZm9yZSBhcnQgdGhvdSwgUm9tZW8/PC9i" +
"b2R5PjwvbWVzc2FnZT4=" +
"</plain>";
PlainElement parsed = new PlainElementProvider()
.parse(getParser(example2));
PlainElement fromPlain = PlainElement.fromUtf8String(plain, ParserUtils.getDateFromXep82String("2010-06-29T02:15:21.012+00:00"));
assertEquals(parsed, fromPlain);
assertEquals(plain, parsed.getUtf8Content());
}
}

View File

@ -0,0 +1,40 @@
package org.jivesoftware.smackx.signed.xep0285;
import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.signed.xep0285.element.SignedElement;
import org.jivesoftware.smackx.signed.xep0285.provider.SignedElementProvider;
import org.jivesoftware.smackx.util.MercurySmackTestSuite;
import org.junit.jupiter.api.Test;
import java.io.IOException;
public class SignedElementTest extends MercurySmackTestSuite {
@Test
public void test() throws XmlPullParserException, IOException, SmackParsingException {
String example3 =
"<signed xmlns=\"urn:xmpp:signed:0\">" +
"<signature algorithm=\"RSA-SHA1\">" +
"DxbxIziY1C1Ytcxkj0IFLsfmDLMv96JMlMAQZ7jh49IbsOIPsxI2LyLmqhKH/994UXDJKQLHvLJz" +
"gAmw8V2b+zmyZeItJzSmB+HHiLFVXkD2Dd4JfetsafsfIcB7uNWg0gAeiKrTHfFgiyEC/2WxwOj3" +
"JUMRyQ9ykEPIzS0GZ/k=" +
"</signature>" +
"<data>" +
"PHBsYWluIHhtbG5zPSJ1cm46eG1wcDpzaWduZWQ6MCIgdGltZXN0YW1wPSIyMDEwLTA2LTI5VDAy" +
"OjE1OjIxLjAxMloiPgogIFBHMWxjM05oWjJVZ2VHMXNibk05SW1waFltSmxjanBqYkdsbGJuUWlJ" +
"R1p5YjIwOUltcDFiR2xsZEVCallYQgogIDFiR1YwTG01bGRDOWlZV3hqYjI1NUlpQjBiejBpY205" +
"dFpXOUFiVzl1ZEdWbmRXVXVibVYwSWlCMGVYQmxQUwogIEpqYUdGMElqNDhkR2h5WldGa1BtTTJN" +
"emN6T0RJMExXRXpNRGN0TkRCa1pDMDRabVV3TFdKaFpEWmxOekk1TwogIFdGa01Ed3ZkR2h5WldG" +
"a1BqeGliMlI1UGxkb1pYSmxabTl5WlNCaGNuUWdkR2h2ZFN3Z1VtOXRaVzgvUEM5aQogIGIyUjVQ" +
"and2YldWemMyRm5aVDQ9CjwvcGxhaW4+Cg==" +
"</data>" +
"</signed>";
SignedElement signedElement = new SignedElementProvider()
.parse(getParser(example3));
System.out.println(example3);
System.out.println(signedElement.toXML());
}
}

@ -1 +1 @@
Subproject commit 38bfe2492149cb095a1376080320e37c71832504
Subproject commit 1c822dcaa4d4cb92d8b2d048f49bb69885143d56