Giter VIP home page Giter VIP logo

bouncy-gpg's People

Contributors

ispringer avatar jayceekay avatar mdesmons avatar neuhalje avatar neustradamus avatar sauhardstark avatar user9209 avatar vanitasvitae avatar xsavikx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bouncy-gpg's Issues

unknown packet type encountered: 20 error is coming when decrypt

Describe the bug
I created gpg keys(public/private) and managed to successfully encrypt/decrypt files using keys in command line.
Encrypt : gpg --batch --armor --passphrase "PASSWORD" -se --recipient "RECIPIENT" FILE.txt

it generated .asc file and i managed to decrypt it using bellow command
Decrypt: gpg --yes --batch --passphrase "PASSWORD" FILE.txt.asc

But when i try to decrypt the same file in code, I am getting "unknown packet type encountered: 20" error

Sample Code:
{
System.out.println("Initializing Bouncy Castle");

    BouncyGPG.registerProvider();

    System.out.println("Creating keyring");

//I am providing pub/keys as strings
final InMemoryKeyring keyring = KeyringConfigs
.forGpgExportedKeys(KeyringConfigCallbacks.withPassword("passwod"));
keyring.addSecretKey(BPAY_PRIVATE.getBytes());
keyring.addPublicKey(BPAY_PUBLIC.getBytes());

    final InputStream cipherTextStream = Files.newInputStream(Path.of("FILE.txt.asc"));

    final InputStream decryptedInputStream = BouncyGPG
            .decryptAndVerifyStream()
            .withConfig(keyring)
            .andRequireSignatureFromAllKeys("USERID")
            .fromEncryptedInputStream(cipherTextStream);

    byte[] plain = new byte[2048];
    int len = decryptedInputStream.read(plain);

    String plainText = new String(plain, 0, len);
    System.out.println(plainText);

}

A way to encrypt with just a public key

Describe the bug
it is normal for third parties to give you a public key to encrypt a file you will send to them, i.e: they don't give you anything else, and the key is not signed. Currently the library requires a recipient address (which if I understand correctly is to search for the public key?) But you don't really need to search as if you are given a public key file you will only have that public key in the file and nothing else.
To Reproduce
Steps to reproduce the behavior (code sample)
Try and encrypt a file with just a unsigned public key, and no recipient address
Expected behavior
A clear and concise description of what you expected to happen.
You should be able to encrypt a file with just the public key as available, official GPG tools can do that without any problem, but if you want to automate that with code this library constrains you

** System (please complete the following information):**

  • Device: [e.g. iPhone6]
    Lenovo Thinkpad

  • OS: [e.g. Linux]
    Windows 10

  • Java [output of java -version]
    java version "1.8.0_231"
    Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
    Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)

  • Version [e.g. 2.2.0]
    2.2.0
    Additional context
    Add any other context about the problem here.

Get Key Usage for older legacy keys of PGP version 6.5.8 Network Associates

No able to get the key usage from the Key rings of PGP version 6.5.8 Network Associates

