diff options
author | Thomas Wolf <thomas.wolf@paranor.ch> | 2020-06-17 18:43:32 +0200 |
---|---|---|
committer | Matthias Sohn <matthias.sohn@sap.com> | 2020-09-05 21:03:38 +0200 |
commit | 38015e3d36369c7e43916117df7d0f2f8da8344b (patch) | |
tree | fdfc4b52ae6df2676f48d4af34afd0e99d033707 /org.eclipse.jgit.gpg.bc | |
parent | 920442ff42f2656ca4c9a748a05409baa5b16706 (diff) | |
download | jgit-38015e3d36369c7e43916117df7d0f2f8da8344b.tar.gz jgit-38015e3d36369c7e43916117df7d0f2f8da8344b.zip |
GPG: include signer's user ID in the signature
Signing a commit with command line git and gpg 2.2.20 includes the
e-mail part of the key's user ID as a "Signer's User ID" subpacket
on the signature.
Implement this for signing via Bouncy Castle.
Bug: 564386
Change-Id: I68906b895349359596cf3451d65f2840c60df856
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
Diffstat (limited to 'org.eclipse.jgit.gpg.bc')
-rw-r--r-- | org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSigner.java | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSigner.java b/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSigner.java index c6ecdbe6da..ea159c547d 100644 --- a/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSigner.java +++ b/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSigner.java @@ -15,6 +15,7 @@ import java.net.URISyntaxException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; +import java.util.Iterator; import org.bouncycastle.bcpg.ArmoredOutputStream; import org.bouncycastle.bcpg.BCPGOutputStream; @@ -22,6 +23,7 @@ import org.bouncycastle.bcpg.HashAlgorithmTags; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPrivateKey; +import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPSecretKey; import org.bouncycastle.openpgp.PGPSignature; import org.bouncycastle.openpgp.PGPSignatureGenerator; @@ -38,6 +40,7 @@ import org.eclipse.jgit.lib.GpgSignature; import org.eclipse.jgit.lib.GpgSigner; import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.util.StringUtils; /** * GPG Signer using BouncyCastle library @@ -126,17 +129,32 @@ public class BouncyCastleGpgSigner extends GpgSigner { privateKey = secretKey .extractPrivateKey(decryptorBuilder.build(passphrase)); } + PGPPublicKey publicKey = secretKey.getPublicKey(); PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator( new JcaPGPContentSignerBuilder( - secretKey.getPublicKey().getAlgorithm(), + publicKey.getAlgorithm(), HashAlgorithmTags.SHA256).setProvider( BouncyCastleProvider.PROVIDER_NAME)); signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, privateKey); - PGPSignatureSubpacketGenerator subpacketGenerator = new PGPSignatureSubpacketGenerator(); - subpacketGenerator.setIssuerFingerprint(false, - secretKey.getPublicKey()); + PGPSignatureSubpacketGenerator subpackets = new PGPSignatureSubpacketGenerator(); + subpackets.setIssuerFingerprint(false, publicKey); + // Also add the signer's user ID. Note that GPG uses only the e-mail + // address part. + String userId = committer.getEmailAddress(); + Iterator<String> userIds = publicKey.getUserIDs(); + if (userIds.hasNext()) { + String keyUserId = userIds.next(); + if (!StringUtils.isEmptyOrNull(keyUserId) + && (userId == null || !keyUserId.contains(userId))) { + // Not the committer's key? + userId = extractSignerId(keyUserId); + } + } + if (userId != null) { + subpackets.setSignerUserID(false, userId); + } signatureGenerator - .setHashedSubpackets(subpacketGenerator.generate()); + .setHashedSubpackets(subpackets.generate()); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); try (BCPGOutputStream out = new BCPGOutputStream( new ArmoredOutputStream(buffer))) { @@ -149,4 +167,15 @@ public class BouncyCastleGpgSigner extends GpgSigner { throw new JGitInternalException(e.getMessage(), e); } } + + private String extractSignerId(String pgpUserId) { + int from = pgpUserId.indexOf('<'); + if (from >= 0) { + int to = pgpUserId.indexOf('>', from + 1); + if (to > from + 1) { + return pgpUserId.substring(from + 1, to); + } + } + return pgpUserId; + } } |