Skip to content

Commit

Permalink
GPG: use BC PGP secret key parsing out of the box
Browse files Browse the repository at this point in the history
Remove the custom S-expression parsing; BC has gotten many
improvements in 1.79 regarding PGP ed25519 keys, AES/OCB
encryption, and generally parsing key files. It now can do
all we need.

Change-Id: I392443e040cce150a9575d18795a7cb8195a3515
Signed-off-by: Thomas Wolf <[email protected]>
  • Loading branch information
tomaswolf committed Nov 6, 2024
1 parent a3dbf3a commit b2accb0
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 1,585 deletions.
11 changes: 6 additions & 5 deletions org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-17
Require-Bundle: org.hamcrest.core;bundle-version="[1.3.0,2.0.0)"
Import-Package: org.bouncycastle.jce.provider;version="[1.65.0,2.0.0)",
org.bouncycastle.openpgp;version="[1.65.0,2.0.0)",
org.bouncycastle.openpgp.operator;version="[1.65.0,2.0.0)",
org.bouncycastle.openpgp.operator.jcajce;version="[1.65.0,2.0.0)",
org.bouncycastle.util.encoders;version="[1.65.0,2.0.0)",
Import-Package: org.bouncycastle.asn1.cryptlib;version="[1.79.0,2.0.0)",
org.bouncycastle.jce.provider;version="[1.79.0,2.0.0)",
org.bouncycastle.openpgp;version="[1.79.0,2.0.0)",
org.bouncycastle.openpgp.operator;version="[1.79.0,2.0.0)",
org.bouncycastle.openpgp.operator.jcajce;version="[1.79.0,2.0.0)",
org.bouncycastle.util.encoders;version="[1.79.0,2.0.0)",
org.eclipse.jgit.gpg.bc.internal;version="[7.1.0,7.2.0)",
org.eclipse.jgit.gpg.bc.internal.keys;version="[7.1.0,7.2.0)",
org.eclipse.jgit.util.sha1;version="[7.1.0,7.2.0)",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021 Thomas Wolf <[email protected]> and others
* Copyright (C) 2021, 2024 Thomas Wolf <[email protected]> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
Expand All @@ -9,19 +9,14 @@
*/
package org.eclipse.jgit.gpg.bc.internal.keys;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.Security;
import java.util.Iterator;

import javax.crypto.Cipher;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
Expand Down Expand Up @@ -49,39 +44,15 @@ public static void ensureBC() {
}
}

private static volatile Boolean haveOCB;

private static boolean ocbAvailable() {
Boolean haveIt = haveOCB;
if (haveIt != null) {
return haveIt.booleanValue();
}
try {
Cipher c = Cipher.getInstance("AES/OCB/NoPadding"); //$NON-NLS-1$
if (c == null) {
haveOCB = Boolean.FALSE;
return false;
}
} catch (NoClassDefFoundError | Exception e) {
haveOCB = Boolean.FALSE;
return false;
}
haveOCB = Boolean.TRUE;
return true;
}