Iterator<PGPSignature> sigItr = secretKey.getPublicKey().getSignatures(); StringBuilder keyUsage = new StringBuilder(); while (sigItr.hasNext()) { PGPSignature sig = sigItr.next(); PGPSignatureSubpacketVector subPacks = sig.getHashedSubPackets(); if (subPacks != null) { if ((subPacks.getKeyFlags() & KeyFlags.ENCRYPT_COMMS) == 4) {

Expected behavior

It should fetch me the actual key usages, it's working for all keys except for PGP version 6.5.8 Network associates types key

** System (please complete the following information):**

  • OS: [Windows, Linux]
  • Java [1.8]

Allow UIDs to be managed

Is your feature request related to a problem? Please describe.
GPG keys can carry multiple user IDs. BouncyGPGs key generation currently only supports a single UID per keyring.

Describe the solution you'd like
The API for keyring management should enable the caller to

  • Add user IDs to a key
  • Enumerate all user IDs of a key
  • Remove user IDs from a key
  • Set the validity of user IDs

Describe alternatives you've considered
N/A

Additional context
E.g. this is the key of the gpgtools project:

pub   dsa2048/0x76D78F0500D026C4 2010-08-19 [SC] [expires: 2020-06-15]
      85E38F69046B44C1EC9FB07B76D78F0500D026C4
uid                   [ultimate] GPGTools Team <[email protected]>
uid                   [ultimate] GPGMail Project Team (Official OpenPGP Key) <[email protected]>
uid                   [ultimate] GPGTools Project Team (Official OpenPGP Key) <[email protected]>
uid                   [ultimate] [jpeg image of size 5871]
sub   elg2048/0x07EAE49ADBCBE671 2010-08-19 [E] [expires: 2020-06-15]
sub   rsa4096/0xE8A664480D9E43F5 2014-04-08 [S] [expires: 2024-01-02]

Writing Keyrings to storage

Hi!
I noticed, that Bouncy-GPG for now only focusses on reading keyrings from files etc.
Is support for writing modified keyrings planned as well?

Unable to encrypt a plaintext file without a secret key and passphrase

Usage: Need to encrypt a text file with ONLY 3rd party client's public key so I can transfer the encrypted data file to the 3rd party client. The client received the encrypted the file and they can use their secret key and passphrase to decrypt it.

It looks like KeyringConfigs.withKeyRingsFromFiles requires secret key and passphrase that I don't have from the 3rd party client. It doesn't allow null value neither. I am wondering if there would be a solution or a patch or a new API to support the usage.

@Test
  public void testEncryption() throws Exception {
    final KeyringConfig keyringConfig = KeyringConfigs.withKeyRingsFromFiles(new File(publicKeyLocation), null, null);
    try (
      final FileInputStream is = new FileInputStream(plainFileLocation);
      final FileOutputStream fileOutput = new FileOutputStream(gpgFileLocation);
      final BufferedOutputStream bufferedOut = new BufferedOutputStream(fileOutput);

      final OutputStream outputStream = BouncyGPG
        .encryptToStream()
        .withConfig(keyringConfig)
        .withStrongAlgorithms()
        .toRecipient("[email protected]")
        .andSignWith("[email protected]")
        .binaryOutput()
        .andWriteTo(bufferedOut);

    ) {
      Streams.pipeAll(is, outputStream);
    }
  }

Support for sign only

I would like to offer the functions sign() and verify(). As you know from PGP, I want to create a second file in which the signature of the original file is stored. Currently there are only the methods encryptToStream() and decryptAndVerifyStream() in the class BouncyGPG.

Best regards /
mit freundlichen Grüßen

Mike

how to generate an openpgp key?

There are examples on how to read a key that is exported. I'm looking for a way to generate a key directly using the library. Are there examples on how to do this?

Integration tests fails with PGP interop for ECC keys ( gpg: decryption failed: No secret key)

Describe the bug
The integration tests with gpg fail for exporting BouncyGPG generated private ECC keys to gpg.

To Reproduce
Failing test for ECC keyrings, although RSA keyrings work.

Expected behavior
The tests should succeed

System:

  • OS: MacOS
  • Java [output of java -version]: openjdk version "11" 2018-09-25
  • Version [e.g. 2.1.2]: commit 3af038f
  • gpg: gpg (GnuPG/MacGPG2) 2.2.10 with libgcrypt 1.8.3

Additional context

The exported keys:

cat cmd_001_log-ImportCommand/to_gpg_stdin.log | gpg --list-packets -v
# off=0 ctb=94 tag=5 hlen=2 plen=119
:secret key packet:
	version 4, algo 19, created 1546083299, expires 0
	pkey[0]: 082A8648CE3D030107 nistp256 (1.2.840.10045.3.1.7)
	pkey[1]: 0445B0F04963E49A626B0CAC27908A9064442E2D829E2ACF5179260CA12427039BC1FE0460DA1D0BD6EEE6334973AC918BE50A99DF7831B55F6CA200752D2E18DA
	skey[2]: CDB24D40EF9DE69DC60FFAEC70C504BBE3DCF5DB2C1A7B146710C22DBD99B543
	checksum: 11e3
	keyid: 732D8515470359BC
# off=121 ctb=b4 tag=13 hlen=2 plen=35
:user ID packet: "Juliet Capulet <[email protected]>"
# off=158 ctb=88 tag=2 hlen=2 plen=123
:signature packet: algo 19, keyid 732D8515470359BC
	version 4, created 1546083299, md5len 0, sigclass 0x13
	digest algo 10, begin of digest 76 82
	hashed subpkt 2 len 4 (sig created 2018-12-29)
	hashed subpkt 27 len 1 (key flags: 23)
	hashed subpkt 22 len 4 (pref-zip-algos: 3 1 0 2)
	hashed subpkt 11 len 8 (pref-sym-algos: 11 7 12 13 2 10 8 9)
	hashed subpkt 21 len 5 (pref-hash-algos: 9 3 8 10 11)
	hashed subpkt 30 len 1 (features: 01)
	subpkt 16 len 8 (issuer key ID 732D8515470359BC)
	data: 28934D133350EF4BA130831027751E1C8D7BEE1B745E185690DE6F3A21CB02CB
	data: 95CC6634A867507CB1CE1D1E6798C417644A8E07ACB4520DB6876D651E80BA9A
# off=283 ctb=9c tag=7 hlen=2 plen=123
:secret sub key packet:
	version 4, algo 18, created 1546083299, expires 0
	pkey[0]: 082A8648CE3D030107 nistp256 (1.2.840.10045.3.1.7)
	pkey[1]: 0452CDCBBF92C1F05B40EAD4C4AD12E967AE6B1BBF457834F75DC61C49FFD29B8AB53365DA4F02D05AAE3B99970521DD3750560A9CDB9F3A6F4CD67DAEBC58FA19
	pkey[2]: 03010807
	skey[3]: 78CFB85E037074B9A6FB14B4A090487EB054F13527B4DD96398B8354F9960EB4
	checksum: 11bf
	keyid: A99B151C882FF69C
# off=408 ctb=88 tag=2 hlen=2 plen=123
:signature packet: algo 19, keyid 732D8515470359BC
	version 4, created 1546083299, md5len 0, sigclass 0x18
	digest algo 10, begin of digest a4 8a
	hashed subpkt 2 len 4 (sig created 2018-12-29)
	hashed subpkt 27 len 1 (key flags: 0C)
	hashed subpkt 22 len 4 (pref-zip-algos: 3 1 0 2)
	hashed subpkt 11 len 8 (pref-sym-algos: 11 7 12 13 2 10 8 9)
	hashed subpkt 21 len 5 (pref-hash-algos: 9 3 8 10 11)
	hashed subpkt 30 len 1 (features: 01)
	subpkt 16 len 8 (issuer key ID 732D8515470359BC)
	data: 7631A142BC418E3C51835283EB9FA2A8FFB14F0B5A94367E04EC2B887567F544
	data: B5209ED7A03825676334C8832239D3A99D4481A2BAAA57A2CC76454B6C75C9DD

The message that fails to decrypt with " gpg: decryption failed: No secret key":

cat cmd_002_log-DecryptCommand/to_gpg_stdin.log | gpg --list-packets --verbose
gpg: public key is 0xA99B151C882FF69C
gpg: encrypted with ECDH key, ID 0xA99B151C882FF69C
gpg: decryption failed: No secret key
# off=0 ctb=84 tag=1 hlen=2 plen=126
:pubkey enc packet: version 3, algo 18, keyid A99B151C882FF69C
	data: 0462E9F40AC8D473C129FFECD9DA3C3621502CE58C2860EC44FB7A078461052F8F5218570A13DFA719412CD0FA88238BA3836363DE70F28E7E8B020C5A58BEE384
	data: 30B8F38183CF85419854384D6BEFEA77E0D69997BD3175E1557CE7352431092611B6C7713F01D0694C7043AAFDB6FD5E2E
# off=128 ctb=d2 tag=18 hlen=3 plen=295 new-ctb
:encrypted data packet:
	length: 295
	mdc_method: 2

What puzzles me is, that the key 0xA99B151C882FF69C is part of the imported private key:

...
:secret sub key packet:
	version 4, algo 18, created 1546083299, expires 0
	pkey[0]: 082A8648CE3D030107 nistp256 (1.2.840.10045.3.1.7)
        [...]
	keyid: A99B151C882FF69C

Encrypt using aes256

Hi,

There is a way for encrypt using AES 256 ??? I didn't see anything related to AES in any example or document.

Thanks

Is ASCII armoring supported?

Hi there,

first of all many thanks for implementing my change suggestion from pull request #6. Today I would like to ask if decrypting ASCII armored data is already supported.

Greetings Mike

Upgrade all the tests to Junit 5

Some of the tests have assertions that have been deprecated and alternative imports are being suggested for it.

So rather than, updating just the assertions, I was thinking that it might be better to upgrade the entire Junit framework.

If we update just the assertions, they might become obsolete soon as well. However, Junit 5 is new and should persist for a while. There are also a number of drill down features in Junit 5 that will enhance the strength of the tests.
Please let me know what you think

Generate signature for CANONICAL_TEXT_DOCUMENT

I have a use-case where I need to sign and encrypt a canonical text document rather than a binary document (see https://tools.ietf.org/html/rfc4880#section-5.2.1). This should replace \n with \r\n and set a particular flag, from what I understand.

It looks like the best way is to modify name.neuhalfen.projects.crypto.bouncycastle.openpgp.encrypting.PGPEncryptingStream#setup to make this statement configurable:

signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);

The PGPSignature.BINARY_DOCUMENT could be something that can be changed in BuildEncryptionOutputStreamAPI?

BouncyGPG
	.encryptToStream()
...
	.andSignWith(uid, PGPSignature.CANONICAL_TEXT_DOCUMENT)
	.binaryOutput()
	.andWriteTo(...)

Input stream based key rings

It'd be cool to have a class that consumes input streams to get the key rings. That seems to be how it works under the hood.

java.io.EOFException: Unexpected end of ZIP input stream using 2.2.0 version for PGP file

Describe the bug
I'm trying to decrypt a PGP file encrypted with an old version of BC (2017) within bouncy-gpg 2.2.0 and it fails giving me the error
java.io.EOFException: Unexpected end of ZIP input stream
at org.bouncycastle.openpgp.PGPCompressedData$1.fill(Unknown Source)
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158)
at org.bouncycastle.bcpg.BCPGInputStream.read(Unknown Source)
at org.bouncycastle.bcpg.BCPGInputStream$PartialInputStream.read(Unknown Source)
at org.bouncycastle.bcpg.BCPGInputStream.read(Unknown Source)
at java.io.InputStream.read(InputStream.java:101)

If I use bouncy-gpg 2.1.2, file is decrypted.
If I use bouncy-gpg 2.1.2 with last version of bcprov-jdk15on 1.65.01 and bcgp-jdk15on 1.65, file is decrypted
If I use bouncy-gpg 2.2.0 with last version of bcprov-jdk15on 1.65.01 and bcgp-jdk15on 1.65, file decryption fails giving me the same issue.

To Reproduce

Expected behavior
Based on my test, I think that the issue is within bouncy-gpg libraries instead of something related to BC libraries.

** System (please complete the following information):**

  • Device: Laptop
  • OS: Windows10
  • Java JDK 1.8
  • Version 2.2.0

Encryption Key is being selected for signing rather than signing subkey

When encrypting and signing a file, I'm getting complaints that the encryption key is being used to sign.

I can see code in the source that suggests there has been attempted provisions to get the correct sub key, but I am not sure it is being used in this circumstance.

I have regenerated keys just in case to no avail.

Are there any special tricks to ensure the correct subkey is used for the signing process?

NullPointerException when trying to decrypt non-encrypted data (v2.3.0)

Describe the bug
When we call the method decryptAndVerifyStream with an input stream that contains data that is not encrypted (for example only signed), there is a NullPointerException when reading the returned InputStream later thrown by name.neuhalfen.projects.crypto.bouncycastle.openpgp.decrypting.MDCValidatingInputStream.validateMDC, where the local variable pbe is null.

In v2.2.0, there was no exception, trying to decrypt a non-encrypted stream just returned the original stream.
The same thing happens when trying to read an input stream obtained after trying to decrypt an input stream that was (incorrectly) encrypted twice (which is a unit test we are running).

The issue seems to be introduced by the following commit:
986d436#diff-f7bfd613f0ac7d22e02bd9c1727a319dad532f787e9de5ae702da71b252580b4

Here the new MDCValidatingInputStream class is introduced, and we see that the value of pbe comes from DecryptionStreamFactory, where it is initialized only if the method nextDecryptedStream finds an instance of PGPEncryptedDataList, otherwise it stays null and is passed to the MDCValidatingInputStream where there is no null check.

To Reproduce
In v2.3.0, execute a decryption with:

BouncyGPG
                        .decryptAndVerifyStream()
                        .withConfig(keyringConfig)
                        .andIgnoreSignatures()
                        .fromEncryptedInputStream(in)

where in is an input stream containing not encrypted, but signed data.

Expected behavior
No NullPointerException thrown.

** System (please complete the following information):**

  • Device: workstation
  • OS: Linux
  • Java:
openjdk version "11.0.9.1" 2020-11-04
OpenJDK Runtime Environment (build 11.0.9.1+1-Ubuntu-0ubuntu1.20.04)
OpenJDK 64-Bit Server VM (build 11.0.9.1+1-Ubuntu-0ubuntu1.20.04, mixed mode, sharing)
  • Version 2.3.0

Command line gpg and this java library produces different results

How do I convert following command into the equivalent using this library.

gpg -e -r "recipient" --output output.gpg input.zip

I have tried following options but with no success:

final OutputStream outputStream = BouncyGPG.encryptToStream()
	        .withConfig(keyring)
	        .withOxAlgorithms()
	        //.withDefaultAlgorithms()
                //.withAlgorithms(new PGPAlgorithmSuite(PGPHashAlgorithms.SHA_256 , 
                //   PGPSymmetricEncryptionAlgorithms.AES_256, 
                //   PGPCompressionAlgorithms.ZLIB))
	        .toRecipient("recipient")
	        .andDoNotSign()
	        .binaryOutput()
	        .andWriteTo(encrypted);

Every time I encrypt a file using command line and using the code, I get two different results. One with the command line for example if is 300KB, then the one with the code is almost twice the size ~550KB.

Our legacy system is having issues decrypting the gpg file coming from this java library. However, if encrypted using command line GPG GnuPG (2.17.2) version using the command, it is able to decrypt.

Any help will be highly appreciated.

Provide a custom `SignatureValidationStrategy`

I have a use case where I need to check that decrypted data has been signed by any of two given keys. The current API RequireSpecificSignatureValidationStrategy supports an "AND" verification, but I need an "OR" verification.

I think it would be nice if users had the possibility to provide their own instance of SignatureValidationStrategy. This way they can use custom strategies without having to submit PRs here and wait for a release.

Maybe a new method named andValidateSignatureMatches(SignatureValidationStrategy) in name.neuhalfen.projects.crypto.bouncycastle.openpgp.BuildDecryptionInputStreamAPI.Validation:

BouncyGPG
	.decryptAndVerifyStream()
	.withConfig(...)
	.andValidateSignatureMatches(mySignatureValidationStrategy)
	.fromEncryptedInputStream(cipherTextStream);

File with valid MDC can fail MDC verification when stream is wrapped

Describe the bug
Exception thrown ('Error while validating MDC') if MDC validation occurs twice, caused by nested InputStreams.

To Reproduce
Wrap the decryptAndVerifyStream in an additional InputStream, reading to the end of that stream can cause MDCValidatingInputStream#read to be called twice. PGPEncryptedData#verify doesn't like being called twice, possibly due to the reuse of the integrityCalculator OutputStream (a guess).

Expected behavior
Exception should not be thrown if MDC is valid, even if nested streams cause the validator to trigger twice.

** System (please complete the following information):**

  • Version 2.3.0

Additional context
I've got an example trivial fix, will raise a PR for consideration shortly. Thanks!

Can be used the .P12 file as keyring

I am going to encrypt and decrypt the files with p12 using bouncy-gpg .
Of course, I can get a public key and private key from p12 file.
But not adaptable with these public key and private key.

How can I handle this problem?
That would be appreciated for any advice.

No (suitable) public key for encryption to [a provided recipient email address] found

Hi,

I tested encryption out with gpg in commandline with no problem. When I test it out with Bouncy-gpg by using this code:

    publicKeyLocation = "../GPGKeys/Experian/Experian_Public.asc";
    final String PUBLIC_KEY = new String(Files.readAllBytes(Paths.get(publicKeyLocation)));
    gpgFileLocation = "../Development/treadstone/test.gpg";
    FileOutputStream fileOutput = new FileOutputStream(gpgFileLocation);
    BufferedOutputStream bufferedOutputStream = null;
    FileInputStream fis = null;
    OutputStream outputStream = null;
    InMemoryKeyring keyring = 
    KeyringConfigs.forGpgExportedKeys(KeyringConfigCallbacks.withUnprotectedKeys());
    String UID = "[email protected]";
    keyring.addPublicKey(PUBLIC_KEY.getBytes(StandardCharsets.US_ASCII));

    try {
      bufferedOutputStream = new BufferedOutputStream(fileOutput);
      fis = new FileInputStream(plainFileLocation);
      outputStream = BouncyGPG
        .encryptToStream()
        .withConfig(keyring)
        .withStrongAlgorithms()
        .toRecipient(UID)
        .andDoNotSign()
        .binaryOutput()
        .andWriteTo(bufferedOutputStream);
      Streams.pipeAll(fis, outputStream);

    } catch (Exception ex) {
      throw new RuntimeException(ex);
    } finally {
      if (bufferedOutputStream != null && fis != null && outputStream != null) {
        outputStream.close();
        bufferedOutputStream.close();
        fileOutput.close();
      }
    }

Then, It gives exception

java.lang.RuntimeException: org.bouncycastle.openpgp.PGPException: No (suitable) public key for encryption to [email protected] found
	at com.viantinc.BouncyGPGTest.testEncryptionByUsingPubKeyWithTryCatch(BouncyGPGTest.java:165)
...
...
...
Caused by: org.bouncycastle.openpgp.PGPException: No (suitable) public key for encryption to [email protected] found
	at name.neuhalfen.projects.crypto.bouncycastle.openpgp.BuildEncryptionOutputStreamAPI$WithAlgorithmSuiteImpl$ToImpl.extractValidKey(BuildEncryptionOutputStreamAPI.java:414)
	at name.neuhalfen.projects.crypto.bouncycastle.openpgp.BuildEncryptionOutputStreamAPI$WithAlgorithmSuiteImpl$ToImpl.toRecipient(BuildEncryptionOutputStreamAPI.java:431)
	at com.viantinc.BouncyGPGTest.testEncryptionByUsingPubKeyWithTryCatch(BouncyGPGTest.java:158)

This code works all other public key except this one. The interesting part is that it works in GPG commandline.

I have attached the public key in the following comment. I don't know if the recipient email address the "dot" in front of domain that causes the issue.

No (suitable) public key for encryption to [a provided recipient email address] found

When I'm adding the pub and secret keys of sender in KeyringConfig and i can't add more than two keys as per the function (withKeyRingsFromFiles)

But seems like it is expecting three keys (sender's public, private key and receiver public key) to be added in KeyringConfig but function doesn't allow us to add more than two keys, getting the following error "org.bouncycastle.openpgp.PGPException: No (suitable) public key for encryption to [email protected] found".

Should it be asking for the receiver public key in the local directory of the sender? if yes, please suggest how can i specify the public key of a receiver also?

Empty key rings

Does it make sense to support empty key rings? If I'm encrypting something, I presumably only need the recipient's public key to do so. Likewise, if I'm decrypting something, I only need my secret key.

This seems to be possible with GPG on the command line. Is my understanding not correct?

PGPKeyGeneration

Hi!
Do you consider adding code to generate PGPKeys?
I'm currently trying to generate my own PGPKeys using BouncyCastle, but fail to use them in the process of encryption due to "No suitable keys found".

Apparently the keyflags on the keys I generate are always 0.
(Edit: I already found a solution to the keyflags issue, now using my keys in bouncy-gpg works fine.)

Do you plan to add a keygenerator api in the future?

MDC (integrity checksum) is not verified when decrypting

Describe the bug
MDC is not verified.

To Reproduce
Step through code while decrypting a message that contains an MDC.

Expected behavior
MDC should be verified when present. There should also be a way to configure MDC policy - whether MDC is required.

System

  • Version: 2.2.0

Additional context
https://github.com/neuhalje/bouncy-gpg/blob/master/src/main/java/name/neuhalfen/projects/crypto/bouncycastle/openpgp/decrypting/DecryptionStreamFactory.java does not appear to have any code for verifying MDC (data integrity check). I would expect to find code that looks something like this:

private static void checkDataIntegrity(PGPPublicKeyEncryptedData encryptedData) throws PGPException, IOException {
    if (encryptedData.isIntegrityProtected()) {
        if (!encryptedData.verify()) {
            throw new RuntimeException("Data failed MDC integrity check.");
        }
    } else {
        throw new RuntimeException("MDC not found - cannot check data integrity.");
    }
}

Some background on MDC and why it's important security-wise: https://gpgtools.tenderapp.com/kb/faq/modification-detection-code-mdc-errors

Some files cannot be decrypted with error "premature end of stream in PartialInputStream"

Describe the bug
An error occurs when decrypting some files. It seems caused by a stream closed too early (see additional information)

To Reproduce

        encryptedStream.use { cipherTextStream ->
            FileOutputStream(decryptedFile).use { bufferedOut ->
                BouncyGPG
                    .decryptAndVerifyStream()
                    .withConfig(keyRing)
                    .andIgnoreSignatures()
                    .fromEncryptedInputStream(cipherTextStream)
                    .use { plaintextStream ->
                        Streams.pipeAll(plaintextStream, bufferedOut)
                    }
            }
        }

Expected behavior
File gets decrypted

** System (please complete the following information):**

  • Device: Laptop?
  • OS: Linux 5.5.13-arch1-1 #1 SMP PREEMPT Wed, 25 Mar 2020 16:04:40 +0000 x86_64 GNU/Linux
  • Java
openjdk version "1.8.0_242"
OpenJDK Runtime Environment (build 1.8.0_242-b08)
OpenJDK 64-Bit Server VM (build 25.242-b08, mixed mode)
  • Version 2.2.0 (new, 2.1.2 works)

Additional context
Stacktrace :

Caused by: java.io.EOFException: premature end of stream in PartialInputStream
	at org.bouncycastle.bcpg.BCPGInputStream$PartialInputStream.read(Unknown Source)
	at org.bouncycastle.bcpg.BCPGInputStream.read(Unknown Source)
	at org.bouncycastle.openpgp.PGPCompressedData$1.fill(Unknown Source)
	at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158)
	at org.bouncycastle.bcpg.BCPGInputStream.read(Unknown Source)
	at org.bouncycastle.bcpg.BCPGInputStream$PartialInputStream.read(Unknown Source)
	at org.bouncycastle.bcpg.BCPGInputStream.read(Unknown Source)
	at org.bouncycastle.util.io.Streams.pipeAll(Unknown Source)
	at [redacted, my code].decryptIntoOutputStream(BouncyCastleFileDecryptor.kt:47)

I've isolated the breaking commit : 012c3f9 (reverting to 2.1.2 works)

It seems the stream closes too soon, but I have no idea why it works with some files and not with some others.

It works well with a file I encrypted myself. However, it does not work with the file the provider creates. I have no idea why. I also have no idea how they encrypt it to be honest. I cannot share the file for privacy reasons, however if some info on it can help, let me know.

I'm sorry I can't provide more information! Let me know how I can help more

Do not expose logback as compile-time dependency

Describe the bug
A library should not restrict its users to a particular logging framework. Currently, bouncy-gpg uses logback and depends on it in compile while this should be clearly up to the user what logging framework to use.

Expected behavior
Only the logging facade should be exposed such as slf4j or flogger or log4j2-api.

Additional context
While different applications rely on different logging frameworks, having a strict dependency on logback forces users either to exclude logback from the dependency or switch to it.

Quick fix
One can exclude the logback from the library dependency, e.g. in Maven:

<dependency>
	<groupId>name.neuhalfen.projects.crypto.bouncycastle.openpgp</groupId>
	<artifactId>bouncy-gpg</artifactId>
	<version>${bouncy-gpg.version}</version>
	<exclusions>
		<exclusion>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
		</exclusion>
	</exclusions>
</dependency>

Support flag on keys without sub keys

Is your feature request related to a problem? Please describe.
We've received a key from an external party without any sub-keys. bouncy-gpg refuses using this key for encryption as no sub-key is present with the encryption flag. This flag is however available on the key itself.

Describe the solution you'd like
Query the primary key for flags. sub-keys, if any are present, can add / override these flags.

Describe alternatives you've considered
Currently we have a custom KeySelectionStrategy that do not call isEncryption in selectPublicKey.

Additional context
gpg commandline handles this case transparently.

key listing:

pub   rsa1024 2019-05-07 [SCEA] [expires: 2019-10-04]
      25FCD105E7678499A589CED75D9A137B3470B15A
uid           [ unknown] someUidProvidedByExternalParty

Rfc4880KeySelectionStrategy only considers email addresses as uids

I'm not sure, if this is really an issue on your side, but the Rfc4880KeySelectionStrategy's publicKeyRingsForUid() method encloses uid queries with < and >, so every query represents an email address.

The query [email protected] would match the uid Juliet Capulet <[email protected]>.

Rfc4880 however states:

By convention, it includes an RFC 2822 [RFC2822] mail name-addr, but there are no restrictions on its content.

In my case I have to search for uids that do not contain an email address (for example xmpp:[email protected]).
As the Rfc4880KeySelectionStrategy encloses all queries with <>, I am not able to find those uids.

The solution for me was to overwrite the publicKeyRingsForUid() methods behaviour in my own KeySelectionStrategy.

I'm reporting this though, since I'm not sure if it is an error in your implementation or not.
Other than that, I found your library very pleasing to use, thank you for that :)

Not null requirement for Keyring Config

Keyring config requires private key public key and password to be not null, even when they are not used. For example, even to only encrypt with public key (not signing) it requires those to be non null. Current workaround I found is to give empty string for password and random file for private key (because it creates an input stream from file).

The problem I specifically have is at (public class Rfc4880KeySelectionStrategy implements KeySelectionStrategy:137) and the reason it gives an error is, it tries to get secret keyrings before checking what the purpose is, So a simple solution for this specific problem would be to move line 137 inside the switch statement. However, I don't have extended knowledge of this project, so I am not sure if that is the optimal solution

Cannot decrypt using ByteArrayInputStream as input stream

Hello, I ran into the following issue:
I need to decrypt some secret data which is just encrypted and stored in memory as byte array. I have the following error:

Exception in thread "main" java.io.EOFException: premature end of stream in PartialInputStream
	at org.bouncycastle.bcpg.BCPGInputStream$PartialInputStream.read(Unknown Source)
	at org.bouncycastle.bcpg.BCPGInputStream.read(Unknown Source)
	at org.bouncycastle.bcpg.SymmetricEncIntegrityPacket.<init>(Unknown Source)
	at org.bouncycastle.bcpg.BCPGInputStream.readPacket(Unknown Source)
	at org.bouncycastle.openpgp.PGPEncryptedDataList.<init>(Unknown Source)
	at org.bouncycastle.openpgp.PGPObjectFactory.nextObject(Unknown Source)
	at name.neuhalfen.projects.crypto.bouncycastle.openpgp.decrypting.DecryptionStreamFactory.nextDecryptedStream(DecryptionStreamFactory.java:78)
	at name.neuhalfen.projects.crypto.bouncycastle.openpgp.decrypting.DecryptionStreamFactory.wrapWithDecryptAndVerify(DecryptionStreamFactory.java:58)
	at name.neuhalfen.projects.crypto.bouncycastle.openpgp.BuildDecryptionInputStreamAPI$Validation$Builder.fromEncryptedInputStream(BuildDecryptionInputStreamAPI.java:170)
	at Main.main(Main.java:61)

My source code:

byte[] bytes;
        try (
                final ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();

                final OutputStream outputStream = BouncyGPG
                        .encryptToStream()
                        .withConfig(keyringConfigInMemoryForSender())
                        .withStrongAlgorithms()
                        .toRecipient("[email protected]")
                        .andSignWith("[email protected]")
                        .binaryOutput()
                        .andWriteTo(byteOutput);

                final FileInputStream is = new FileInputStream("tmp/plaintext.txt")
        ) {
            Streams.pipeAll(is, outputStream);
            bytes = byteOutput.toByteArray();
        }


        try (
                final ByteArrayInputStream cipherTextStream = new ByteArrayInputStream(bytes);

                final FileOutputStream fileOutput = new FileOutputStream("tmp/decrypted.txt");
                final BufferedOutputStream bufferedOut = new BufferedOutputStream(fileOutput);

                final InputStream plaintextStream = BouncyGPG
                        .decryptAndVerifyStream()
                        .withConfig(keyringConfigInMemoryForRecipient())
                        .andIgnoreSignatures()
                        .fromEncryptedInputStream(cipherTextStream)

        ) {
            Streams.pipeAll(plaintextStream, bufferedOut);
        }
    }

