neuhalje / bouncy-gpg

Make using Bouncy Castle with OpenPGP fun again!
https://neuhalje.github.io/bouncy-gpg/
Other
205 stars 58 forks source link

Support flag on keys without sub keys #34

Closed naude-r closed 4 years ago

naude-r commented 5 years ago

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
neuhalje commented 5 years ago

@naude-r , any idea what the correct gpg commandline call would be to create such a key?

btw: 1024 is no longer considered secure

naude-r commented 5 years ago

@neuhalje not sure. looking at the key it was generated with the .net libraries: Version: BCPG C# v2.0.0.0

the key can be provided if you would like to inspect it.

naude-r commented 5 years ago

@neuhalje got it working using the commandline:

gpg --full-generate-key --expert
  1. choose option 8: (8) RSA (set your own capabilities)
  2. keep actions as is (Q Finished)
  3. any validity
  4. any test uid
  5. choose okay

output for the test key:

pub   rsa2048 2019-06-13 [SCE] [expires: 2022-06-12]
      E3649F0241561C8321C797AA31B84A579D67666A
uid                      Testing (Primary key test) <testing@example3.org>

hope this helps.

neuhalje commented 5 years ago

Thank you! - I'll look into this (probably next week)

neuhalje commented 4 years ago

It seems: next week is already over ..

neuhalje commented 4 years ago

@naude-r it seems to be fixed now. I could not reproduce it in bc167c4, so maybe I had fixed it before.

naude-r commented 4 years ago

@neuhalje re-tested using version 2.2.0.

still failing. have updated EncryptionScenariosTest with relevant key + uid. would be happy to send this to you.

neuhalje commented 4 years ago

@naude-r please send it to me. Could you attach it to the ticket?

naude-r commented 4 years ago

-----BEGIN PGP PUBLIC KEY BLOCK----- Version: BCPG C# v2.0.0.0

