Skip to content

Commit a54d7c5

Browse files
authored
Merge pull request #978 from sigstore/reader-writer
Add RFC3161 timestamps to bundle reader and writer
2 parents 55eb097 + 9dc6859 commit a54d7c5

File tree

5 files changed

+77
-2
lines changed

5 files changed

+77
-2
lines changed

sigstore-java/src/main/java/dev/sigstore/bundle/Bundle.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ interface Signature {
185185
@Immutable
186186
public interface Timestamp {
187187

188-
/** Raw bytes of an rfc31616 timestamp */
188+
/** Raw bytes of an rfc3161 timestamp */
189189
byte[] getRfc3161Timestamp();
190190
}
191191

sigstore-java/src/main/java/dev/sigstore/bundle/BundleReader.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,9 @@ static Bundle readBundle(Reader jsonReader) throws BundleParseException {
177177
.getTimestampVerificationData()
178178
.getRfc3161TimestampsList()) {
179179
bundleBuilder.addTimestamps(
180-
ImmutableTimestamp.builder().rfc3161Timestamp(timestamp.toByteArray()).build());
180+
ImmutableTimestamp.builder()
181+
.rfc3161Timestamp(timestamp.getSignedTimestamp().toByteArray())
182+
.build());
181183
}
182184
}
183185

sigstore-java/src/main/java/dev/sigstore/bundle/BundleWriter.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020
import com.google.protobuf.InvalidProtocolBufferException;
2121
import com.google.protobuf.util.JsonFormat;
2222
import dev.sigstore.proto.ProtoMutators;
23+
import dev.sigstore.proto.bundle.v1.TimestampVerificationData;
2324
import dev.sigstore.proto.bundle.v1.VerificationMaterial;
2425
import dev.sigstore.proto.common.v1.HashOutput;
2526
import dev.sigstore.proto.common.v1.LogId;
2627
import dev.sigstore.proto.common.v1.MessageSignature;
28+
import dev.sigstore.proto.common.v1.RFC3161SignedTimestamp;
2729
import dev.sigstore.proto.common.v1.X509Certificate;
2830
import dev.sigstore.proto.rekor.v1.Checkpoint;
2931
import dev.sigstore.proto.rekor.v1.InclusionPromise;
@@ -34,6 +36,7 @@
3436
import java.security.cert.CertificateEncodingException;
3537
import java.util.Base64;
3638
import java.util.List;
39+
import java.util.Optional;
3740
import java.util.stream.Collectors;
3841

3942
class BundleWriter {
@@ -110,6 +113,8 @@ private static VerificationMaterial.Builder buildVerificationMaterial(Bundle bun
110113
"Exactly 1 rekor entry must be present in the signing result");
111114
}
112115
builder.addTlogEntries(buildTlogEntries(bundle.getEntries().get(0)));
116+
buildTimestampVerificationData(bundle.getTimestamps())
117+
.ifPresent(data -> builder.setTimestampVerificationData(data));
113118
return builder;
114119
}
115120

@@ -148,4 +153,23 @@ private static void addInclusionProof(
148153
.collect(Collectors.toList()))
149154
.setCheckpoint(Checkpoint.newBuilder().setEnvelope(inclusionProof.getCheckpoint())));
150155
}
156+
157+
private static Optional<TimestampVerificationData> buildTimestampVerificationData(
158+
List<Bundle.Timestamp> bundleTimestamps) {
159+
if (bundleTimestamps == null || bundleTimestamps.isEmpty()) {
160+
return Optional.empty();
161+
}
162+
TimestampVerificationData.Builder tsvBuilder = TimestampVerificationData.newBuilder();
163+
for (Bundle.Timestamp ts : bundleTimestamps) {
164+
byte[] tsBytes = ts.getRfc3161Timestamp();
165+
if (tsBytes != null && tsBytes.length > 0) {
166+
tsvBuilder.addRfc3161Timestamps(
167+
RFC3161SignedTimestamp.newBuilder().setSignedTimestamp(ByteString.copyFrom(tsBytes)));
168+
}
169+
}
170+
if (tsvBuilder.getRfc3161TimestampsCount() > 0) {
171+
return Optional.of(tsvBuilder.build());
172+
}
173+
return Optional.empty();
174+
}
151175
}

