bc-java
bc-java copied to clipboard
Feature request: Expose API for copying PGPPublicKey
Consider a scenario when a PGP key is acquired from a remote server and we only care about the master key and (probably) subkeys. The downloaded key might contain a lot of irrelevant data like images or user ids. There should be a way to transform PGPKeyring to remove unnecessary data from it.
Right now it is possible with this constructor for master key and this constructor for a subkey, but they are both are package private.
See an example of usage here.
Other scenarios might include GDPR handling (stripping any private data from a key) or size considerations (keeping a keyring as small as possible).
okay, interesting, as the example usage points out, there's a bit of list juggling to keep everything in sync. What if rather than exposing the constructors we add an extract method, something like PGPKeyRing.extract(PGPKeyRing.KEYS | PGPKeyRing.SIGNATURES) which would return just the keys and key signatures? I'm not sure how far we could push it but at least we should be able to ensure correctness.
Ensuring correctness is nice, yeah. However, I doubt It would be extensible enough to support all possible key transformations. I think extraction might be feasible with some sort of builder class for PGPKey.
I suspect there'll be a point where just parsing the encoding and ignoring things would be the easiest way to do this... For the use case described, you're trying to generate a list of keys with their associated certifications but have all the user information and trust packets stripped out. Is that correct?
Actually, I was thinking about this encoding/decoding, but found it a bit cumbersome in the end. As a user, I expect that library provides abstraction on lower-lever details and I don’t like the idea of serializing/deserializing stuff just to change something. It’s something like doing JSON.parse(JSON.stringify(o)); to get a deep copy of an object in JS.
Yes, your description of my case is correct. At first we decided to strip all userIDs, but then we decided to leave one for debugging purposes.
Another use-case that is probably related to this:
OpenPGP v6 introduces minimal key-revocation certificates. To revoke a key(ring), it will be sufficient to distribute only the bare primary key (no user-ids, no signatures) with a single revocation signature. To extract only the bare key, it is currently required to strip all signatures, userIds and attributes one-by-one from a copy of the original key. An API that allows to directly create a copy from the public key would be nice to reduce the complexity here.
I found that stripping any additional packets from the a public key works best using this constructor.
With it, I can clean a whole key ring simply using this method:
PGPPublicKeyRing original = ...;
KeyFingerprintCalculator fpCalc = ...;
List<PGPPublicKey> cleaned = new ArrayList<>();
Iterator<PGPPublicKey> it = original.getPublicKeys();
while(it.hasNext()) {
PGPPublicKey cleanedKey = new PGPPublicKey(it.next().getPublicKeyPacket(), fpCalc);
cleaned.add(cleanedKey);
}
PGPPublicKeyRing cleanedKeyRing = new PGPPublicKeyRing(cleaned);