mI0EXXjmnwEEAMF/BtQCgedgaALZfSx+QEYKJXl3+N5Lk3I40AoSiPdQI1WIw7Yg +jWmVAwvTxI9CSe/37bASd1I30PGonKKB7FLTnCBwGlkUIeAXp35qu1QVo6v/o9V dESisXz+wtH4Vs77UV8qICnonGze2CuVUKprzFS3oKOEgv1NyONBjQTtABEBAAG0 LnR1c2VwMjAxOXhkczIwMTl2Y2NiaXNoZXJld2gyZGFsb2Y3ZXhwY29tcHNjb3OI ogQQAQIADAUCXXjmnwWJAMB6AgAKCRBlpeBT3lPwt9g7A/9y+FRq7GKhsdBHCB/l pqeFyTU0g7sOKF1CPZnDLrb2uYSQAgQ8HSvoQ+oXf45I1peq3FS+FqYmfE9Ok5qM CU6ObYYX3DbBQaSZDM+pplhURJYV6HnuXVQ4TosDV0+d8cjD3kr+gFFAvT5ePa4F 0BdJss42Zi06n8CGNicFmVWPYQ== =ArbK -----END PGP PUBLIC KEY `BLOCK-----

recipientId = tusep2019xds2019vccbisherewh2dalof7expcompscos

neuhalje commented 4 years ago

$DAYJOB starts in a few minutes. Here is my first analysis:

The key is importable by GPG but has a different structure

gpg --import pubkey.gpg
gpg: key 0x65A5E053DE53F0B7: public key "tusep2019xds2019vccbisherewh2dalof7expcompscos" imported
gpg: Total number processed: 1
gpg:               imported: 1

Here is a comparison between you key, and the key I generated from your instructions:

# Your Key

 gpg --list-packets  pubkey.gpg 
# off=0 ctb=98 tag=6 hlen=2 plen=141
:public key packet:
        version 4, algo 1, created 1568204447, expires 0
        pkey[0]: [1024 bits]
        pkey[1]: [17 bits]
        keyid: 65A5E053DE53F0B7
# off=143 ctb=b4 tag=13 hlen=2 plen=46
:user ID packet: "tusep2019xds2019vccbisherewh2dalof7expcompscos"
# off=191 ctb=88 tag=2 hlen=2 plen=162
:signature packet: algo 1, keyid 65A5E053DE53F0B7
        version 4, created 1568204447, md5len 0, sigclass 0x10
        digest algo 2, begin of digest d8 3b
        hashed subpkt 2 len 4 (sig created 2019-09-11)
        critical hashed subpkt 9 len 4 (key expires after 145d23h55m)
        subpkt 16 len 8 (issuer key ID 65A5E053DE53F0B7)
        data: [1023 bits]

And here is my key:

gpg --list-packets  my_key.gpg 
# off=0 ctb=99 tag=6 hlen=3 plen=269
:public key packet:
        version 4, algo 1, created 1579425324, expires 0
        pkey[0]: [2048 bits]
        pkey[1]: [17 bits]
        keyid: A3EE3A40BD8A546B
# off=272 ctb=b4 tag=13 hlen=2 plen=78
:user ID packet: "Only Masterkey, No Subkeys (This key has no sub keys) <no_subkeys@example.com>"
# off=352 ctb=89 tag=2 hlen=3 plen=331
:signature packet: algo 1, keyid A3EE3A40BD8A546B
        version 4, created 1579425324, md5len 0, sigclass 0x13
        digest algo 10, begin of digest 15 14
        hashed subpkt 33 len 21 (issuer fpr v4 A62BCB74561AECF0CA06D52CA3EE3A40BD8A546B)
        hashed subpkt 2 len 4 (sig created 2020-01-19)
        hashed subpkt 27 len 1 (key flags: 0F)
        hashed subpkt 11 len 7 (pref-sym-algos: 9 8 7 13 12 11 10)
        hashed subpkt 21 len 4 (pref-hash-algos: 10 9 8 11)
        hashed subpkt 30 len 1 (features: 01)
        hashed subpkt 23 len 1 (keyserver preferences: 80)
        subpkt 16 len 8 (issuer key ID A3EE3A40BD8A546B)
        data: [2047 bits]

The error is thrown in bouncy castle

The error is thrown by bouncy-castle when calling:

    try (
        InputStream raw = new ByteArrayInputStream(encodedPublicKey);
        InputStream decoded = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(raw)
    ) {
     // the error is raised here, in the constructor of PGPPublicKeyRing
      final PGPPublicKeyRing pgpPub = new PGPPublicKeyRing(decoded, getKeyFingerPrintCalculator());

      addPublicKeyRing(pgpPub);
    }
java.io.IOException: public key ring doesn't start with public key tag: tag 0xffffffff

    at org.bouncycastle.openpgp.PGPPublicKeyRing.<init>(Unknown Source)
    at name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.InMemoryKeyring.addPublicKey(InMemoryKeyring.java:68)
...
neuhalje commented 4 years ago

BTW: your key looks fishy. In the last line there is a superflous "`" before BLOCK:

-----END PGP PUBLIC KEY `BLOCK-----

Removing it does not change the result though

naude-r commented 4 years ago

apologies, my mistake. was trying to quote it.

bouncycastle do import the key. the problem arise when attempting to use it for encryption.

EncryptionScenariosTest fails with: org.bouncycastle.openpgp.PGPException: No (suitable) public key for encryption to tusep2019xds2019vccbisherewh2dalof7expcompscos found

neuhalje commented 4 years ago

Fixing that, and removing the leading spaces leads me to the following root cause: The key has no key-flags. It needs either the KeyFlag.ENCRYPT_COMMS) or the KeyFlag.ENCRYPT_STORAGE.

I see two solutions:

naude-r commented 4 years ago

thank you. we do not have control over the key. it is provided by a 3rd party.

for now our work-round is as above (overriding isEnryptionKey. not great, but not much we can do about that.