Have you any ideas what I'm doing wrong, or it is an expected behaviour?

KeySelectionStrategy that receive keys

I cant find a way to define a keystregy any other beyond by email, this is a problem because I don't know name ID of the key sent to me. I only need to use this public key to encrypt to my sender.

In the end would be awesome have an option to KeySelectionStrategy such as:

byte[] myOwnPrivateKey = DB.getMyPrivateKey();
byte[] customerPublicKey = DB.getCustomerPrivateKey();

final OutputStream encryptionStream = BouncyGPG
        .encryptToStream()
        .toRecipient(customerPublicKey)
        .andSignWith(myOwnPrivateKey)
        .armorAsciiOutput()
        .andWriteTo(buffer);

I am sorry, this may is a stupid question but I really don't know how to deal with it.

Downloading 2.2.0 from bintray fails with maven bc. of HTTP

Describe the bug

Downloading 2.2.0 with maven fails with an error message:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.036 s
[INFO] Finished at: 2020-01-23T07:43:31+01:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal on project maven-example: Could not resolve dependencies for project name.neuhalfen.projects.crypto.bouncycastle.openpgp:maven-example:jar:1.0-SNAPSHOT: Failed to collect dependencies at name.neuhalfen.projects.crypto.bouncycastle.openpgp:bouncy-gpg:jar:2.2.0: Failed to read artifact descriptor for name.neuhalfen.projects.crypto.bouncycastle.openpgp:bouncy-gpg:jar:2.2.0: Could not transfer artifact name.neuhalfen.projects.crypto.bouncycastle.openpgp:bouncy-gpg:pom:2.2.0 from/to bintray (http://jcenter.bintray.com): Access denied to: http://jcenter.bintray.com/name/neuhalfen/projects/crypto/bouncycastle/openpgp/bouncy-gpg/2.2.0/bouncy-gpg-2.2.0.pom -> [Help 1]

To Reproduce

cd bouncy-gpg/examples/maven
rm -rf target
rm -rf rm -rf ~/.m2/repository/name/neuhalfen/projects/crypto/bouncycastle/openpgp/bouncy-gpg/   
mvn compile -X

Error message

Apache Maven 3.6.1
Maven home: /usr/share/maven
Java version: 11.0.5, vendor: Private Build, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "5.3.0-26-generic", arch: "amd64", family: "unix"
[DEBUG] Created new class realm maven.api
[DEBUG] Importing foreign packages into class realm maven.api
[DEBUG]   Imported: javax.annotation.* < plexus.core
[DEBUG]   Imported: javax.annotation.security.* < plexus.core
[DEBUG]   Imported: javax.enterprise.inject.* < plexus.core
[DEBUG]   Imported: javax.enterprise.util.* < plexus.core
[DEBUG]   Imported: javax.inject.* < plexus.core
[DEBUG]   Imported: org.apache.maven.* < plexus.core
[DEBUG]   Imported: org.apache.maven.artifact < plexus.core
[DEBUG]   Imported: org.apache.maven.classrealm < plexus.core
[DEBUG]   Imported: org.apache.maven.cli < plexus.core
[DEBUG]   Imported: org.apache.maven.configuration < plexus.core
[DEBUG]   Imported: org.apache.maven.exception < plexus.core
[DEBUG]   Imported: org.apache.maven.execution < plexus.core
[DEBUG]   Imported: org.apache.maven.execution.scope < plexus.core
[DEBUG]   Imported: org.apache.maven.lifecycle < plexus.core
[DEBUG]   Imported: org.apache.maven.model < plexus.core
[DEBUG]   Imported: org.apache.maven.monitor < plexus.core
[DEBUG]   Imported: org.apache.maven.plugin < plexus.core
[DEBUG]   Imported: org.apache.maven.profiles < plexus.core
[DEBUG]   Imported: org.apache.maven.project < plexus.core
[DEBUG]   Imported: org.apache.maven.reporting < plexus.core
[DEBUG]   Imported: org.apache.maven.repository < plexus.core
[DEBUG]   Imported: org.apache.maven.rtinfo < plexus.core
[DEBUG]   Imported: org.apache.maven.settings < plexus.core
[DEBUG]   Imported: org.apache.maven.toolchain < plexus.core
[DEBUG]   Imported: org.apache.maven.usability < plexus.core
[DEBUG]   Imported: org.apache.maven.wagon.* < plexus.core
[DEBUG]   Imported: org.apache.maven.wagon.authentication < plexus.core
[DEBUG]   Imported: org.apache.maven.wagon.authorization < plexus.core
[DEBUG]   Imported: org.apache.maven.wagon.events < plexus.core
[DEBUG]   Imported: org.apache.maven.wagon.observers < plexus.core
[DEBUG]   Imported: org.apache.maven.wagon.proxy < plexus.core
[DEBUG]   Imported: org.apache.maven.wagon.repository < plexus.core
[DEBUG]   Imported: org.apache.maven.wagon.resource < plexus.core
[DEBUG]   Imported: org.codehaus.classworlds < plexus.core
[DEBUG]   Imported: org.codehaus.plexus.* < plexus.core
[DEBUG]   Imported: org.codehaus.plexus.classworlds < plexus.core
[DEBUG]   Imported: org.codehaus.plexus.component < plexus.core
[DEBUG]   Imported: org.codehaus.plexus.configuration < plexus.core
[DEBUG]   Imported: org.codehaus.plexus.container < plexus.core
[DEBUG]   Imported: org.codehaus.plexus.context < plexus.core
[DEBUG]   Imported: org.codehaus.plexus.lifecycle < plexus.core
[DEBUG]   Imported: org.codehaus.plexus.logging < plexus.core
[DEBUG]   Imported: org.codehaus.plexus.personality < plexus.core
[DEBUG]   Imported: org.codehaus.plexus.util.xml.Xpp3Dom < plexus.core
[DEBUG]   Imported: org.codehaus.plexus.util.xml.pull.XmlPullParser < plexus.core
[DEBUG]   Imported: org.codehaus.plexus.util.xml.pull.XmlPullParserException < plexus.core
[DEBUG]   Imported: org.codehaus.plexus.util.xml.pull.XmlSerializer < plexus.core
[DEBUG]   Imported: org.eclipse.aether.* < plexus.core
[DEBUG]   Imported: org.eclipse.aether.artifact < plexus.core
[DEBUG]   Imported: org.eclipse.aether.collection < plexus.core
[DEBUG]   Imported: org.eclipse.aether.deployment < plexus.core
[DEBUG]   Imported: org.eclipse.aether.graph < plexus.core
[DEBUG]   Imported: org.eclipse.aether.impl < plexus.core
[DEBUG]   Imported: org.eclipse.aether.installation < plexus.core
[DEBUG]   Imported: org.eclipse.aether.internal.impl < plexus.core
[DEBUG]   Imported: org.eclipse.aether.metadata < plexus.core
[DEBUG]   Imported: org.eclipse.aether.repository < plexus.core
[DEBUG]   Imported: org.eclipse.aether.resolution < plexus.core
[DEBUG]   Imported: org.eclipse.aether.spi < plexus.core
[DEBUG]   Imported: org.eclipse.aether.transfer < plexus.core
[DEBUG]   Imported: org.eclipse.aether.version < plexus.core
[DEBUG]   Imported: org.fusesource.jansi.* < plexus.core
[DEBUG]   Imported: org.slf4j.* < plexus.core
[DEBUG]   Imported: org.slf4j.event.* < plexus.core
[DEBUG]   Imported: org.slf4j.helpers.* < plexus.core
[DEBUG]   Imported: org.slf4j.spi.* < plexus.core
[DEBUG] Populating class realm maven.api
[INFO] Error stacktraces are turned on.
[DEBUG] Message scheme: plain
[DEBUG] Reading global settings from /usr/share/maven/conf/settings.xml
[DEBUG] Reading user settings from /home/jens/.m2/settings.xml
[DEBUG] Reading global toolchains from /usr/share/maven/conf/toolchains.xml
[DEBUG] Reading user toolchains from /home/jens/.m2/toolchains.xml
[DEBUG] Using local repository at /home/jens/.m2/repository
[DEBUG] Using manager EnhancedLocalRepositoryManager with priority 10.0 for /home/jens/.m2/repository
[INFO] Scanning for projects...
[DEBUG] Extension realms for project name.neuhalfen.projects.crypto.bouncycastle.openpgp:maven-example:jar:1.0-SNAPSHOT: (none)
[DEBUG] Looking up lifecycle mappings for packaging jar from ClassRealm[plexus.core, parent: null]
[WARNING] 
[WARNING] Some problems were encountered while building the effective model for name.neuhalfen.projects.crypto.bouncycastle.openpgp:maven-example:jar:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ line 11, column 15
[WARNING] 
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING] 
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING] 
[DEBUG] === REACTOR BUILD PLAN ================================================
[DEBUG] Project: name.neuhalfen.projects.crypto.bouncycastle.openpgp:maven-example:jar:1.0-SNAPSHOT
[DEBUG] Tasks:   [compile]
[DEBUG] Style:   Regular
[DEBUG] =======================================================================
[INFO] 
[INFO] --< name.neuhalfen.projects.crypto.bouncycastle.openpgp:maven-example >--
[INFO] Building maven-example 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[DEBUG] Lifecycle default -> [validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy]
[DEBUG] Lifecycle clean -> [pre-clean, clean, post-clean]
[DEBUG] Lifecycle site -> [pre-site, site, post-site, site-deploy]
[DEBUG] Lifecycle default -> [validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy]
[DEBUG] Lifecycle clean -> [pre-clean, clean, post-clean]
[DEBUG] Lifecycle site -> [pre-site, site, post-site, site-deploy]
[DEBUG] Lifecycle default -> [validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy]
[DEBUG] Lifecycle clean -> [pre-clean, clean, post-clean]
[DEBUG] Lifecycle site -> [pre-site, site, post-site, site-deploy]
[DEBUG] === PROJECT BUILD PLAN ================================================
[DEBUG] Project:       name.neuhalfen.projects.crypto.bouncycastle.openpgp:maven-example:1.0-SNAPSHOT
[DEBUG] Dependencies (collect): []
[DEBUG] Dependencies (resolve): [compile]
[DEBUG] Repositories (dependencies): [bintray (http://jcenter.bintray.com, default, releases), central (https://repo.maven.apache.org/maven2, default, releases)]
[DEBUG] Repositories (plugins)     : [central (https://repo.maven.apache.org/maven2, default, releases)]
[DEBUG] -----------------------------------------------------------------------
[DEBUG] Goal:          org.apache.maven.plugins:maven-resources-plugin:2.6:resources (default-resources)
[DEBUG] Style:         Regular
[DEBUG] Configuration: <?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <buildFilters default-value="${project.build.filters}"/>
  <encoding default-value="${project.build.sourceEncoding}">${encoding}</encoding>
  <escapeString>${maven.resources.escapeString}</escapeString>
  <escapeWindowsPaths default-value="true">${maven.resources.escapeWindowsPaths}</escapeWindowsPaths>
  <includeEmptyDirs default-value="false">${maven.resources.includeEmptyDirs}</includeEmptyDirs>
  <outputDirectory default-value="${project.build.outputDirectory}"/>
  <overwrite default-value="false">${maven.resources.overwrite}</overwrite>
  <project default-value="${project}"/>
  <resources default-value="${project.resources}"/>
  <session default-value="${session}"/>
  <supportMultiLineFiltering default-value="false">${maven.resources.supportMultiLineFiltering}</supportMultiLineFiltering>
  <useBuildFilters default-value="true"/>
  <useDefaultDelimiters default-value="true"/>
</configuration>
[DEBUG] -----------------------------------------------------------------------
[DEBUG] Goal:          org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile)
[DEBUG] Style:         Regular
[DEBUG] Configuration: <?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <basedir default-value="${basedir}"/>
  <buildDirectory default-value="${project.build.directory}"/>
  <classpathElements default-value="${project.compileClasspathElements}"/>
  <compileSourceRoots default-value="${project.compileSourceRoots}"/>
  <compilerId default-value="javac">${maven.compiler.compilerId}</compilerId>
  <compilerReuseStrategy default-value="${reuseCreated}">${maven.compiler.compilerReuseStrategy}</compilerReuseStrategy>
  <compilerVersion>${maven.compiler.compilerVersion}</compilerVersion>
  <debug default-value="true">${maven.compiler.debug}</debug>
  <debuglevel>${maven.compiler.debuglevel}</debuglevel>
  <encoding default-value="${project.build.sourceEncoding}">${encoding}</encoding>
  <executable>${maven.compiler.executable}</executable>
  <failOnError default-value="true">${maven.compiler.failOnError}</failOnError>
  <forceJavacCompilerUse default-value="false">${maven.compiler.forceJavacCompilerUse}</forceJavacCompilerUse>
  <fork default-value="false">${maven.compiler.fork}</fork>
  <generatedSourcesDirectory default-value="${project.build.directory}/generated-sources/annotations"/>
  <maxmem>${maven.compiler.maxmem}</maxmem>
  <meminitial>${maven.compiler.meminitial}</meminitial>
  <mojoExecution>${mojoExecution}</mojoExecution>
  <optimize default-value="false">${maven.compiler.optimize}</optimize>
  <outputDirectory default-value="${project.build.outputDirectory}"/>
  <projectArtifact default-value="${project.artifact}"/>
  <showDeprecation default-value="false">${maven.compiler.showDeprecation}</showDeprecation>
  <showWarnings default-value="false">${maven.compiler.showWarnings}</showWarnings>
  <skipMain>${maven.main.skip}</skipMain>
  <skipMultiThreadWarning default-value="false">${maven.compiler.skipMultiThreadWarning}</skipMultiThreadWarning>
  <source default-value="1.5">1.7</source>
  <staleMillis default-value="0">${lastModGranularityMs}</staleMillis>
  <target default-value="1.5">1.7</target>
  <useIncrementalCompilation default-value="true">${maven.compiler.useIncrementalCompilation}</useIncrementalCompilation>
  <verbose default-value="false">${maven.compiler.verbose}</verbose>
  <mavenSession default-value="${session}"/>
  <session default-value="${session}"/>
</configuration>
[DEBUG] =======================================================================
[DEBUG] aether.artifactDescriptor.threads = 5 
[DEBUG] Using transporter WagonTransporter with priority -1.0 for http://jcenter.bintray.com
[DEBUG] Using connector BasicRepositoryConnector with priority 0.0 for http://jcenter.bintray.com
[INFO] Downloading from bintray: http://jcenter.bintray.com/name/neuhalfen/projects/crypto/bouncycastle/openpgp/bouncy-gpg/2.2.0/bouncy-gpg-2.2.0.pom
[DEBUG] Writing tracking file /home/jens/.m2/repository/name/neuhalfen/projects/crypto/bouncycastle/openpgp/bouncy-gpg/2.2.0/bouncy-gpg-2.2.0.pom.lastUpdated
[DEBUG] Dependency collection stats: {ConflictMarker.analyzeTime=1659023, ConflictMarker.markTime=325904, ConflictMarker.nodeCount=8, ConflictIdSorter.graphTime=897723, ConflictIdSorter.topsortTime=758709, ConflictIdSorter.conflictIdCount=6, ConflictIdSorter.conflictIdCycleCount=0, ConflictResolver.totalTime=7390234, ConflictResolver.conflictItemCount=7, DefaultDependencyCollector.collectTime=409769093, DefaultDependencyCollector.transformTime=15469983}
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.591 s
[INFO] Finished at: 2020-01-23T07:58:00+01:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal on project maven-example: Could not resolve dependencies for project name.neuhalfen.projects.crypto.bouncycastle.openpgp:maven-example:jar:1.0-SNAPSHOT: Failed to collect dependencies at name.neuhalfen.projects.crypto.bouncycastle.openpgp:bouncy-gpg:jar:2.2.0: Failed to read artifact descriptor for name.neuhalfen.projects.crypto.bouncycastle.openpgp:bouncy-gpg:jar:2.2.0: Could not transfer artifact name.neuhalfen.projects.crypto.bouncycastle.openpgp:bouncy-gpg:pom:2.2.0 from/to bintray (http://jcenter.bintray.com): Access denied to: http://jcenter.bintray.com/name/neuhalfen/projects/crypto/bouncycastle/openpgp/bouncy-gpg/2.2.0/bouncy-gpg-2.2.0.pom -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal on project maven-example: Could not resolve dependencies for project name.neuhalfen.projects.crypto.bouncycastle.openpgp:maven-example:jar:1.0-SNAPSHOT: Failed to collect dependencies at name.neuhalfen.projects.crypto.bouncycastle.openpgp:bouncy-gpg:jar:2.2.0
    at org.apache.maven.lifecycle.internal.LifecycleDependencyResolver.getDependencies (LifecycleDependencyResolver.java:269)
    at org.apache.maven.lifecycle.internal.LifecycleDependencyResolver.resolveProjectDependencies (LifecycleDependencyResolver.java:147)
    at org.apache.maven.lifecycle.internal.MojoExecutor.ensureDependenciesAreResolved (MojoExecutor.java:248)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:202)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:956)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:288)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:192)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: org.apache.maven.project.DependencyResolutionException: Could not resolve dependencies for project name.neuhalfen.projects.crypto.bouncycastle.openpgp:maven-example:jar:1.0-SNAPSHOT: Failed to collect dependencies at name.neuhalfen.projects.crypto.bouncycastle.openpgp:bouncy-gpg:jar:2.2.0
    at org.apache.maven.project.DefaultProjectDependenciesResolver.resolve (DefaultProjectDependenciesResolver.java:178)
    at org.apache.maven.lifecycle.internal.LifecycleDependencyResolver.getDependencies (LifecycleDependencyResolver.java:243)
    at org.apache.maven.lifecycle.internal.LifecycleDependencyResolver.resolveProjectDependencies (LifecycleDependencyResolver.java:147)
    at org.apache.maven.lifecycle.internal.MojoExecutor.ensureDependenciesAreResolved (MojoExecutor.java:248)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:202)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:956)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:288)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:192)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: org.eclipse.aether.collection.DependencyCollectionException: Failed to collect dependencies at name.neuhalfen.projects.crypto.bouncycastle.openpgp:bouncy-gpg:jar:2.2.0
    at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.collectDependenciesWithExecutor (DefaultDependencyCollector.java:263)
    at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.collectDependencies (DefaultDependencyCollector.java:155)
    at org.eclipse.aether.internal.impl.DefaultRepositorySystem.collectDependencies (DefaultRepositorySystem.java:284)
    at org.apache.maven.project.DefaultProjectDependenciesResolver.resolve (DefaultProjectDependenciesResolver.java:169)
    at org.apache.maven.lifecycle.internal.LifecycleDependencyResolver.getDependencies (LifecycleDependencyResolver.java:243)
    at org.apache.maven.lifecycle.internal.LifecycleDependencyResolver.resolveProjectDependencies (LifecycleDependencyResolver.java:147)
    at org.apache.maven.lifecycle.internal.MojoExecutor.ensureDependenciesAreResolved (MojoExecutor.java:248)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:202)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:956)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:288)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:192)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: org.eclipse.aether.resolution.ArtifactDescriptorException: Failed to read artifact descriptor for name.neuhalfen.projects.crypto.bouncycastle.openpgp:bouncy-gpg:jar:2.2.0
    at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.loadPom (DefaultArtifactDescriptorReader.java:255)
    at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.readArtifactDescriptor (DefaultArtifactDescriptorReader.java:171)
    at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector$2.call (DefaultDependencyCollector.java:637)
    at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector$2.call (DefaultDependencyCollector.java:632)
    at java.util.concurrent.FutureTask.run (FutureTask.java:264)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1128)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:628)
    at java.lang.Thread.run (Thread.java:834)
