Skip to content

Commit cfc967f

Browse files
Use SHA-256 for runtime telemetry package checksums (#18846)
Signed-off-by: Israel Blancas <iblancasa@gmail.com> Co-authored-by: jason plumb <75337021+breedx-splk@users.noreply.github.com>
1 parent f13dd94 commit cfc967f

5 files changed

Lines changed: 56 additions & 34 deletions

File tree

instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,9 @@ static void processUrl(Logger logger, URL archiveUrl) {
220220
builder.put(PACKAGE_VERSION, jarDetails.version());
221221
builder.put(PACKAGE_DESCRIPTION, jarDetails.packageDescription());
222222

223-
String packageChecksum = jarDetails.computeSha1();
223+
String packageChecksum = jarDetails.computeSha256();
224224
builder.put(PACKAGE_CHECKSUM, packageChecksum);
225-
builder.put(PACKAGE_CHECKSUM_ALGORITHM, "SHA1");
225+
builder.put(PACKAGE_CHECKSUM_ALGORITHM, "SHA-256");
226226

227227
logger
228228
.logRecordBuilder()

instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarDetails.java

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
import java.io.IOException;
1313
import java.io.InputStream;
14-
import java.math.BigInteger;
1514
import java.net.URL;
1615
import java.security.DigestInputStream;
1716
import java.security.MessageDigest;
@@ -37,17 +36,18 @@ class JarDetails {
3736
static final String JAR_EXTENSION = "jar";
3837
static final String WAR_EXTENSION = "war";
3938
static final String EAR_EXTENSION = "ear";
39+
private static final char[] HEX_DIGITS = "0123456789abcdef".toCharArray();
4040
private static final Map<String, String> EMBEDDED_FORMAT_TO_EXTENSION =
4141
Stream.of(JAR_EXTENSION, WAR_EXTENSION, EAR_EXTENSION)
4242
.collect(
4343
collectingAndThen(
4444
toMap(ext -> ('.' + ext + "!/"), identity()),
4545
Collections::<String, String>unmodifiableMap));
46-
private static final ThreadLocal<MessageDigest> sha1 =
46+
private static final ThreadLocal<MessageDigest> sha256 =
4747
ThreadLocal.withInitial(
4848
() -> {
4949
try {
50-
return MessageDigest.getInstance("SHA1");
50+
return MessageDigest.getInstance("SHA-256");
5151
} catch (NoSuchAlgorithmException e) {
5252
throw new IllegalStateException(e);
5353
}
@@ -56,14 +56,14 @@ class JarDetails {
5656
private final URL url;
5757
@Nullable private final Properties pom;
5858
@Nullable private final Manifest manifest;
59-
private final String sha1Checksum;
59+
private final String sha256Checksum;
6060

6161
private JarDetails(
62-
URL url, @Nullable Properties pom, @Nullable Manifest manifest, String sha1Checksum) {
62+
URL url, @Nullable Properties pom, @Nullable Manifest manifest, String sha256Checksum) {
6363
this.url = url;
6464
this.pom = pom;
6565
this.manifest = manifest;
66-
this.sha1Checksum = sha1Checksum;
66+
this.sha256Checksum = sha256Checksum;
6767
}
6868

6969
static JarDetails forUrl(URL url) throws IOException {
@@ -88,14 +88,14 @@ static JarDetails forUrl(URL url) throws IOException {
8888
url,
8989
getPom(jarFile, jarEntry),
9090
getManifest(jarFile, jarEntry),
91-
computeDigest(jarFile, jarEntry, sha1.get()));
91+
computeDigest(jarFile, jarEntry, sha256.get()));
9292
}
9393
}
9494
}
9595
}
9696
try (JarFile jarFile = new JarFile(UrlPaths.toFile(url))) {
9797
return new JarDetails(
98-
url, getPom(jarFile), getManifest(jarFile), computeDigest(url, sha1.get()));
98+
url, getPom(jarFile), getManifest(jarFile), computeDigest(url, sha256.get()));
9999
}
100100
}
101101

@@ -185,9 +185,9 @@ String packageDescription() {
185185
return name + " by " + vendor;
186186
}
187187

