From 9ee47e1711921173b512d4d4346407551de56cd1 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 15 May 2018 21:12:03 +0200 Subject: [PATCH] BouncycastleOpenPgpProvider implementatioN --- .../BouncycastleOpenPgpProvider.java | 192 ++++++++++++------ .../ox/bouncycastle/BasicEncryptionTest.java | 66 +++++- .../BouncycastleOpenPgpProviderTest.java | 72 +++++++ .../ox/bouncycastle/KeyGenerationTest.java | 40 ++++ .../smackx/ox/OpenPgpKeyStore.java | 8 - .../smackx/ox/OpenPgpMessage.java | 12 +- .../smackx/ox/OpenPgpProvider.java | 8 +- .../ox/element/OpenPgpContentElement.java | 8 + .../smackx/ox/element/OpenPgpElement.java | 11 +- .../OpenPgpContentElementProvider.java | 17 +- 10 files changed, 346 insertions(+), 88 deletions(-) create mode 100644 smack-openpgp-bouncycastle/src/test/java/org/jivesoftware/smackx/ox/bouncycastle/BouncycastleOpenPgpProviderTest.java create mode 100644 smack-openpgp-bouncycastle/src/test/java/org/jivesoftware/smackx/ox/bouncycastle/KeyGenerationTest.java delete mode 100644 smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpKeyStore.java diff --git a/smack-openpgp-bouncycastle/src/main/java/org/jivesoftware/smackx/ox/bouncycastle/BouncycastleOpenPgpProvider.java b/smack-openpgp-bouncycastle/src/main/java/org/jivesoftware/smackx/ox/bouncycastle/BouncycastleOpenPgpProvider.java index c7fd4c4b8..3305a2ff5 100644 --- a/smack-openpgp-bouncycastle/src/main/java/org/jivesoftware/smackx/ox/bouncycastle/BouncycastleOpenPgpProvider.java +++ b/smack-openpgp-bouncycastle/src/main/java/org/jivesoftware/smackx/ox/bouncycastle/BouncycastleOpenPgpProvider.java @@ -16,108 +16,168 @@ */ package org.jivesoftware.smackx.ox.bouncycastle; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charset; -import java.security.KeyPair; -import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.Provider; -import java.security.SignatureException; import java.util.Date; -import java.util.Iterator; +import java.util.HashMap; +import java.util.Map; import java.util.Set; +import org.jivesoftware.smack.util.stringencoder.Base64; import org.jivesoftware.smackx.ox.OpenPgpMessage; import org.jivesoftware.smackx.ox.OpenPgpProvider; +import org.jivesoftware.smackx.ox.element.OpenPgpElement; +import org.jivesoftware.smackx.ox.element.PubkeyElement; import name.neuhalfen.projects.crypto.bouncycastle.openpgp.BouncyGPG; +import name.neuhalfen.projects.crypto.bouncycastle.openpgp.algorithms.PublicKeySize; import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.KeySelectionStrategy; -import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.Xep0373KeySelectionStrategy; +import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.KeyringConfigCallbacks; +import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.XmppKeySelectionStrategy; +import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.InMemoryKeyring; import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.KeyringConfig; -import org.bouncycastle.bcpg.HashAlgorithmTags; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.openpgp.PGPEncryptedData; +import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.KeyringConfigs; import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPKeyPair; +import org.bouncycastle.openpgp.PGPKeyRingGenerator; import org.bouncycastle.openpgp.PGPPublicKey; -import org.bouncycastle.openpgp.PGPSecretKey; -import org.bouncycastle.openpgp.PGPSignature; -import org.bouncycastle.openpgp.operator.PGPDigestCalculator; -import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; -import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder; -import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair; -import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder; +import org.bouncycastle.openpgp.PGPPublicKeyRing; +import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.util.io.Streams; import org.jxmpp.jid.BareJid; -import org.jxmpp.jid.Jid; public class BouncycastleOpenPgpProvider implements OpenPgpProvider { - public static final Provider PROVIDER = new BouncyCastleProvider(); + private final BareJid ourJid; + private final InMemoryKeyring ourKeys; + private final Long ourKeyId; + private final Map theirKeys = new HashMap<>(); + private final KeySelectionStrategy keySelectionStrategy = new XmppKeySelectionStrategy(new Date()); - private final KeyringConfig keyringConfig; - private final BareJid signingIdentity; - private final KeySelectionStrategy keySelectionStrategy = new Xep0373KeySelectionStrategy(new Date()); + @Override + public OpenPgpMessage decryptAndVerify(OpenPgpElement element, BareJid sender) throws Exception { + InMemoryKeyring decryptionConfig = KeyringConfigs.forGpgExportedKeys(KeyringConfigCallbacks.withUnprotectedKeys()); - public BouncycastleOpenPgpProvider(KeyringConfig config, BareJid signingIdentity) throws IOException, PGPException { - this.keyringConfig = config; - this.signingIdentity = signingIdentity; - } - - public OpenPgpMessage toOpenPgpMessage(InputStream is, Set recipients, Jid signer) - throws IOException, PGPException, NoSuchAlgorithmException, SignatureException, NoSuchProviderException { - - String[] to = new String[recipients.size()]; - Iterator it = recipients.iterator(); - for (int i = 0; i recipients) + throws Exception { + if (recipients.isEmpty()) { + throw new IllegalArgumentException("Set of recipients must not be empty"); + } + + InMemoryKeyring encryptionConfig = KeyringConfigs.forGpgExportedKeys(KeyringConfigCallbacks.withUnprotectedKeys()); + + // Add all recipients public keys to encryption config + for (BareJid recipient : recipients) { + KeyringConfig c = theirKeys.get(recipient); + for (PGPPublicKeyRing p : c.getPublicKeyRings()) { + encryptionConfig.addPublicKey(p.getPublicKey().getEncoded()); + } + } + + // Add our keys to encryption config + for (PGPPublicKeyRing p : ourKeys.getPublicKeyRings()) { + encryptionConfig.addPublicKey(p.getPublicKey().getEncoded()); + } + for (PGPSecretKeyRing s : ourKeys.getSecretKeyRings()) { + encryptionConfig.addSecretKey(s.getSecretKey().getEncoded()); + } + + String[] recipientUIDs = new String[recipients.size() + 1]; + int pos = 0; + for (BareJid b : recipients) { + recipientUIDs[pos++] = "xmpp:" + b.toString(); + } + recipientUIDs[pos] = "xmpp:" + ourJid.toString(); + + ByteArrayOutputStream encryptedOut = new ByteArrayOutputStream(); + + OutputStream encryptor = BouncyGPG.encryptToStream() + .withConfig(encryptionConfig) + .withKeySelectionStrategy(new XmppKeySelectionStrategy(new Date())) + .withOxAlgorithms() + .toRecipients(recipientUIDs) + .andSignWith("xmpp:" + ourJid.toString()) + .binaryOutput() + .andWriteTo(encryptedOut); + + Streams.pipeAll(inputStream, encryptor); + encryptor.close(); + + String base64 = Base64.encodeToString(encryptedOut.toByteArray()); + + return new OpenPgpElement(base64); } + + public static PGPKeyRingGenerator generateKey(BareJid owner, char[] passPhrase) throws NoSuchAlgorithmException, PGPException { + PGPKeyRingGenerator generator = BouncyGPG.createKeyPair() + .withRSAKeys() + .ofSize(PublicKeySize.RSA._2048) + .forIdentity("xmpp:" + owner.toString()) + .withPassphrase(passPhrase) + .build(); + return generator; + } + } diff --git a/smack-openpgp-bouncycastle/src/test/java/org/jivesoftware/smackx/ox/bouncycastle/BasicEncryptionTest.java b/smack-openpgp-bouncycastle/src/test/java/org/jivesoftware/smackx/ox/bouncycastle/BasicEncryptionTest.java index f684085f7..35d6b4a3d 100644 --- a/smack-openpgp-bouncycastle/src/test/java/org/jivesoftware/smackx/ox/bouncycastle/BasicEncryptionTest.java +++ b/smack-openpgp-bouncycastle/src/test/java/org/jivesoftware/smackx/ox/bouncycastle/BasicEncryptionTest.java @@ -38,13 +38,17 @@ import org.jivesoftware.smackx.ox.TestKeys; import name.neuhalfen.projects.crypto.bouncycastle.openpgp.BouncyGPG; import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.KeySelectionStrategy; import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.KeyringConfigCallbacks; -import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.Xep0373KeySelectionStrategy; +import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.XmppKeySelectionStrategy; import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.InMemoryKeyring; import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.KeyringConfig; import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.KeyringConfigs; import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPKeyRingGenerator; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.bouncycastle.openpgp.PGPSecretKey; import org.bouncycastle.util.io.Streams; import org.junit.Test; +import org.jxmpp.jid.impl.JidCreate; public class BasicEncryptionTest extends SmackTestSuite { @@ -55,7 +59,7 @@ public class BasicEncryptionTest extends SmackTestSuite { public BasicEncryptionTest() throws IOException, PGPException { super(); - // Prepare Juliets keyring + // Prepare Juliet's keyring keyringJuliet = KeyringConfigs.forGpgExportedKeys(KeyringConfigCallbacks.withUnprotectedKeys()); ((InMemoryKeyring) keyringJuliet).addSecretKey(TestKeys.JULIET_PRIV.getBytes(UTF8)); ((InMemoryKeyring) keyringJuliet).addPublicKey(TestKeys.JULIET_PUB.getBytes(UTF8)); @@ -71,12 +75,10 @@ public class BasicEncryptionTest extends SmackTestSuite { @Test public void encryptionTest() throws IOException, PGPException, NoSuchAlgorithmException, SignatureException, NoSuchProviderException { - - ByteArrayOutputStream result = new ByteArrayOutputStream(); - KeySelectionStrategy selectionStrategy = new Xep0373KeySelectionStrategy(new Date()); + KeySelectionStrategy selectionStrategy = new XmppKeySelectionStrategy(new Date()); - byte[] message = "Hello World!!!!".getBytes(UTF8); + byte[] message = "How long do you want these messages to remain secret?".getBytes(UTF8); // Encrypt OutputStream out = BouncyGPG.encryptToStream() @@ -108,4 +110,56 @@ public class BasicEncryptionTest extends SmackTestSuite { assertTrue(Arrays.equals(message, message2)); } + + @Test + public void encryptionWithFreshKeysTest() + throws IOException, PGPException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException { + final String alice = "alice@wonderland.lit"; + final String bob = "bob@builder.tv"; + PGPKeyRingGenerator g1 = BouncycastleOpenPgpProvider.generateKey(JidCreate.bareFrom(alice), null); + PGPKeyRingGenerator g2 = BouncycastleOpenPgpProvider.generateKey(JidCreate.bareFrom(bob), null); + PGPSecretKey s1 = g1.generateSecretKeyRing().getSecretKey(); + PGPSecretKey s2 = g2.generateSecretKeyRing().getSecretKey(); + PGPPublicKey p1 = g1.generatePublicKeyRing().getPublicKey(); + PGPPublicKey p2 = g2.generatePublicKeyRing().getPublicKey(); + + KeyringConfig c1 = KeyringConfigs.forGpgExportedKeys(KeyringConfigCallbacks.withUnprotectedKeys()); + KeyringConfig c2 = KeyringConfigs.forGpgExportedKeys(KeyringConfigCallbacks.withUnprotectedKeys()); + ((InMemoryKeyring) c1).addSecretKey(s1.getEncoded()); + ((InMemoryKeyring) c1).addPublicKey(p1.getEncoded()); + ((InMemoryKeyring) c1).addPublicKey(p2.getEncoded()); + ((InMemoryKeyring) c2).addSecretKey(s2.getEncoded()); + ((InMemoryKeyring) c2).addPublicKey(p2.getEncoded()); + ((InMemoryKeyring) c2).addPublicKey(p1.getEncoded()); + + ByteArrayOutputStream result = new ByteArrayOutputStream(); + + byte[] m1 = "I want them to remain secret for as long as men are capable of evil.".getBytes(UTF8); + OutputStream encrypt = BouncyGPG.encryptToStream() + .withConfig(c1) + .withKeySelectionStrategy(new XmppKeySelectionStrategy(new Date())) + .withOxAlgorithms() + .toRecipients("xmpp:" + alice, "xmpp:" + bob) + .andSignWith("xmpp:" + alice) + .binaryOutput() + .andWriteTo(result); + + encrypt.write(m1); + encrypt.close(); + + byte[] e1 = result.toByteArray(); + result.reset(); + + ByteArrayInputStream in = new ByteArrayInputStream(e1); + InputStream decrypt = BouncyGPG.decryptAndVerifyStream() + .withConfig(c2) + .withKeySelectionStrategy(new XmppKeySelectionStrategy(new Date())) + .andValidateSomeoneSigned() + .fromEncryptedInputStream(in); + + Streams.pipeAll(decrypt, result); + + byte[] m2 = result.toByteArray(); + assertTrue(Arrays.equals(m1, m2)); + } } diff --git a/smack-openpgp-bouncycastle/src/test/java/org/jivesoftware/smackx/ox/bouncycastle/BouncycastleOpenPgpProviderTest.java b/smack-openpgp-bouncycastle/src/test/java/org/jivesoftware/smackx/ox/bouncycastle/BouncycastleOpenPgpProviderTest.java new file mode 100644 index 000000000..05b77d433 --- /dev/null +++ b/smack-openpgp-bouncycastle/src/test/java/org/jivesoftware/smackx/ox/bouncycastle/BouncycastleOpenPgpProviderTest.java @@ -0,0 +1,72 @@ +/** + * + * Copyright 2018 Paul Schaub. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.smackx.ox.bouncycastle; + +import static junit.framework.TestCase.assertTrue; +import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; + +import java.security.Security; +import java.util.Collections; + +import org.jivesoftware.smack.packet.ExtensionElement; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.test.util.SmackTestSuite; +import org.jivesoftware.smackx.ox.OpenPgpMessage; +import org.jivesoftware.smackx.ox.element.OpenPgpContentElement; +import org.jivesoftware.smackx.ox.element.OpenPgpElement; +import org.jivesoftware.smackx.ox.element.PubkeyElement; +import org.jivesoftware.smackx.ox.element.SigncryptElement; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.junit.Test; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; + +public class BouncycastleOpenPgpProviderTest extends SmackTestSuite { + + @Test + public void encryptAndSign_decryptAndVerifyElementTest() throws Exception { + Security.addProvider(new BouncyCastleProvider()); + + // Create providers for alice and the cat + BareJid alice = JidCreate.bareFrom("alice@wonderland.lit"); + BareJid cheshire = JidCreate.bareFrom("cheshire@wonderland.lit"); + BouncycastleOpenPgpProvider aliceProvider = new BouncycastleOpenPgpProvider(alice); + BouncycastleOpenPgpProvider cheshireProvider = new BouncycastleOpenPgpProvider(cheshire); + + // dry exchange keys + PubkeyElement aliceKeys = aliceProvider.createPubkeyElement(); + PubkeyElement cheshireKeys = cheshireProvider.createPubkeyElement(); + aliceProvider.processRecipientsPublicKey(cheshire, cheshireKeys); + cheshireProvider.processRecipientsPublicKey(alice, aliceKeys); + + SigncryptElement signcryptElement = new SigncryptElement( + Collections.singleton(cheshire), + Collections.singletonList( + new Message.Body("en", "How do you know I’m mad?"))); + OpenPgpElement encrypted = aliceProvider.signAndEncrypt( + signcryptElement.toInputStream(), + Collections.singleton(cheshire)); + + OpenPgpMessage decrypted = cheshireProvider.decryptAndVerify(encrypted, alice); + OpenPgpContentElement content = decrypted.getOpenPgpContentElement(); + assertTrue(content instanceof SigncryptElement); + + assertXMLEqual(signcryptElement.toXML(null).toString(), content.toXML(null).toString()); + } +} diff --git a/smack-openpgp-bouncycastle/src/test/java/org/jivesoftware/smackx/ox/bouncycastle/KeyGenerationTest.java b/smack-openpgp-bouncycastle/src/test/java/org/jivesoftware/smackx/ox/bouncycastle/KeyGenerationTest.java new file mode 100644 index 000000000..10e85271d --- /dev/null +++ b/smack-openpgp-bouncycastle/src/test/java/org/jivesoftware/smackx/ox/bouncycastle/KeyGenerationTest.java @@ -0,0 +1,40 @@ +/** + * + * Copyright 2018 Paul Schaub. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.smackx.ox.bouncycastle; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertTrue; + +import name.neuhalfen.projects.crypto.bouncycastle.openpgp.algorithms.PublicKeyType; +import org.bouncycastle.openpgp.PGPSecretKey; +import org.junit.Test; +import org.jxmpp.jid.impl.JidCreate; + +public class KeyGenerationTest { + + @Test + public void createSecretKey() throws Exception { + PGPSecretKey secretKey = BouncycastleOpenPgpProvider + .generateKey(JidCreate.bareFrom("alice@wonderland.lit"), null) + .generateSecretKeyRing() + .getSecretKey(); + assertEquals(PublicKeyType.RSA_GENERAL.getId(), secretKey.getPublicKey().getAlgorithm()); + assertTrue(secretKey.getPublicKey().isEncryptionKey()); + assertEquals(2048, secretKey.getPublicKey().getBitStrength()); + assertEquals("xmpp:alice@wonderland.lit", secretKey.getPublicKey().getUserIDs().next()); + } +} diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpKeyStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpKeyStore.java deleted file mode 100644 index 2f0850164..000000000 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpKeyStore.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.jivesoftware.smackx.ox; - -public class OpenPgpKeyStore { - - public OpenPgpKeyStore() { - - } -} 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 60db44b96..f438169d3 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 @@ -36,7 +36,7 @@ public class OpenPgpMessage { } private final String element; - private final State state; + private State state; private OpenPgpContentElement openPgpContentElement; @@ -56,6 +56,16 @@ public class OpenPgpMessage { return; openPgpContentElement = OpenPgpContentElementProvider.parseOpenPgpContentElement(element); + if (state == null) { + if (openPgpContentElement instanceof SigncryptElement) { + state = State.signcrypt; + } else if (openPgpContentElement instanceof SignElement) { + state = State.sign; + } else { + state = State.crypt; + } + return; + } switch (state) { case signcrypt: if (!(openPgpContentElement instanceof SigncryptElement)) { 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 1fd7631b9..a50505549 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 @@ -17,9 +17,15 @@ package org.jivesoftware.smackx.ox; import java.io.InputStream; +import java.util.Set; + +import org.jivesoftware.smackx.ox.element.OpenPgpElement; + +import org.jxmpp.jid.BareJid; public interface OpenPgpProvider { - OpenPgpMessage toOpenPgpMessage(InputStream is); + OpenPgpMessage decryptAndVerify(OpenPgpElement element, BareJid sender) throws Exception; + OpenPgpElement signAndEncrypt(InputStream inputStream, Set recipients) throws Exception; } 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 0a560e2f4..261faae17 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 @@ -16,6 +16,9 @@ */ package org.jivesoftware.smackx.ox.element; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.Charset; import java.util.Date; import java.util.List; import java.util.Set; @@ -99,4 +102,9 @@ public abstract class OpenPgpContentElement implements ExtensionElement { } xml.closeElement(ELEM_PAYLOAD); } + + public InputStream toInputStream() { + byte[] encoded = toXML(null).toString().getBytes(Charset.forName("UTF-8")); + return new ByteArrayInputStream(encoded); + } } 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 d3ce1d711..6f154b3db 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 @@ -25,6 +25,7 @@ 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.jivesoftware.smackx.ox.OpenPgpProvider; import org.xmlpull.v1.XmlPullParserException; @@ -47,7 +48,7 @@ public class OpenPgpElement implements ExtensionElement { this.base64EncodedOpenPgpMessage = base64EncodedOpenPgpMessage; } - public OpenPgpMessage getOpenPgpMessage() { + public OpenPgpMessage getOpenPgpMessage(OpenPgpProvider provider) { if (openPgpMessage == null) { ensureOpenPgpMessageBytesSet(); InputStream is = new ByteArrayInputStream(openPgpMessageBytes); @@ -57,14 +58,18 @@ public class OpenPgpElement implements ExtensionElement { return openPgpMessage; } - public OpenPgpContentElement getContentElement() throws XmlPullParserException, IOException { + public OpenPgpContentElement getContentElement(OpenPgpProvider provider) throws XmlPullParserException, IOException { if (openPgpContentElement == null) { - openPgpContentElement = getOpenPgpMessage().getOpenPgpContentElement(); + openPgpContentElement = getOpenPgpMessage(provider).getOpenPgpContentElement(); } return openPgpContentElement; } + public String getEncryptedBase64MessageContent() { + return base64EncodedOpenPgpMessage; + } + @Override public String getElementName() { return ELEMENT; 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 79c32bc7b..e75f6f59d 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 @@ -55,9 +55,20 @@ public abstract class OpenPgpContentElementProvider