Caused by: org.eclipse.aether.resolution.ArtifactResolutionException: Could not transfer artifact name.neuhalfen.projects.crypto.bouncycastle.openpgp:bouncy-gpg:pom:2.2.0 from/to bintray (http://jcenter.bintray.com): Access denied to: http://jcenter.bintray.com/name/neuhalfen/projects/crypto/bouncycastle/openpgp/bouncy-gpg/2.2.0/bouncy-gpg-2.2.0.pom
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve (DefaultArtifactResolver.java:424)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifacts (DefaultArtifactResolver.java:229)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifact (DefaultArtifactResolver.java:207)
    at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.loadPom (DefaultArtifactDescriptorReader.java:240)
    at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.readArtifactDescriptor (DefaultArtifactDescriptorReader.java:171)
    at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector$2.call (DefaultDependencyCollector.java:637)
    at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector$2.call (DefaultDependencyCollector.java:632)
    at java.util.concurrent.FutureTask.run (FutureTask.java:264)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1128)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:628)
    at java.lang.Thread.run (Thread.java:834)
Caused by: org.eclipse.aether.transfer.ArtifactTransferException: Could not transfer artifact name.neuhalfen.projects.crypto.bouncycastle.openpgp:bouncy-gpg:pom:2.2.0 from/to bintray (http://jcenter.bintray.com): Access denied to: http://jcenter.bintray.com/name/neuhalfen/projects/crypto/bouncycastle/openpgp/bouncy-gpg/2.2.0/bouncy-gpg-2.2.0.pom
    at org.eclipse.aether.connector.basic.ArtifactTransportListener.transferFailed (ArtifactTransportListener.java:52)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector$TaskRunner.run (BasicRepositoryConnector.java:369)
    at org.eclipse.aether.util.concurrency.RunnableErrorForwarder$1.run (RunnableErrorForwarder.java:75)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector$DirectExecutor.execute (BasicRepositoryConnector.java:644)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector.get (BasicRepositoryConnector.java:262)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.performDownloads (DefaultArtifactResolver.java:499)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve (DefaultArtifactResolver.java:401)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifacts (DefaultArtifactResolver.java:229)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifact (DefaultArtifactResolver.java:207)
    at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.loadPom (DefaultArtifactDescriptorReader.java:240)
    at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.readArtifactDescriptor (DefaultArtifactDescriptorReader.java:171)
    at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector$2.call (DefaultDependencyCollector.java:637)
    at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector$2.call (DefaultDependencyCollector.java:632)
    at java.util.concurrent.FutureTask.run (FutureTask.java:264)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1128)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:628)
    at java.lang.Thread.run (Thread.java:834)