188-
/** Returns the SHA1 hash of this file, e.g. {@code 30d16ec2aef6d8094c5e2dce1d95034ca8b6cb42}. */
189-
String computeSha1() {
190-
return sha1Checksum;
188+
/** Returns the lowercase hex-encoded SHA-256 digest of this file as a 64-character string. */
189+
String computeSha256() {
190+
return sha256Checksum;
191191
}
192192

193193
private static String computeDigest(URL url, MessageDigest md) throws IOException {
@@ -205,12 +205,23 @@ private static String computeDigest(JarFile jarFile, JarEntry jarEntry, MessageD
205205

206206
private static String computeDigest(InputStream inputStream, MessageDigest md)
207207
throws IOException {
208-
md.reset();
209-
DigestInputStream dis = new DigestInputStream(inputStream, md);
210-
byte[] buffer = new byte[8192];
211-
while (dis.read(buffer) != -1) {}
212-
byte[] digest = md.digest();
213-
return String.format(Locale.ROOT, "%040x", new BigInteger(1, digest));
208+
try (DigestInputStream digestInputStream = new DigestInputStream(inputStream, md)) {
209+
byte[] buffer = new byte[8192];
210+
while (digestInputStream.read(buffer) != -1) {}
211+
return toHex(md.digest());
212+
} finally {
213+
md.reset();
214+
}
215+
}
216+
217+
static String toHex(byte[] bytes) {
218+
char[] chars = new char[bytes.length * 2];
219+
for (int i = 0; i < bytes.length; i++) {
220+
int value = bytes[i] & 0xff;
221+
chars[i * 2] = HEX_DIGITS[value >>> 4];
222+
chars[i * 2 + 1] = HEX_DIGITS[value & 0x0f];
223+
}
224+
return new String(chars);
214225
}
215226

216227
@Nullable

instrumentation/runtime-telemetry/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzerInstallerTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ void jarAnalyzerEnabled() {
4646
logRecord ->
4747
assertThat(logRecord.getAttributes())
4848
.containsEntry("package.type", "jar")
49-
.containsEntry("package.checksum_algorithm", "SHA1")
49+
.containsEntry("package.checksum_algorithm", "SHA-256")
5050
.hasEntrySatisfying(
5151
stringKey("package.checksum"),
52-
value -> assertThat(value).matches("[0-9a-f]{40}"))
52+
value -> assertThat(value).matches("[0-9a-f]{64}"))
5353
.hasEntrySatisfying(
5454
stringKey("package.path"), value -> assertThat(value).isNotNull())
5555
.satisfies(

instrumentation/runtime-telemetry/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzerTest.java

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,10 @@ private static Stream<Arguments> processUrlArguments() {
7171
.matches(
7272
"opentelemetry-javaagent-runtime-telemetry-[0-9a-zA-Z-\\.]+\\.jar"))
7373
.containsEntry(PACKAGE_DESCRIPTION, "javaagent by OpenTelemetry")
74-
.containsEntry(PACKAGE_CHECKSUM_ALGORITHM, "SHA1")
74+
.containsEntry(PACKAGE_CHECKSUM_ALGORITHM, "SHA-256")
7575
.hasEntrySatisfying(
76-
PACKAGE_CHECKSUM, checksum -> assertThat(checksum).isNotEmpty()))),
76+
PACKAGE_CHECKSUM,
77+
checksum -> assertThat(checksum).matches("[0-9a-f]{64}")))),
7778
// dummy war
7879
Arguments.of(
7980
archiveUrl(new File(System.getenv("DUMMY_APP_WAR"))),
@@ -83,9 +84,10 @@ private static Stream<Arguments> processUrlArguments() {
8384
.containsEntry(PACKAGE_TYPE, "war")
8485
.containsEntry(PACKAGE_PATH, "app.war")
8586
.containsEntry(PACKAGE_DESCRIPTION, "Dummy App by OpenTelemetry")
86-
.containsEntry(PACKAGE_CHECKSUM_ALGORITHM, "SHA1")
87+
.containsEntry(PACKAGE_CHECKSUM_ALGORITHM, "SHA-256")
8788
.hasEntrySatisfying(
88-
PACKAGE_CHECKSUM, checksum -> assertThat(checksum).isNotEmpty()))),
89+
PACKAGE_CHECKSUM,
90+
checksum -> assertThat(checksum).matches("[0-9a-f]{64}")))),
8991
// io.opentelemetry:opentelemetry-api
9092
Arguments.of(
9193
archiveUrl(Tracer.class),
@@ -99,9 +101,10 @@ private static Stream<Arguments> processUrlArguments() {
99101
assertThat(path)
100102
.matches("opentelemetry-api-[0-9a-zA-Z-\\.]+\\.jar"))
101103
.containsEntry(PACKAGE_DESCRIPTION, "all")
102-
.containsEntry(PACKAGE_CHECKSUM_ALGORITHM, "SHA1")
104+
.containsEntry(PACKAGE_CHECKSUM_ALGORITHM, "SHA-256")
103105
.hasEntrySatisfying(
104-
PACKAGE_CHECKSUM, checksum -> assertThat(checksum).isNotEmpty()))),
106+
PACKAGE_CHECKSUM,
107+
checksum -> assertThat(checksum).matches("[0-9a-f]{64}")))),
105108
// org.springframework:spring-webmvc
106109
Arguments.of(
107110
archiveUrl(HttpRequest.class),
@@ -115,9 +118,10 @@ private static Stream<Arguments> processUrlArguments() {
115118
PACKAGE_PATH,
116119
path -> assertThat(path).matches("spring-web-[0-9a-zA-Z-\\.]+\\.jar"))
117120
.containsEntry(PACKAGE_DESCRIPTION, "org.springframework.web")
118-
.containsEntry(PACKAGE_CHECKSUM_ALGORITHM, "SHA1")
121+
.containsEntry(PACKAGE_CHECKSUM_ALGORITHM, "SHA-256")
119122
.hasEntrySatisfying(
120-
PACKAGE_CHECKSUM, checksum -> assertThat(checksum).isNotEmpty()))),
123+
PACKAGE_CHECKSUM,
124+
checksum -> assertThat(checksum).matches("[0-9a-f]{64}")))),
121125
// com.google.guava:guava
122126
Arguments.of(
123127
archiveUrl(ImmutableMap.class),
@@ -131,9 +135,10 @@ private static Stream<Arguments> processUrlArguments() {
131135
.containsEntry(PACKAGE_NAME, "com.google.guava:guava")
132136
.hasEntrySatisfying(
133137
PACKAGE_VERSION, version -> assertThat(version).isNotEmpty())
134-
.containsEntry(PACKAGE_CHECKSUM_ALGORITHM, "SHA1")
138+
.containsEntry(PACKAGE_CHECKSUM_ALGORITHM, "SHA-256")
135139
.hasEntrySatisfying(
136-
PACKAGE_CHECKSUM, checksum -> assertThat(checksum).isNotEmpty()))));
140+
PACKAGE_CHECKSUM,
141+
checksum -> assertThat(checksum).matches("[0-9a-f]{64}")))));
137142
}
138143