sigstore-java/src/test/java/dev/sigstore/bundle/BundleReaderTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ public void readDSSEBundle() throws Exception {
8787
Assertions.assertEquals("https://slsa.dev/provenance/v1", intotoPayload.getPredicateType());
8888
}
8989

90+
@Test
91+
public void readBundle_timestamp() throws Exception {
92+
readBundle("dev/sigstore/samples/bundles/bundle-with-timestamp.sigstore");
93+
}
94+
9095
private Bundle readBundle(String resourcePath) throws Exception {
9196
try (var reader =
9297
new InputStreamReader(
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json",
3+
"verificationMaterial": {
4+
"tlogEntries": [{
5+
"logIndex": "42526129",
6+
"logId": {
7+
"keyId": "0y8wo8MtY5wrdiIFohx7sHeI5oKDpK5vQhGHI6G+pJY="
8+
},
9+
"kindVersion": {
10+
"kind": "hashedrekord",
11+
"version": "0.0.1"
12+
},
13+
"integratedTime": "1747928754",
14+
"inclusionPromise": {
15+
"signedEntryTimestamp": "MEUCIQDb6hFD6jFyxQkhaTwmhZff4OEsCRGzrJDUzpZegs3jawIgb3zIyIG6Jl668RiBWl1ruYJe+1zmL2eDItz/8B6xpN0="
16+
},
17+
"inclusionProof": {
18+
"logIndex": "10843717",
19+
"rootHash": "RHR6sLAcLFR3TSZvk7xjQNhhJcvIJ9vdGUaLzI2lPnQ=",
20+
"treeSize": "10843718",
21+
"hashes": ["7detk7zciZ8J25BEY8vnk3Q++C939iksS9riXXDjLgA=", "aAG4ljdHqt6d4fSfWKCEc1gZ6KbrzL+5/LfeJDNDPS0=", "IfARZxUnm+0Ca2AZPbdVK6gcrWRTrC1gyH5j4immJbs=", "nJ7X9be7ongRfyJWHcM5SkDHab0Z7pIOAcbu39U6S7Q=", "vFPYRnY3euO/rJBLyB2FSQ6SGWhUlBKxlWiEa+6Zob8=", "1bnzlpz1mUbCBkGSgZWTHMRvywOoCYdVf8S+fZPCnKs=", "rX5Ef4SVBizgYyu1+QRR4GTPYJwreTrY2gRNd3elTmE=", "bI8RkKJpochUYXwnNqOOUvrkcJuRhIbnPDaVcl3Ej1c=", "iy7T8tqDDvtO+yXkGSlT0aWzNoZ6ExItEs+EOgI4kC0=", "ilFXtFIHdJH0+r+CQ/dG37NJepm0LsZqJrAd3MGR5uA=", "3itMWeZPQXMyYki8lnPZVbzzneXD3w/xvhQsm7VP1ck=", "OdoqbUqBYHhj2W1RLM8APkQOnM2K9gzGm1KPFmwIIeQ="],
22+
"checkpoint": {
23+
"envelope": "rekor.sigstage.dev - 8202293616175992157\n10843718\nRHR6sLAcLFR3TSZvk7xjQNhhJcvIJ9vdGUaLzI2lPnQ\u003d\n\n— rekor.sigstage.dev 0y8wozBFAiA6lsxGcHHUCsYG7eHrwuXkKxu6c9kYGOkoppCzS9rrPAIhALr8TeKA0pmvaUo+oXzYmTRdUIWBVn3gJOiuYQPQksos\n"
24+
}
25+
},
26+
"canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJhMGNmYzcxMjcxZDZlMjc4ZTU3Y2QzMzJmZjk1N2MzZjcwNDNmZGRhMzU0YzRjYmIxOTBhMzBkNTZlZmEwMWJmIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUNMbldZdDNmL0FFWmVYbThvWkpsUXVZaEZMTFF6TDZPeVFGc2JRUHYrMnl3SWdaZk1ZRHVWVkpEejFVQ1UvYUxTSXg0aFhEUVlZSkVkbHFUMDllSlpMUlRnPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTjZha05EUVd4UFowRjNTVUpCWjBsVlpXZDRZMlpQVm5GNk1XTnFlamx1V1hNeE1UWkJlQ3RNYlZCTmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFZkMDVVU1hsTlZGVXdUbFJWZWxkb1kwNU5hbFYzVGxSSmVVMVVWVEZPVkZWNlYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZ5WW1SUk0xQXZaMEY1YW00MmNFczFWRmhEZEc1cGNVeDZPRXB1V25WcU1YbE9jM01LVkhKbVNHTm1lVWx0UWtrMVkyeGthR0ZqU1V3cmJXUktSR1JzTUVSTk1UbENOMkpLT0hwNFprWmhaSFZoWlRoUmNXRlBRMEZZU1hkblowWjFUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZXUVhwYUNtaFNUVmxzYTJGaFFrWnNRM0JJT0dnMk1UZHJLMWRyZDBoM1dVUldVakJxUWtKbmQwWnZRVlZqV1ZsM2NHaFNPRmx0THpVNU9XSXdRbEp3TDFndkwzSUtZalozZDBsUldVUldVakJTUVZGSUwwSkNZM2RHV1VWVVdWZEdlV0l5TlhOYVdHUkJXakk1ZGxveWVHeE1iVTUyWWxSQmNFSm5iM0pDWjBWRlFWbFBMd3BOUVVWQ1FrSjBiMlJJVW5kamVtOTJUREpHYWxreU9URmlibEo2VEcxa2RtSXlaSE5hVXpWcVlqSXdkMHQzV1V0TGQxbENRa0ZIUkhaNlFVSkRRVkZrQ2tSQ2RHOWtTRkozWTNwdmRrd3lSbXBaTWpreFltNVNla3h0WkhaaU1tUnpXbE0xYW1JeU1IZG5XWE5IUTJselIwRlJVVUl4Ym10RFFrRkpSV1pSVWpjS1FVaHJRV1IzUVhKTlRIcGpZVWxxU2pSMVNGbEthV3hsWkVJNVNVOVVSMWRCZGt0alRUaDBaVkV3UkN0emNYbEhaV2RCUVVGYVlqUnlRMk55UVVGQlJRcEJkMEpKVFVWWlEwbFJRelkzYzNkRVIyTmFhMEZGTVZSblJYVkRPRW93YUhOWU1VNXFWa3hNYTFGeVZreDJhMlJLU1dwQ1JGRkphRUZQZUVoU1VsRkdDakJsVFdoMlFrbGpjV0ZKY201c2QwZEVkMVEyZHlzM2VXWlFZWGhWS3pkUWNVbFhaVTFCYjBkRFEzRkhVMDAwT1VKQlRVUkJNbXRCVFVkWlEwMVJSRFVLZHpVeVdUZHFWVFpyZEN0R1NsaHZaMjU2WkVoMVRHWkdibFpVYlZsTFFVNXNXRTFaTVhORmRGUXpVRXd3UTIxQ1dEUmxhMDFDTlhkc05qVlJlbVJ6UXdwTlVVTkRWbWMxU25wRmJFWnhPV1ZCU3prcmNsRkxNMkZoT1ZwTlEwZGxValoyWTFoVlVVdDVUVUpCY2s5eVFXcEthMUpGZEhWMFJuTlljMWQwZVVndkNrbFdhejBLTFMwdExTMUZUa1FnUTBWU1ZFbEdTVU5CVkVVdExTMHRMUW89In19fX0="
27+
}],
28+
"timestampVerificationData": {
29+
"rfc3161Timestamps": [{
30+
"signedTimestamp": "MIIC1DADAgEAMIICywYJKoZIhvcNAQcCoIICvDCCArgCAQMxDTALBglghkgBZQMEAgEwgcIGCyqGSIb3DQEJEAEEoIGyBIGvMIGsAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQg+W1ptazwQEH3WWJYvSD8k7mBD0sukwxxLoY1O797LQ8CFQCNmL6bHDPfDLI1pYdm/HYTm+g/iBgPMjAyNTA1MjIxNTQ1NTRaMAMCAQECCFWBYCIgMDUnoDKkMDAuMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxFTATBgNVBAMTDHNpZ3N0b3JlLXRzYaAAMYIB2zCCAdcCAQEwUTA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQKNaEGYdXiQXPGiZan8n3yfgN8pzALBglghkgBZQMEAgGggfwwGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNTA1MjIxNTQ1NTRaMC8GCSqGSIb3DQEJBDEiBCBBoLsCXV9DBcEGu5MDDDPOyNn8BZepkpDg6kZQUEYMlTCBjgYLKoZIhvcNAQkQAi8xfzB9MHsweQQgBvT/4Ef+s1mZtzOw16MjUBz8GOTAM2aoRdd1NudLJ0QwVTA9pDswOTEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MSAwHgYDVQQDExdzaWdzdG9yZS10c2Etc2VsZnNpZ25lZAIUCjWhBmHV4kFzxomWp/J98n4DfKcwCgYIKoZIzj0EAwIEZzBlAjBarxOk09BZ6k3/IRcCRiZ2uEDLkWrN7+BTW4NJw0+h0hRaUd7DGlNpsd3Kne6HokwCMQCba5x2yv6vm9a/1wfuxa0+mEyv6NcIcdi4ESi+4jIQPTIEfefhgADA/U6vhpD3a24="
31+
}]
32+
},
33+
"certificate": {
34+
"rawBytes": "MIICzjCCAlOgAwIBAgIUegxcfOVqz1cjz9nYs116Ax+LmPMwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUwNTIyMTU0NTUzWhcNMjUwNTIyMTU1NTUzWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAErbdQ3P/gAyjn6pK5TXCtniqLz8JnZuj1yNssTrfHcfyImBI5cldhacIL+mdJDdl0DM19B7bJ8zxfFaduae8QqaOCAXIwggFuMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUVAzZhRMYlkaaBFlCpH8h617k+WkwHwYDVR0jBBgwFoAUcYYwphR8Ym/599b0BRp/X//rb6wwIQYDVR0RAQH/BBcwFYETYWFyb25sZXdAZ29vZ2xlLmNvbTApBgorBgEEAYO/MAEBBBtodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20wKwYKKwYBBAGDvzABCAQdDBtodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20wgYsGCisGAQQB1nkCBAIEfQR7AHkAdwArMLzcaIjJ4uHYJiledB9IOTGWAvKcM8teQ0D+sqyGegAAAZb4rCcrAAAEAwBIMEYCIQC67swDGcZkAE1TgEuC8J0hsX1NjVLLkQrVLvkdJIjBDQIhAOxHRRQF0eMhvBIcqaIrnlwGDwT6w+7yfPaxU+7PqIWeMAoGCCqGSM49BAMDA2kAMGYCMQD5w52Y7jU6kt+FJXognzdHuLfFnVTmYKANlXMY1sEtT3PL0CmBX4ekMB5wl65QzdsCMQCCVg5JzElFq9eAK9+rQK3aa9ZMCGeR6vcXUQKyMBArOrAjJkREtutFsXsWtyH/IVk="
35+
}
36+
},
37+
"messageSignature": {
38+
"messageDigest": {
39+
"algorithm": "SHA2_256",
40+
"digest": "oM/HEnHW4njlfNMy/5V8P3BD/do1TEy7GQow1W76Ab8="
41+
},
42+
"signature": "MEUCIQCLnWYt3f/AEZeXm8oZJlQuYhFLLQzL6OyQFsbQPv+2ywIgZfMYDuVVJDz1UCU/aLSIx4hXDQYYJEdlqT09eJZLRTg="
43+
}
44+
}

0 commit comments

Comments
 (0)