GPG: check secring.gpg for keys if pubring.kbx is empty

If no OpenPGP key is found in pubring.kbx, try the legacy secring.gpg.
This appears to be consistent with GPG[1].

[1] https://lists.gnupg.org/pipermail/gnupg-users/2015-December/054881.html

Bug: 549439
Change-Id: I1557fd9b1f555a9b521fcd57cd3caccbdbacbeda
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
This commit is contained in:
Thomas Wolf 2019-07-20 18:45:56 +02:00 committed by Matthias Sohn
parent 3cea3676c7
commit db0eb9f8ae
1 changed files with 65 additions and 23 deletions

View File

@ -97,6 +97,13 @@
*/ */
class BouncyCastleGpgKeyLocator { class BouncyCastleGpgKeyLocator {
/** Thrown if a keybox file exists but doesn't contain an OpenPGP key. */
private static class NoOpenPgpKeyException extends Exception {
private static final long serialVersionUID = 1L;
}
private static final Logger log = LoggerFactory private static final Logger log = LoggerFactory
.getLogger(BouncyCastleGpgKeyLocator.class); .getLogger(BouncyCastleGpgKeyLocator.class);
@ -215,13 +222,17 @@ private PGPPublicKey findPublicKeyByUserId(KeyBlob keyBlob)
* in case of problems reading the file * in case of problems reading the file
* @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException
* @throws NoSuchProviderException * @throws NoSuchProviderException
* @throws NoOpenPgpKeyException
* if the file does not contain any OpenPGP key
*/ */
private PGPPublicKey findPublicKeyInKeyBox(Path keyboxFile) private PGPPublicKey findPublicKeyInKeyBox(Path keyboxFile)
throws IOException, NoSuchAlgorithmException, throws IOException, NoSuchAlgorithmException,
NoSuchProviderException { NoSuchProviderException, NoOpenPgpKeyException {
KeyBox keyBox = readKeyBoxFile(keyboxFile); KeyBox keyBox = readKeyBoxFile(keyboxFile);
boolean hasOpenPgpKey = false;
for (KeyBlob keyBlob : keyBox.getKeyBlobs()) { for (KeyBlob keyBlob : keyBox.getKeyBlobs()) {
if (keyBlob.getType() == BlobType.OPEN_PGP_BLOB) { if (keyBlob.getType() == BlobType.OPEN_PGP_BLOB) {
hasOpenPgpKey = true;
PGPPublicKey key = findPublicKeyByKeyId(keyBlob); PGPPublicKey key = findPublicKeyByKeyId(keyBlob);
if (key != null) { if (key != null) {
return key; return key;
@ -232,6 +243,9 @@ private PGPPublicKey findPublicKeyInKeyBox(Path keyboxFile)
} }
} }
} }
if (!hasOpenPgpKey) {
throw new NoOpenPgpKeyException();
}
return null; return null;
} }
@ -253,36 +267,60 @@ private PGPPublicKey findPublicKeyInKeyBox(Path keyboxFile)
public BouncyCastleGpgKey findSecretKey() throws IOException, public BouncyCastleGpgKey findSecretKey() throws IOException,
NoSuchAlgorithmException, NoSuchProviderException, PGPException, NoSuchAlgorithmException, NoSuchProviderException, PGPException,
CanceledException, UnsupportedCredentialItem, URISyntaxException { CanceledException, UnsupportedCredentialItem, URISyntaxException {
BouncyCastleGpgKey key;
if (exists(USER_KEYBOX_PATH)) { if (exists(USER_KEYBOX_PATH)) {
PGPPublicKey publicKey = // try {
findPublicKeyInKeyBox(USER_KEYBOX_PATH); key = loadKeyFromKeybox(USER_KEYBOX_PATH);
if (key != null) {
if (publicKey != null) { return key;
return findSecretKeyForKeyBoxPublicKey(publicKey, }
USER_KEYBOX_PATH); throw new PGPException(MessageFormat.format(
} JGitText.get().gpgNoPublicKeyFound, signingKey));
} catch (NoOpenPgpKeyException e) {
throw new PGPException(MessageFormat // Ignore and try the secring.gpg, if it exists.
.format(JGitText.get().gpgNoPublicKeyFound, signingKey)); if (log.isDebugEnabled()) {
} else if (exists(USER_PGP_LEGACY_SECRING_FILE)) { log.debug("{} does not contain any OpenPGP keys", //$NON-NLS-1$
PGPSecretKey secretKey = findSecretKeyInLegacySecring(signingKey, USER_KEYBOX_PATH);
USER_PGP_LEGACY_SECRING_FILE);
if (secretKey != null) {
if (!secretKey.isSigningKey()) {
throw new PGPException(MessageFormat.format(
JGitText.get().gpgNotASigningKey, signingKey));
} }
return new BouncyCastleGpgKey(secretKey, USER_PGP_LEGACY_SECRING_FILE);
} }
}
if (exists(USER_PGP_LEGACY_SECRING_FILE)) {
key = loadKeyFromSecring(USER_PGP_LEGACY_SECRING_FILE);
if (key != null) {
return key;
}
throw new PGPException(MessageFormat.format( throw new PGPException(MessageFormat.format(
JGitText.get().gpgNoKeyInLegacySecring, signingKey)); JGitText.get().gpgNoKeyInLegacySecring, signingKey));
} }
throw new PGPException(JGitText.get().gpgNoKeyring); throw new PGPException(JGitText.get().gpgNoKeyring);
} }
private BouncyCastleGpgKey loadKeyFromKeybox(Path keybox)
throws NoOpenPgpKeyException, NoSuchAlgorithmException,
NoSuchProviderException, IOException, CanceledException,
UnsupportedCredentialItem, PGPException, URISyntaxException {
PGPPublicKey publicKey = findPublicKeyInKeyBox(keybox);
if (publicKey != null) {
return findSecretKeyForKeyBoxPublicKey(publicKey, keybox);
}
return null;
}
private BouncyCastleGpgKey loadKeyFromSecring(Path secring)
throws IOException, PGPException {
PGPSecretKey secretKey = findSecretKeyInLegacySecring(signingKey,
secring);
if (secretKey != null) {
if (!secretKey.isSigningKey()) {
throw new PGPException(MessageFormat
.format(JGitText.get().gpgNotASigningKey, signingKey));
}
return new BouncyCastleGpgKey(secretKey, secring);
}
return null;
}
private BouncyCastleGpgKey findSecretKeyForKeyBoxPublicKey( private BouncyCastleGpgKey findSecretKeyForKeyBoxPublicKey(
PGPPublicKey publicKey, Path userKeyboxPath) PGPPublicKey publicKey, Path userKeyboxPath)
throws PGPException, CanceledException, UnsupportedCredentialItem, throws PGPException, CanceledException, UnsupportedCredentialItem,
@ -385,7 +423,11 @@ private PGPPublicKey getFirstPublicKey(KeyBlob keyBlob) throws IOException {
} }
private KeyBox readKeyBoxFile(Path keyboxFile) throws IOException, private KeyBox readKeyBoxFile(Path keyboxFile) throws IOException,
NoSuchAlgorithmException, NoSuchProviderException { NoSuchAlgorithmException, NoSuchProviderException,
NoOpenPgpKeyException {
if (keyboxFile.toFile().length() == 0) {
throw new NoOpenPgpKeyException();
}
KeyBox keyBox; KeyBox keyBox;
try (InputStream in = new BufferedInputStream( try (InputStream in = new BufferedInputStream(
newInputStream(keyboxFile))) { newInputStream(keyboxFile))) {