139144
private static URL archiveUrl(File file) {

instrumentation/runtime-telemetry/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarDetailsTest.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package io.opentelemetry.javaagent.instrumentation.runtimetelemetry;
77

8+
import static java.nio.charset.StandardCharsets.UTF_8;
89
import static org.assertj.core.api.Assertions.assertThat;
910

1011
import java.io.ByteArrayOutputStream;
@@ -21,6 +22,11 @@
2122

2223
class JarDetailsTest {
2324

25+
@Test
26+
void toHex_encodesBytes() {
27+
assertThat(JarDetails.toHex("hello".getBytes(UTF_8))).isEqualTo("68656c6c6f");
28+
}
29+
2430
@Test
2531
void forUrl_handlesPathWithSpaces(@TempDir Path tempDir) throws IOException {
2632
Path dirWithSpaces = Files.createDirectories(tempDir.resolve("dir with spaces"));
@@ -33,7 +39,7 @@ void forUrl_handlesPathWithSpaces(@TempDir Path tempDir) throws IOException {
3339
JarDetails details = JarDetails.forUrl(url);
3440

3541
assertThat(details.packageDescription()).isEqualTo("Test Title by Test Vendor");
36-
assertThat(details.computeSha1()).isNotEmpty();
42+
assertThat(details.computeSha256()).matches("[0-9a-f]{64}");
3743
}
3844

3945
@Test
@@ -59,7 +65,7 @@ void forUrl_handlesEmbeddedJar(@TempDir Path tempDir) throws IOException {
5965
JarDetails details = JarDetails.forUrl(url);
6066

6167
assertThat(details.packageDescription()).isEqualTo("Inner Title by Inner Vendor");
62-
assertThat(details.computeSha1()).isNotEmpty();
68+
assertThat(details.computeSha256()).matches("[0-9a-f]{64}");
6369
}
6470

6571
@Test
@@ -86,7 +92,7 @@ void forUrl_handlesEmbeddedJarWithSpaces(@TempDir Path tempDir) throws IOExcepti
8692
JarDetails details = JarDetails.forUrl(url);
8793

8894
assertThat(details.packageDescription()).isEqualTo("Inner Title by Inner Vendor");
89-
assertThat(details.computeSha1()).isNotEmpty();
95+
assertThat(details.computeSha256()).matches("[0-9a-f]{64}");
9096
}
9197

9298
private static Manifest manifest(String title, String vendor) {

0 commit comments

Comments
 (0)