Caused by: org.apache.maven.wagon.authorization.AuthorizationException: Access denied to: http://jcenter.bintray.com/name/neuhalfen/projects/crypto/bouncycastle/openpgp/bouncy-gpg/2.2.0/bouncy-gpg-2.2.0.pom
    at org.apache.maven.wagon.providers.http.wagon.shared.AbstractHttpClientWagon.fillInputData (AbstractHttpClientWagon.java:1141)
    at org.apache.maven.wagon.providers.http.wagon.shared.AbstractHttpClientWagon.fillInputData (AbstractHttpClientWagon.java:1094)
    at org.apache.maven.wagon.StreamWagon.getInputStream (StreamWagon.java:126)
    at org.apache.maven.wagon.StreamWagon.getIfNewer (StreamWagon.java:88)
    at org.apache.maven.wagon.StreamWagon.get (StreamWagon.java:61)
    at org.eclipse.aether.transport.wagon.WagonTransporter$GetTaskRunner.run (WagonTransporter.java:567)
    at org.eclipse.aether.transport.wagon.WagonTransporter.execute (WagonTransporter.java:435)
    at org.eclipse.aether.transport.wagon.WagonTransporter.get (WagonTransporter.java:412)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector$GetTaskRunner.runTask (BasicRepositoryConnector.java:457)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector$TaskRunner.run (BasicRepositoryConnector.java:364)
    at org.eclipse.aether.util.concurrency.RunnableErrorForwarder$1.run (RunnableErrorForwarder.java:75)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector$DirectExecutor.execute (BasicRepositoryConnector.java:644)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector.get (BasicRepositoryConnector.java:262)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.performDownloads (DefaultArtifactResolver.java:499)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve (DefaultArtifactResolver.java:401)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifacts (DefaultArtifactResolver.java:229)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifact (DefaultArtifactResolver.java:207)
    at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.loadPom (DefaultArtifactDescriptorReader.java:240)
    at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.readArtifactDescriptor (DefaultArtifactDescriptorReader.java:171)
    at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector$2.call (DefaultDependencyCollector.java:637)
    at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector$2.call (DefaultDependencyCollector.java:632)
    at java.util.concurrent.FutureTask.run (FutureTask.java:264)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1128)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:628)
    at java.lang.Thread.run (Thread.java:834)
