As it took me some time to figure it out, here I am sharing my code that, using PGP, encrypts/signs a JSON request to be the request body, and decrypts/verifies a response body to see the JSON response.
It’s in Groovy Java, using Bouncy-GPG library. It worked well.
How it works is described in the code comments.
import java.nio.charset.Charset import java.security.NoSuchAlgorithmException import java.security.NoSuchProviderException; import java.security.Security import java.security.SignatureException import name.neuhalfen.projects.crypto.bouncycastle.openpgp.BouncyGPG import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.KeyringConfigCallbacks 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.jce.provider.BouncyCastleProvider import org.bouncycastle.util.io.Streams class PayloadService { /** * On sending * * To encrypt request payload, to be the request body * * The PGP works as follow: * First, creates a key to encrypt the payload, * then encrypts the key using the recipient's public key. * Then encrypts the payload using that key. * Then signs the encrypted payload using the sender's signature, * so the recipient is sure that this is really from the sender. * * @param sourceText, i.e. the payload string * @param pubKeyRing, sender's public key ring, containing also the recipient's public key * @param privKeyRing, sender's private key ring * @param privKeyPwd, sender's private key password * @param sender, corresponds with user id in sender's key * @param recipient, corresponds with user id in recipient's key * * @return the encrypted message i.e. PGP message, must be set with UTF-8 */ String encryptAndSign(String sourceText, File pubKeyRing, File privKeyRing, String privKeyPwd, String sender, String recipient) throws IOException, PGPException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException { installBCProvider() KeyringConfig keyringConfig = KeyringConfigs.withKeyRingsFromFiles(pubKeyRing, privKeyRing, KeyringConfigCallbacks.withPassword(privKeyPwd)) ByteArrayOutputStream cipherStream = new ByteArrayOutputStream() OutputStream encryptionStream = BouncyGPG .encryptToStream() .withConfig(keyringConfig) .withStrongAlgorithms() .toRecipient(recipient) .andSignWith(sender) .armorAsciiOutput() .andWriteTo(cipherStream) encryptionStream.write(sourceText.getBytes()) encryptionStream.close() cipherStream.close() byte[] cipherBytes = cipherStream.toByteArray() return new String(cipherBytes, Charset.forName("UTF-8")) } /** * On receiving * * To decrypt response body, to see the response payload * * The PGP works as follows: * Decrypts the key (to open the payload) using recipient's private key. * It's possible because the key was encrypted using the recipient's public key. * Then, using that key, decrypts the payload. * Then, using the sender's signature, verifies if the payload is really * from the sender. * * @param cipherText, the PGP message to be decrypted * @param pubKeyRing, recipient's public key ring, containing also the sender's public key * @param privKeyRing, recipient's private key ring * @param privKeyPwd, recipient's private key password * @param sender, corresponds with user id in sender's key * * @return the original text, must be set with UTF-8 */ String decryptAndVerify(String cipherText, File pubKeyRing, File privKeyRing, String privKeyPwd, String sender) throws IOException, PGPException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException { installBCProvider() KeyringConfig keyringConfig = KeyringConfigs.withKeyRingsFromFiles(pubKeyRing, privKeyRing, KeyringConfigCallbacks.withPassword(privKeyPwd)) ByteArrayInputStream cipherStream = new ByteArrayInputStream(cipherText.getBytes()); InputStream decryptedStream = BouncyGPG .decryptAndVerifyStream() .withConfig(keyringConfig) .andRequireSignatureFromAllKeys(sender) .fromEncryptedInputStream(cipherStream) byte[] decryptedBytes = Streams.readAll(decryptedStream) return new String(decryptedBytes, Charset.forName("UTF-8")) } /** * Call this before all PGP works, * as we are using Jens Neuhalfen's library based on Bouncy Castle */ private void installBCProvider() { if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { Security.addProvider(new BouncyCastleProvider()) } } }