Skip to content

Commit abbb427

Browse files
committed
Add public key header/footer (#30877)
A previous commit added the public key used for signing artifacts to the plugin CLI. This commit is an iteration on that to add the header and footer to the key so that it is clear what the key is. Instead, we strip the header/footer on read. With this change we simplify our test where keys already in this format are generated and we had to strip on the test side.
1 parent b006f3b commit abbb427

File tree

3 files changed

+23
-11
lines changed

3 files changed

+23
-11
lines changed

distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/InstallPluginCommand.java

+17-5
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.elasticsearch.env.Environment;
4848

4949
import java.io.BufferedReader;
50+
import java.io.ByteArrayInputStream;
5051
import java.io.IOException;
5152
import java.io.InputStream;
5253
import java.io.InputStreamReader;
@@ -71,7 +72,6 @@
7172
import java.nio.file.attribute.PosixFilePermissions;
7273
import java.security.MessageDigest;
7374
import java.security.NoSuchAlgorithmException;
74-
import java.security.Security;
7575
import java.util.ArrayList;
7676
import java.util.Arrays;
7777
import java.util.Base64;
@@ -543,8 +543,8 @@ void verifySignature(final Path zip, final String urlString) throws IOException,
543543
InputStream fin = pluginZipInputStream(zip);
544544
// sin is a URL stream to the signature corresponding to the downloaded plugin zip
545545
InputStream sin = urlOpenStream(ascUrl);
546-
// pin is a decoded base64 stream over the embedded public key in RFC2045 format
547-
InputStream pin = Base64.getMimeDecoder().wrap(getPublicKey())) {
546+
// pin is a input stream to the public key in ASCII-Armor format (RFC4880); the Armor data is in RFC2045 format
547+
InputStream pin = getPublicKey()) {
548548
final JcaPGPObjectFactory factory = new JcaPGPObjectFactory(PGPUtil.getDecoderStream(sin));
549549
final PGPSignature signature = ((PGPSignatureList) factory.nextObject()).get(0);
550550

@@ -555,7 +555,19 @@ void verifySignature(final Path zip, final String urlString) throws IOException,
555555
}
556556

557557
// compute the signature of the downloaded plugin zip
558-
final PGPPublicKeyRingCollection collection = new PGPPublicKeyRingCollection(pin, new JcaKeyFingerprintCalculator());
558+
final List<String> lines =
559+
new BufferedReader(new InputStreamReader(pin, StandardCharsets.UTF_8)).lines().collect(Collectors.toList());
560+
// skip armor headers and possible blank line
561+
int index = 1;
562+
for (; index < lines.size(); index++) {
563+
if (lines.get(index).matches(".*: .*") == false && lines.get(index).matches("\\s*") == false) {
564+
break;
565+
}
566+
}
567+
final byte[] armoredData =
568+
lines.subList(index, lines.size() - 1).stream().collect(Collectors.joining("\n")).getBytes(StandardCharsets.UTF_8);
569+
final InputStream ain = Base64.getMimeDecoder().wrap(new ByteArrayInputStream(armoredData));
570+
final PGPPublicKeyRingCollection collection = new PGPPublicKeyRingCollection(ain, new JcaKeyFingerprintCalculator());
559571
final PGPPublicKey key = collection.getPublicKey(signature.getKeyID());
560572
signature.init(new JcaPGPContentVerifierBuilderProvider().setProvider(new BouncyCastleProvider()), key);
561573
final byte[] buffer = new byte[1024];
@@ -597,7 +609,7 @@ String getPublicKeyId() {
597609
* @return an input stream to the public key
598610
*/
599611
InputStream getPublicKey() {
600-
return InstallPluginCommand.class.getResourceAsStream("/public_key");
612+
return InstallPluginCommand.class.getResourceAsStream("/public_key.asc");
601613
}
602614

603615
/**

distribution/tools/plugin-cli/src/main/resources/public_key renamed to distribution/tools/plugin-cli/src/main/resources/public_key.asc

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
-----BEGIN PGP PUBLIC KEY BLOCK-----
2+
Version: SKS 1.1.6
3+
Comment: Hostname: pgp.mit.edu
4+
15
mQENBFI3HsoBCADXDtbNJnxbPqB1vDNtCsqhe49vFYsZN9IOZsZXgp7aHjh6CJBDA+bGFOwy
26
hbd7at35jQjWAw1O3cfYsKAmFy+Ar3LHCMkV3oZspJACTIgCrwnkic/9CUliQe324qvObU2Q
37
RtP4Fl0zWcfb/S8UYzWXWIFuJqMvE9MaRY1bwUBvzoqavLGZj3SF1SPO+TB5QrHkrQHBsmX+
@@ -22,3 +26,4 @@ EyUJ8SKsaHh4jV9wp9KmC8C+9CwMukL7vM5w8cgvJoAwsp3Fn59AxWthN3XJYcnMfStkIuWg
2226
R7U2r+a210W6vnUxU4oN0PmMcursYPyeV0NX/KQeUeNMwGTFB6QHS/anRaGQewijkrYYoTNt
2327
fllxIu9XYmiBERQ/qPDlGRlOgVTd9xUfHFkzB52c70E=
2428
=92oX
29+
-----END PGP PUBLIC KEY BLOCK-----

distribution/tools/plugin-cli/src/test/java/org/elasticsearch/plugins/InstallPluginCommandTests.java

+1-6
Original file line numberDiff line numberDiff line change
@@ -893,12 +893,7 @@ InputStream getPublicKey() {
893893
final ArmoredOutputStream armored = new ArmoredOutputStream(output);
894894
secretKey.getPublicKey().encode(armored);
895895
armored.close();
896-
final String publicKey = new String(output.toByteArray(), "UTF-8");
897-
int start = publicKey.indexOf("\n", 1 + publicKey.indexOf("\n"));
898-
int end = publicKey.lastIndexOf("\n", publicKey.lastIndexOf("\n") - 1);
899-
// strip the header (first two lines) and footer (last line)
900-
final String substring = publicKey.substring(1 + start, end);
901-
return new ByteArrayInputStream(substring.getBytes("UTF-8"));
896+
return new ByteArrayInputStream(output.toByteArray());
902897
} catch (final IOException e) {
903898
throw new AssertionError(e);
904899
}

0 commit comments

Comments
 (0)