[ERROR] 
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException

The gist of seems to be:

Caused by: org.apache.maven.wagon.authorization.AuthorizationException: Access denied to: http://jcenter.bintray.com/name/neuhalfen/projects/crypto/bouncycastle/openpgp/bouncy-gpg/2.2.0/bouncy-gpg-2.2.0.pom

Expected behavior

The artifact bouncy-gpg-2.2.0 should be downloaded and used.

System

  • OS: Ubuntu 18.04
  • Java: openjdk version "11.0.5" 2019-10-15
  • Version: 2.2.0
  • maven version: Apache Maven 3.6.1

Additional context

curl

curl  http://jcenter.bintray.com/name/neuhalfen/projects/crypto/bouncycastle/openpgp/bouncy-gpg/2.2.0/bouncy-gpg-2.2.0.pom
<!DOCTYPE HTML>
<html lang="en-US">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="refresh" content="0; url=https://jfrog.com/jcenter-http/">
        <script type="text/javascript">
            window.location.href = "https://jfrog.com/jcenter-http/"
        </script>
        <title>HTTP not supported</title>
    </head>
    <body>
        JCenter only supports HTTPS requests for both the user interface and the APIs, read more <a href='https://jfrog.com/jcenter-http/'>here</a>.
    </body>
</html>