private static class TestData {

final String name;

final boolean encrypted;

final boolean keyValue;

TestData(String name, boolean encrypted, boolean keyValue) {
TestData(String name, boolean encrypted) {
this.name = name;
this.encrypted = encrypted;
this.keyValue = keyValue;
}

@Override
Expand All @@ -93,19 +64,12 @@ public String toString() {
@Parameters(name = "{0}")
public static TestData[] initTestData() {
return new TestData[] {
new TestData("AFDA8EA10E185ACF8C0D0F8885A0EF61A72ECB11", false, false),
new TestData("2FB05DBB70FC07CB84C13431F640CA6CEA1DBF8A", false, true),
new TestData("66CCECEC2AB46A9735B10FEC54EDF9FD0F77BAF9", true, true),
new TestData("F727FAB884DA3BD402B6E0F5472E108D21033124", true, true),
new TestData("62D43D7F117F7A5E4998ECB6617EE9942D069C14", true, true),
new TestData("faked", false, true) };
}

private static byte[] readTestKey(String filename) throws Exception {
try (InputStream in = new BufferedInputStream(
SecretKeysTest.class.getResourceAsStream(filename))) {
return SecretKeys.keyFromNameValueFormat(in);
}
new TestData("AFDA8EA10E185ACF8C0D0F8885A0EF61A72ECB11", false),
new TestData("2FB05DBB70FC07CB84C13431F640CA6CEA1DBF8A", false),
new TestData("66CCECEC2AB46A9735B10FEC54EDF9FD0F77BAF9", true),
new TestData("F727FAB884DA3BD402B6E0F5472E108D21033124", true),
new TestData("62D43D7F117F7A5E4998ECB6617EE9942D069C14", true),
new TestData("faked", false) };
}

private static PGPPublicKey readAsc(InputStream in)
Expand All @@ -131,11 +95,6 @@ private static PGPPublicKey readAsc(InputStream in)

@Test
public void testKeyRead() throws Exception {
if (data.keyValue) {
byte[] bytes = readTestKey(data.name + ".key");
assertEquals('(', bytes[0]);
assertEquals(')', bytes[bytes.length - 1]);
}
try (InputStream pubIn = this.getClass()
.getResourceAsStream(data.name + ".asc")) {
if (pubIn != null) {
Expand All @@ -151,11 +110,6 @@ public void testKeyRead() throws Exception {
: null,
publicKey);
assertNotNull(secretKey);
} catch (PGPException e) {
// Currently we may not be able to load OCB-encrypted keys.
assertTrue(e.toString(), e.getMessage().contains("OCB"));
assertTrue(data.encrypted);
assertFalse(ocbAvailable());
}
}
}
Expand Down
37 changes: 17 additions & 20 deletions org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,23 @@ Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: OSGI-INF/l10n/gpg_bc
Bundle-Version: 7.1.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-17
Import-Package: org.bouncycastle.asn1;version="[1.69.0,2.0.0)",
org.bouncycastle.asn1.x9;version="[1.69.0,2.0.0)",
org.bouncycastle.bcpg;version="[1.69.0,2.0.0)",
org.bouncycastle.bcpg.sig;version="[1.69.0,2.0.0)",
org.bouncycastle.crypto.ec;version="[1.69.0,2.0.0)",
org.bouncycastle.gpg;version="[1.69.0,2.0.0)",
org.bouncycastle.gpg.keybox;version="[1.69.0,2.0.0)",
org.bouncycastle.gpg.keybox.jcajce;version="[1.69.0,2.0.0)",
org.bouncycastle.jcajce.interfaces;version="[1.69.0,2.0.0)",
org.bouncycastle.jcajce.util;version="[1.69.0,2.0.0)",
org.bouncycastle.jce.provider;version="[1.69.0,2.0.0)",
org.bouncycastle.math.ec;version="[1.69.0,2.0.0)",
org.bouncycastle.math.field;version="[1.69.0,2.0.0)",
org.bouncycastle.openpgp;version="[1.69.0,2.0.0)",
org.bouncycastle.openpgp.jcajce;version="[1.69.0,2.0.0)",
org.bouncycastle.openpgp.operator;version="[1.69.0,2.0.0)",
org.bouncycastle.openpgp.operator.jcajce;version="[1.69.0,2.0.0)",
org.bouncycastle.util;version="[1.69.0,2.0.0)",
org.bouncycastle.util.encoders;version="[1.69.0,2.0.0)",
org.bouncycastle.util.io;version="[1.69.0,2.0.0)",
Import-Package: org.bouncycastle.asn1;version="[1.79.0,2.0.0)",
org.bouncycastle.asn1.x9;version="[1.79.0,2.0.0)",
org.bouncycastle.bcpg;version="[1.79.0,2.0.0)",
org.bouncycastle.bcpg.sig;version="[1.79.0,2.0.0)",
org.bouncycastle.crypto.ec;version="[1.79.0,2.0.0)",
org.bouncycastle.gpg;version="[1.79.0,2.0.0)",
org.bouncycastle.gpg.keybox;version="[1.79.0,2.0.0)",
org.bouncycastle.gpg.keybox.jcajce;version="[1.79.0,2.0.0)",
org.bouncycastle.jcajce.interfaces;version="[1.79.0,2.0.0)",
org.bouncycastle.jcajce.util;version="[1.79.0,2.0.0)",
org.bouncycastle.math.ec;version="[1.79.0,2.0.0)",
org.bouncycastle.math.field;version="[1.79.0,2.0.0)",
org.bouncycastle.openpgp;version="[1.79.0,2.0.0)",
org.bouncycastle.openpgp.jcajce;version="[1.79.0,2.0.0)",
org.bouncycastle.openpgp.operator;version="[1.79.0,2.0.0)",
org.bouncycastle.openpgp.operator.jcajce;version="[1.79.0,2.0.0)",
org.bouncycastle.util.encoders;version="[1.79.0,2.0.0)",
org.slf4j;version="[1.7.0,3.0.0)"
Export-Package: org.eclipse.jgit.gpg.bc.internal;version="7.1.0";x-friends:="org.eclipse.jgit.gpg.bc.test",
org.eclipse.jgit.gpg.bc.internal.keys;version="7.1.0";x-friends:="org.eclipse.jgit.gpg.bc.test"
26 changes: 0 additions & 26 deletions org.eclipse.jgit.gpg.bc/about.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,32 +58,6 @@
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.</p>

<hr>
<p><b>org.eclipse.jgit.gpg.bc.internal.keys.SExprParser - MIT</b></p>

<p>Copyright (c) 2000-2021 The Legion of the Bouncy Castle Inc.
(<a href="https://www.bouncycastle.org">https://www.bouncycastle.org</a>)</p>

<p>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
</p>
<p>
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
</p>
<p>
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
</p>

</body>

</html>
Original file line number Diff line number Diff line change
@@ -1,30 +1,20 @@
corrupt25519Key=Ed25519/Curve25519 public key has wrong length: {0}
credentialPassphrase=Passphrase
cryptCipherError=Cannot create cipher to decrypt: {0}
cryptWrongDecryptedLength=Decrypted key has wrong length; expected {0} bytes, got only {1} bytes
gpgFailedToParseSecretKey=Failed to parse secret key file {0}. Is the entered passphrase correct?
gpgNoCredentialsProvider=missing credentials provider
gpgNoKeygrip=Cannot find key {0}: cannot determine key grip
gpgNoKeyring=neither pubring.kbx nor secring.gpg files found
gpgNoKeyInLegacySecring=no matching secret key found in legacy secring.gpg for key or user id: {0}
gpgNoPublicKeyFound=Unable to find a public-key with key or user id: {0}
gpgNoSecretKeyForPublicKey=unable to find associated secret key for public key: {0}
gpgNoSuchAlgorithm=Cannot decrypt encrypted secret key: encryption algorithm {0} is not available
gpgNotASigningKey=Secret key ({0}) is not suitable for signing
gpgKeyInfo=GPG Key (fingerprint {0})
gpgSigningCancelled=Signing was cancelled
keyAlgorithmMismatch=Secret key has a different algorithm than the public key
keyMismatch=Secret key does not match public key; public key is {0} {1} while secret key is for {2} {3}
logWarnGnuPGHome=Cannot access GPG home directory given by environment variable GNUPGHOME={}
logWarnGpgHomeProperty=Cannot access GPG home directory given by Java system property jgit.gpg.home={}
nonSignatureError=Signature does not decode into a signature object
secretKeyTooShort=Secret key file corrupt; only {0} bytes read
sexprHexNotClosed=Hex number in s-expression not closed
sexprHexOdd=Hex number in s-expression has an odd number of digits
sexprStringInvalidEscape=Invalid escape {0} in s-expression
sexprStringInvalidEscapeAtEnd=Invalid s-expression: quoted string ends with escape character
sexprStringInvalidHexEscape=Invalid hex escape in s-expression
sexprStringInvalidOctalEscape=Invalid octal escape in s-expression
sexprStringNotClosed=String in s-expression not closed
sexprUnhandled=Unhandled token {0} in s-expression
signatureInconsistent=Inconsistent signature; key ID {0} does not match issuer fingerprint {1}
signatureKeyLookupError=Error occurred while looking for public key
signatureNoKeyInfo=No way to determine a public key from the signature
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018, 2021 Salesforce and others
* Copyright (C) 2018, 2024 Salesforce and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
Expand Down Expand Up @@ -30,31 +30,21 @@ public static BCText get() {
// @formatter:off
/***/ public String corrupt25519Key;
/***/ public String credentialPassphrase;
/***/ public String cryptCipherError;
/***/ public String cryptWrongDecryptedLength;
/***/ public String gpgFailedToParseSecretKey;
/***/ public String gpgNoCredentialsProvider;
/***/ public String gpgNoKeygrip;
/***/ public String gpgNoKeyring;
/***/ public String gpgNoKeyInLegacySecring;
/***/ public String gpgNoPublicKeyFound;
/***/ public String gpgNoSecretKeyForPublicKey;
/***/ public String gpgNoSuchAlgorithm;
/***/ public String gpgNotASigningKey;
/***/ public String gpgKeyInfo;
/***/ public String gpgSigningCancelled;
/***/ public String keyAlgorithmMismatch;
/***/ public String keyMismatch;
/***/ public String logWarnGnuPGHome;
/***/ public String logWarnGpgHomeProperty;
/***/ public String nonSignatureError;
/***/ public String secretKeyTooShort;
/***/ public String sexprHexNotClosed;
/***/ public String sexprHexOdd;
/***/ public String sexprStringInvalidEscape;
/***/ public String sexprStringInvalidEscapeAtEnd;
/***/ public String sexprStringInvalidHexEscape;
/***/ public String sexprStringInvalidOctalEscape;
/***/ public String sexprStringNotClosed;
/***/ public String sexprUnhandled;
/***/ public String signatureInconsistent;
/***/ public String signatureKeyLookupError;
/***/ public String signatureNoKeyInfo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ public GpgSignature sign(Repository repository, GpgConfig config,
PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(
new JcaPGPContentSignerBuilder(
publicKey.getAlgorithm(),
HashAlgorithmTags.SHA256));
HashAlgorithmTags.SHA256),
publicKey);
signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, privateKey);
PGPSignatureSubpacketGenerator subpackets = new PGPSignatureSubpacketGenerator();
subpackets.setIssuerFingerprint(false, publicKey);
Expand Down
Loading

0 comments on commit b2accb0

Please sign in to comment.