OpenPGP: Add subkey to existing PGPSecretKeyRing

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

OpenPGP: Add subkey to existing PGPSecretKeyRing

Paul Schaub-2
Hi everyone!

I'm developing a free software library that strives to make using
OpenPGP with BouncyCastle as easy as possible.

PGPainless: https://github.com/pgpainless/pgpainless

Currently I'm working on the feature of adding sub keys to existing key
rings.

For that purpose I created a PGPSecretKey which I want to use as the sub
key:

        PGPKeyPair keyPair = KeyRingBuilder.generateKeyPair(keySpec);
        PGPSecretKey secretSubKey = new
PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(),
                checksumCalculator, false, subKeyEncryptor);

As you can see I set the flag isMasterKey to false.

Next I generate a subkey binding signature and add it to the sub key:

        signatureGenerator.init(SignatureType.SUBKEY_BINDING.getCode(),
primaryPrivateKey);
        signatureGenerator.generateCertification(subPublicKey);
        PGPSignature bindingSig = signatureGenerator.generate();
        PGPPublicKey publicSubKey =
PGPPublicKey.addCertification(secretSubKey.getPublicKey(), bindingSig);
        secretSubKey = PGPSecretKey.replacePublicKey(secretSubKey,
publicSubKey);

Now, when I try to insert the subKey into the key ring, I get an
exception stating that only one master key can exist in the key ring.

I figured out that during insertion, subKey.isMasterKey() is called on
the subKey. This method returns true iff the list of subSigs on the
public key is null.

Now my question is: How can I get that list to be non-null? Ideally I'd
want to use one of the package-visible constructors of PGPPublicKey to
create the public key with a list that contains my binding signature,
but when I try to access the constructor by creating another class in
the org.bouncycastle.openpgp package namespace, I get a
SecurityException that states that the signer information of my class
does not match that of PGPPublicKey.

I guess there must be another way to generate valid subkeys? What is the
intended way of using BC to add subkeys to existing PGPSecretKeyRings?

Related PGPainless ticket:
https://github.com/pgpainless/pgpainless/issues/20

Paul



Reply | Threaded
Open this post in threaded view
|

Re: OpenPGP: Add subkey to existing PGPSecretKeyRing

David Hook-3

We actually did some work on this in 1.67.

Have a look at:

https://github.com/bcgit/bc-java/blob/66d368da88c018cc79840711bfd308a9ec35fbea/pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyRingTest.java#L3311

for an example of the current approach.

Happy to hear any feedback, we have been working on this on the basis of
specific use cases, it wouldn't surprise me if things are still more
complicated than they need to be.

Regards,

David

On 8/11/20 3:48 am, Paul Schaub wrote:

> Hi everyone!
>
> I'm developing a free software library that strives to make using
> OpenPGP with BouncyCastle as easy as possible.
>
> PGPainless: https://github.com/pgpainless/pgpainless
>
> Currently I'm working on the feature of adding sub keys to existing key
> rings.
>
> For that purpose I created a PGPSecretKey which I want to use as the sub
> key:
>
>         PGPKeyPair keyPair = KeyRingBuilder.generateKeyPair(keySpec);
>         PGPSecretKey secretSubKey = new
> PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(),
>                 checksumCalculator, false, subKeyEncryptor);
>
> As you can see I set the flag isMasterKey to false.
>
> Next I generate a subkey binding signature and add it to the sub key:
>
>         signatureGenerator.init(SignatureType.SUBKEY_BINDING.getCode(),
> primaryPrivateKey);
>         signatureGenerator.generateCertification(subPublicKey);
>         PGPSignature bindingSig = signatureGenerator.generate();
>         PGPPublicKey publicSubKey =
> PGPPublicKey.addCertification(secretSubKey.getPublicKey(), bindingSig);
>         secretSubKey = PGPSecretKey.replacePublicKey(secretSubKey,
> publicSubKey);
>
> Now, when I try to insert the subKey into the key ring, I get an
> exception stating that only one master key can exist in the key ring.
>
> I figured out that during insertion, subKey.isMasterKey() is called on
> the subKey. This method returns true iff the list of subSigs on the
> public key is null.
>
> Now my question is: How can I get that list to be non-null? Ideally I'd
> want to use one of the package-visible constructors of PGPPublicKey to
> create the public key with a list that contains my binding signature,
> but when I try to access the constructor by creating another class in
> the org.bouncycastle.openpgp package namespace, I get a
> SecurityException that states that the signer information of my class
> does not match that of PGPPublicKey.
>
> I guess there must be another way to generate valid subkeys? What is the
> intended way of using BC to add subkeys to existing PGPSecretKeyRings?
>
> Related PGPainless ticket:
> https://github.com/pgpainless/pgpainless/issues/20
>
> Paul
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: OpenPGP: Add subkey to existing PGPSecretKeyRing

