Restoring PGPPublicKeyRing from bytes discards additional PGPPublicKeys

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Restoring PGPPublicKeyRing from bytes discards additional PGPPublicKeys

Paul Schaub
Hi!

In my project I wrote code to generate an elliptic curve key ring. A key
ring consists of an ECDSA key pair used for signing and a second ECDHE
key pair used for encryption.

When I serialize the key ring and create a new instance from bytes, the
key ring only contains the first key pair. The second one gets discarded.

PGPPublicKeyRing ring = ...
byte[] bytes = ring.getEncoded(true);
PGPPublicKeyRing parsed = new PGPPublicKeyRing(bytes);

By stepping through the execution, I figured, that the cause of this
issue is probably, that the constructor of PGPPublicKey only checks for
the packet tag of a PUBLIC_SUBKEY, while the second key has the packet
type PUBLIC_KEY.
See
https://github.com/bcgit/bc-java/blob/master/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKeyRing.java#L114

I suspect, that the constructor of PGPPublicKey is probably doing the
right thing, but the question is, what did I wrong then when creating my
key ring / why does the getEncoded() method use PUBLIC_KEY as packet tag
instead of PUBLIC_SUBKEY?

I added the subkey as follows:

PGPKeyRingGenerator ringGenerator = new PGPKeyRingGenerator(
    PGPSignature.POSITIVE_CERTIFICATION, certKey,
    userId, calculator,
    hashedSubPackets, null, signer, encryptor);

PGPKeyPair subKey = generateKeyPair(subKeySpec); // Generates a PGPKey pair
ringGenerator.addSubKey(subKey);

My code can be found here:
https://github.com/vanitasvitae/pgpainless/blob/master/src/main/java/org/pgpainless/pgpainless/key/generation/KeyRingBuilder.java

Paul



Reply | Threaded
Open this post in threaded view
|

Re: Restoring PGPPublicKeyRing from bytes discards additional PGPPublicKeys

Paul Schaub
Hi again!

Using gpg --list-packets I can confirm, that the bytes I get from
publicKeyRing.getEncoded() are consisting of two public keys (the second
key is no sub key).

I retrieved the PGPPublicKeyRing from the PGPSecretKeyRing I generated
by using the following code (maybe that is wrong?)

    public static PGPPublicKeyRing
publicKeyRingFromSecretKeyRing(PGPSecretKeyRing secring) {
        List<PGPPublicKey> list = new ArrayList<>();
        for (Iterator<PGPPublicKey> i = secring.getPublicKeys();
i.hasNext(); ) {
            PGPPublicKey k = i.next();
            list.add(k);
        }

        return new PGPPublicKeyRing(list);
    }

Is there a proper way to do this?

Paul

Am 11.07.2018 um 15:43 schrieb Paul Schaub:

> Hi!
>
> In my project I wrote code to generate an elliptic curve key ring. A key
> ring consists of an ECDSA key pair used for signing and a second ECDHE
> key pair used for encryption.
>
> When I serialize the key ring and create a new instance from bytes, the
> key ring only contains the first key pair. The second one gets discarded.
>
> PGPPublicKeyRing ring = ...
> byte[] bytes = ring.getEncoded(true);
> PGPPublicKeyRing parsed = new PGPPublicKeyRing(bytes);
>
> By stepping through the execution, I figured, that the cause of this
> issue is probably, that the constructor of PGPPublicKey only checks for
> the packet tag of a PUBLIC_SUBKEY, while the second key has the packet
> type PUBLIC_KEY.
> See
> https://github.com/bcgit/bc-java/blob/master/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKeyRing.java#L114
>
> I suspect, that the constructor of PGPPublicKey is probably doing the
> right thing, but the question is, what did I wrong then when creating my
> key ring / why does the getEncoded() method use PUBLIC_KEY as packet tag
> instead of PUBLIC_SUBKEY?
>
> I added the subkey as follows:
>
> PGPKeyRingGenerator ringGenerator = new PGPKeyRingGenerator(
>     PGPSignature.POSITIVE_CERTIFICATION, certKey,
>     userId, calculator,
>     hashedSubPackets, null, signer, encryptor);
>
> PGPKeyPair subKey = generateKeyPair(subKeySpec); // Generates a PGPKey pair
> ringGenerator.addSubKey(subKey);
>
> My code can be found here:
> https://github.com/vanitasvitae/pgpainless/blob/master/src/main/java/org/pgpainless/pgpainless/key/generation/KeyRingBuilder.java
>
> Paul
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Restoring PGPPublicKeyRing from bytes discards additional PGPPublicKeys

David Hook-3
In reply to this post by Paul Schaub

Yep, this is a bug in our generator, well at least when the secret key
ring is used to source a public key ring at any rate.

This should be fixed in the latest beta https://www.bouncycastle.org/betas

