From 0902e060f737324434ec019f7d68d1320f733416 Mon Sep 17 00:00:00 2001 From: Roan Hofland Date: Tue, 22 Oct 2019 02:16:43 +0200 Subject: [PATCH] GpgKeyLocator: Return a signing key for a user instead of the master key Currently when a GPG key is looked up using a user identity the first key from the keyring that has this user identity is returned. The code was changed to instead return the first signing [S] key in this keyring and only return the master key if no such signing key was found. If the master key also does not have the signing flag set null is returned instead. Bug: 552288 Change-Id: I194862991d13c2c7ff34a60a54a227167f88f53b Signed-off-by: Roan Hofland --- .../internal/BouncyCastleGpgKeyLocator.java | 41 ++++++++++++++++--- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java index c662ada7c..e3233590f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java @@ -72,12 +72,14 @@ import org.bouncycastle.gpg.keybox.PublicKeyRingBlob; import org.bouncycastle.gpg.keybox.UserID; import org.bouncycastle.gpg.keybox.jcajce.JcaKeyBoxBuilder; import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPKeyFlags; import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; import org.bouncycastle.openpgp.PGPSecretKey; import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; +import org.bouncycastle.openpgp.PGPSignature; import org.bouncycastle.openpgp.PGPUtil; import org.bouncycastle.openpgp.operator.PBEProtectionRemoverFactory; import org.bouncycastle.openpgp.operator.PGPDigestCalculatorProvider; @@ -212,7 +214,7 @@ class BouncyCastleGpgKeyLocator { throws IOException { for (UserID userID : keyBlob.getUserIds()) { if (containsSigningKey(userID.getUserIDAsString())) { - return getFirstPublicKey(keyBlob); + return getSigningPublicKey(keyBlob); } } return null; @@ -517,17 +519,44 @@ class BouncyCastleGpgKeyLocator { return null; } - private PGPPublicKey getFirstPublicKey(KeyBlob keyBlob) throws IOException { - return ((PublicKeyRingBlob) keyBlob).getPGPPublicKeyRing() - .getPublicKey(); - } - private PGPPublicKey getPublicKey(KeyBlob blob, byte[] fingerprint) throws IOException { return ((PublicKeyRingBlob) blob).getPGPPublicKeyRing() .getPublicKey(fingerprint); } + private PGPPublicKey getSigningPublicKey(KeyBlob blob) throws IOException { + PGPPublicKey masterKey = null; + Iterator keys = ((PublicKeyRingBlob) blob) + .getPGPPublicKeyRing().getPublicKeys(); + while (keys.hasNext()) { + PGPPublicKey key = keys.next(); + // only consider keys that have the [S] usage flag set + if (isSigningKey(key)) { + if (key.isMasterKey()) { + masterKey = key; + } else { + return key; + } + } + } + // return the master key if no other signing key was found or null if + // the master key did not have the signing flag set + return masterKey; + } + + private boolean isSigningKey(PGPPublicKey key) { + Iterator signatures = key.getSignatures(); + while (signatures.hasNext()) { + PGPSignature sig = (PGPSignature) signatures.next(); + if ((sig.getHashedSubPackets().getKeyFlags() + & PGPKeyFlags.CAN_SIGN) > 0) { + return true; + } + } + return false; + } + private KeyBox readKeyBoxFile(Path keyboxFile) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, NoOpenPgpKeyException {