Paul Schaub-2
Hey David,

These changes actually helped me with my problem :) Thank you!

Paul

Am 19.11.20 um 23:45 schrieb David Hook:

> We actually did some work on this in 1.67.
>
> Have a look at:
>
> https://github.com/bcgit/bc-java/blob/66d368da88c018cc79840711bfd308a9ec35fbea/pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyRingTest.java#L3311
>
> for an example of the current approach.
>
> Happy to hear any feedback, we have been working on this on the basis of
> specific use cases, it wouldn't surprise me if things are still more
> complicated than they need to be.
>
> Regards,
>
> David
>
> On 8/11/20 3:48 am, Paul Schaub wrote:
>> Hi everyone!
>>
>> I'm developing a free software library that strives to make using
>> OpenPGP with BouncyCastle as easy as possible.
>>
>> PGPainless: https://github.com/pgpainless/pgpainless
>>
>> Currently I'm working on the feature of adding sub keys to existing key
>> rings.
>>
>> For that purpose I created a PGPSecretKey which I want to use as the sub
>> key:
>>
>>         PGPKeyPair keyPair = KeyRingBuilder.generateKeyPair(keySpec);
>>         PGPSecretKey secretSubKey = new
>> PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(),
>>                 checksumCalculator, false, subKeyEncryptor);
>>
>> As you can see I set the flag isMasterKey to false.
>>
>> Next I generate a subkey binding signature and add it to the sub key:
>>
>>         signatureGenerator.init(SignatureType.SUBKEY_BINDING.getCode(),
>> primaryPrivateKey);
>>         signatureGenerator.generateCertification(subPublicKey);
>>         PGPSignature bindingSig = signatureGenerator.generate();
>>         PGPPublicKey publicSubKey =
>> PGPPublicKey.addCertification(secretSubKey.getPublicKey(), bindingSig);
>>         secretSubKey = PGPSecretKey.replacePublicKey(secretSubKey,
>> publicSubKey);
>>
>> Now, when I try to insert the subKey into the key ring, I get an
>> exception stating that only one master key can exist in the key ring.
>>
>> I figured out that during insertion, subKey.isMasterKey() is called on
>> the subKey. This method returns true iff the list of subSigs on the
>> public key is null.
>>
>> Now my question is: How can I get that list to be non-null? Ideally I'd
>> want to use one of the package-visible constructors of PGPPublicKey to
>> create the public key with a list that contains my binding signature,
>> but when I try to access the constructor by creating another class in
>> the org.bouncycastle.openpgp package namespace, I get a
>> SecurityException that states that the signer information of my class
>> does not match that of PGPPublicKey.
>>
>> I guess there must be another way to generate valid subkeys? What is the
>> intended way of using BC to add subkeys to existing PGPSecretKeyRings?
>>
>> Related PGPainless ticket:
>> https://github.com/pgpainless/pgpainless/issues/20
>>
>> Paul
>>
>>
>>
>