Regards,

David

On 11/07/18 23:43, Paul Schaub wrote:

> Hi!
>
> In my project I wrote code to generate an elliptic curve key ring. A key
> ring consists of an ECDSA key pair used for signing and a second ECDHE
> key pair used for encryption.
>
> When I serialize the key ring and create a new instance from bytes, the
> key ring only contains the first key pair. The second one gets discarded.
>
> PGPPublicKeyRing ring = ...
> byte[] bytes = ring.getEncoded(true);
> PGPPublicKeyRing parsed = new PGPPublicKeyRing(bytes);
>
> By stepping through the execution, I figured, that the cause of this
> issue is probably, that the constructor of PGPPublicKey only checks for
> the packet tag of a PUBLIC_SUBKEY, while the second key has the packet
> type PUBLIC_KEY.
> See
> https://github.com/bcgit/bc-java/blob/master/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKeyRing.java#L114
>
> I suspect, that the constructor of PGPPublicKey is probably doing the
> right thing, but the question is, what did I wrong then when creating my
> key ring / why does the getEncoded() method use PUBLIC_KEY as packet tag
> instead of PUBLIC_SUBKEY?
>
> I added the subkey as follows:
>
> PGPKeyRingGenerator ringGenerator = new PGPKeyRingGenerator(
>     PGPSignature.POSITIVE_CERTIFICATION, certKey,
>     userId, calculator,
>     hashedSubPackets, null, signer, encryptor);
>
> PGPKeyPair subKey = generateKeyPair(subKeySpec); // Generates a PGPKey pair
> ringGenerator.addSubKey(subKey);
>
> My code can be found here:
> https://github.com/vanitasvitae/pgpainless/blob/master/src/main/java/org/pgpainless/pgpainless/key/generation/KeyRingBuilder.java
>
> Paul
>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Restoring PGPPublicKeyRing from bytes discards additional PGPPublicKeys

David Hook-3
In reply to this post by Paul Schaub

Yep, same issue again I suspect...

Regards,

David

On 12/07/18 00:01, Paul Schaub wrote:

> Hi again!
>
> Using gpg --list-packets I can confirm, that the bytes I get from
> publicKeyRing.getEncoded() are consisting of two public keys (the second
> key is no sub key).
>
> I retrieved the PGPPublicKeyRing from the PGPSecretKeyRing I generated
> by using the following code (maybe that is wrong?)
>
>     public static PGPPublicKeyRing
> publicKeyRingFromSecretKeyRing(PGPSecretKeyRing secring) {
>         List<PGPPublicKey> list = new ArrayList<>();
>         for (Iterator<PGPPublicKey> i = secring.getPublicKeys();
> i.hasNext(); ) {
>             PGPPublicKey k = i.next();
>             list.add(k);
>         }
>
>         return new PGPPublicKeyRing(list);
>     }
>
> Is there a proper way to do this?
>
> Paul
>
> Am 11.07.2018 um 15:43 schrieb Paul Schaub:
>> Hi!
>>
>> In my project I wrote code to generate an elliptic curve key ring. A key
>> ring consists of an ECDSA key pair used for signing and a second ECDHE
>> key pair used for encryption.
>>
>> When I serialize the key ring and create a new instance from bytes, the
>> key ring only contains the first key pair. The second one gets discarded.
>>
>> PGPPublicKeyRing ring = ...
>> byte[] bytes = ring.getEncoded(true);
>> PGPPublicKeyRing parsed = new PGPPublicKeyRing(bytes);
>>
>> By stepping through the execution, I figured, that the cause of this
>> issue is probably, that the constructor of PGPPublicKey only checks for
>> the packet tag of a PUBLIC_SUBKEY, while the second key has the packet
>> type PUBLIC_KEY.
>> See
>> https://github.com/bcgit/bc-java/blob/master/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKeyRing.java#L114
>>
>> I suspect, that the constructor of PGPPublicKey is probably doing the
>> right thing, but the question is, what did I wrong then when creating my
>> key ring / why does the getEncoded() method use PUBLIC_KEY as packet tag
>> instead of PUBLIC_SUBKEY?
>>
>> I added the subkey as follows:
>>
>> PGPKeyRingGenerator ringGenerator = new PGPKeyRingGenerator(
>>     PGPSignature.POSITIVE_CERTIFICATION, certKey,
>>     userId, calculator,
>>     hashedSubPackets, null, signer, encryptor);
>>
>> PGPKeyPair subKey = generateKeyPair(subKeySpec); // Generates a PGPKey pair
>> ringGenerator.addSubKey(subKey);
>>
>> My code can be found here:
>> https://github.com/vanitasvitae/pgpainless/blob/master/src/main/java/org/pgpainless/pgpainless/key/generation/KeyRingBuilder.java
>>
>> Paul
>>
>>
>>
>
>