Gradle

It works with gradle:

cd bouncy-gpg/examples/encrypt
rm -rf  ~/.gradle/caches/modules-2/files-2.1/name.neuhalfen.projects.crypto.bouncycastle.openpgp 
rm -rf  ~/.gradle/caches/modules-2/metadata-2.63/descriptors/name.neuhalfen.projects.crypto.bouncycastle.openpgp

rm -rf target
./gradlew assemble

FR: Encrypt to multiple recipients + encrypt to self

I have two feature request that could be combined into one.
First I would like to be able to encrypt to multiple user ids.
Second I would like to (optionally) also encrypt to myself. The second of course can be done with the first. But maybe it would be nicer to have it as a paramater in the fluid interface. like ….andEncryptToSelf() or something like that.

I could provide a PR if we can agree on the API. For the first feature i would let the toRecipient() just take String... instead of String and then feed a Collection into the EncryptionStream class.

Support keyId in all APIs

Is your feature request related to a problem? Please describe.

Some parts of BuildDecryptionInputStreamAPI/BuildEncryptionOutputStreamAPI accept keyIds and userIds, others only the userIds. This makes it harder to work with keys where the keyId is known, but not the userId.

Describe the solution you'd like
Extend the APIs to add keyId parameters

Describe alternatives you've considered
All of them ugly

Additional context
See issue #26

Not included in jcenter

The library went missing in jcenter. A ticket has been opened.

As a workaround:

Drop this in the root level of pom.xml:

<repositories>
    <repository>
        <id>bintray</id>
        <name>bintray</name>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
        <url>http://dl.bintray.com/neuhalje/maven</url>
    </repository>
</repositories>

and this dependency snippet:

    <dependency>
        <groupId>name.neuhalfen.projects.crypto.bouncycastle.openpgp</groupId>
        <artifactId>bouncy-gpg</artifactId>
        <version>2.0.1</version>
    </dependency>

(Thanks to @jayceekay)

Method for returning keys and/or IDs from decryption?

Could I request a method that allows the caller to extract exactly which key(s) were used to decrypt, and which key(s) were used for signature verification, after the decryption has completed?

I have a working solution, but it is a Frankensteinian monster that tramples all over your elegant design, and I am ashamed.

Maven central

Great and much needed project. Do you have plans to push releases to Maven central?

Recommendation: Implement SOP interface to benefit from test.sequoia-pgp.org

The folks over at sequoia-pgp.org are doing a great job of improving the OpenPGP ecosystem. What helped me a lot to gain a deeper understanding of OpenPGP signatures and verification was to implement the Stateless OpenPGP Command Line Interface which allows to plug an implementation into the sequoia interoperability test suite which uncovered a ton of things I missed.

The SOP specification describes a minimal command-line application which can be used to test different implementations against each other and against certain test cases.
The suite goes into great detail and contains lots of checks that otherwise easily slip the radar.

I can highly recommend implementing the interface to improve bouncy-gpg.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.