Skip to content

Commit 7d0999f

Browse files
authored
Merge pull request #607 from sigstore/preserve-raw-signing-json
Preserve raw signed json segments in TUF metadata
2 parents 51f9270 + cc32d4b commit 7d0999f

File tree

9 files changed

+206
-9
lines changed

9 files changed

+206
-9
lines changed

sigstore-java/src/main/java/dev/sigstore/tuf/model/Root.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,15 @@
1717

1818
import org.immutables.gson.Gson;
1919
import org.immutables.value.Value;
20+
import org.immutables.value.Value.Derived;
2021

2122
/** Signed envelope of the Root metadata. */
2223
@Gson.TypeAdapters
2324
@Value.Immutable
2425
public interface Root extends SignedTufMeta<RootMeta> {
2526
@Override
26-
@Gson.Named("signed")
27-
RootMeta getSignedMeta();
27+
@Derived
28+
default RootMeta getSignedMeta() {
29+
return getSignedMeta(RootMeta.class);
30+
}
2831
}

sigstore-java/src/main/java/dev/sigstore/tuf/model/SignedTufMeta.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@
1515
*/
1616
package dev.sigstore.tuf.model;
1717

18+
import com.google.gson.JsonElement;
1819
import dev.sigstore.json.GsonSupplier;
1920
import dev.sigstore.json.canonicalizer.JsonCanonicalizer;
2021
import java.io.IOException;
2122
import java.util.List;
23+
import org.immutables.gson.Gson;
24+
import org.immutables.value.Value.Derived;
25+
import org.immutables.value.Value.Lazy;
2226

2327
/**
2428
* Signed wrapper around {@link TufMeta}.
@@ -32,7 +36,19 @@ public interface SignedTufMeta<T extends TufMeta> {
3236
/** The role metadata that has been signed. */
3337
T getSignedMeta();
3438

39+
/** An internal helper to translate raw signed json to a useable type. */
40+
@Derived
41+
default T getSignedMeta(Class<T> type) {
42+
return GsonSupplier.GSON.get().fromJson(getRawSignedMeta(), type);
43+
}
44+
45+
/** The raw signed json, just verify signature over this to prevent loss of unknown fields */
46+
@Gson.Named("signed")
47+
JsonElement getRawSignedMeta();
48+
49+
@Lazy
3550
default byte[] getCanonicalSignedBytes() throws IOException {
36-
return new JsonCanonicalizer(GsonSupplier.GSON.get().toJson(getSignedMeta())).getEncodedUTF8();
51+
return new JsonCanonicalizer(GsonSupplier.GSON.get().toJson(getRawSignedMeta()))
52+
.getEncodedUTF8();
3753
}
3854
}

sigstore-java/src/main/java/dev/sigstore/tuf/model/Snapshot.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,15 @@
1717

1818
import org.immutables.gson.Gson;
1919
import org.immutables.value.Value;
20+
import org.immutables.value.Value.Derived;
2021

2122
/** Signed envelope of the Snapshot metadata. */
2223
@Gson.TypeAdapters
2324
@Value.Immutable
2425
public interface Snapshot extends SignedTufMeta<SnapshotMeta> {
2526
@Override
26-
@Gson.Named("signed")
27-
SnapshotMeta getSignedMeta();
27+
@Derived
28+
default SnapshotMeta getSignedMeta() {
29+
return getSignedMeta(SnapshotMeta.class);
30+
}
2831
}

sigstore-java/src/main/java/dev/sigstore/tuf/model/Targets.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,15 @@
1717

1818
import org.immutables.gson.Gson;
1919
import org.immutables.value.Value;
20+
import org.immutables.value.Value.Derived;
2021

2122
/** Signed envelope of the Targets metadata. */
2223
@Gson.TypeAdapters
2324
@Value.Immutable
2425
public interface Targets extends SignedTufMeta<TargetMeta> {
2526
@Override
26-
@Gson.Named("signed")
27-
TargetMeta getSignedMeta();
27+
@Derived
28+
default TargetMeta getSignedMeta() {
29+
return getSignedMeta(TargetMeta.class);
30+
}
2831
}

sigstore-java/src/main/java/dev/sigstore/tuf/model/Timestamp.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@
1717

1818
import org.immutables.gson.Gson;
1919
import org.immutables.value.Value;
20+
import org.immutables.value.Value.Derived;
2021

2122
/** Signed envelope of the Timestamp metadata. */
2223
@Gson.TypeAdapters
2324
@Value.Immutable
2425
public interface Timestamp extends SignedTufMeta<TimestampMeta> {
2526

2627
@Override
27-
@Gson.Named("signed")
28-
TimestampMeta getSignedMeta();
28+
@Derived
29+
default TimestampMeta getSignedMeta() {
30+
return getSignedMeta(TimestampMeta.class);
31+
}
2932
}

sigstore-java/src/test/java/dev/sigstore/tuf/UpdaterTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.google.common.collect.ImmutableList;
2323
import com.google.common.collect.ImmutableMap;
2424
import com.google.common.hash.Hashing;
25+
import com.google.common.io.Resources;
2526
import com.google.gson.JsonSyntaxException;
2627
import dev.sigstore.encryption.signers.Verifier;
2728
import dev.sigstore.encryption.signers.Verifiers;
@@ -126,6 +127,21 @@ public void testRootUpdate_notEnoughSignatures()
126127
}
127128
}
128129

130+
@Test
131+
public void testRootUpdate_newRootHasUnknownFields() throws Exception {
132+
setupMirror("synthetic/root-update-with-unknown-fields", "4.root.json", "5.root.json");
133+
Path startingRoot =
134+
Path.of(
135+
Resources.getResource(
136+
"dev/sigstore/tuf/synthetic/root-update-with-unknown-fields/4.root.json")
137+
.getPath());
138+
var updater = createTimeStaticUpdater(localStorePath, startingRoot);
139+
140+
updater.updateRoot();
141+
Root root = TestResources.loadRoot(localStorePath.resolve("root.json"));
142+
assertEquals(5, root.getSignedMeta().getVersion());
143+
}
144+
129145
@Test
130146
public void testRootUpdate_expiredRoot()
131147
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{
2+
"signed": {
3+
"_type": "root",
4+
"spec_version": "1.0",
5+
"version": 4,
6+
"expires": "2029-03-05T22:50:21Z",
7+
"keys": {
8+
"314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600": {
9+
"keytype": "ecdsa-sha2-nistp256",
10+
"scheme": "ecdsa-sha2-nistp256",
11+
"keyid_hash_algorithms": [
12+
"sha256",
13+
"sha512"
14+
],
15+
"keyval": {
16+
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXMZ7rD8tWDE4lK/+naJN7INMxNC7\nbMMANDqTQE7WpzyzffWOg59hc/MwbvJtvuxhO9mEu3GD3Cn0HffFlmVRiA==\n-----END PUBLIC KEY-----\n"
17+
}
18+
},
19+
"c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda": {
20+
"keytype": "ecdsa-sha2-nistp256",
21+
"scheme": "ecdsa-sha2-nistp256",
22+
"keyid_hash_algorithms": [
23+
"sha256",
24+
"sha512"
25+
],
26+
"keyval": {
27+
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEL3vL/VeaH6nBbo4rekyO4cc/QthS\n+nlyJXCXSnyIMAtLmVTa8Pf0qG6YIVaR0TmLkyk9YoSVsZakxuMTuaEwrg==\n-----END PUBLIC KEY-----\n"
28+
}
29+
}
30+
},
31+
"roles": {
32+
"root": {
33+
"keyids": [
34+
"c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda"
35+
],
36+
"threshold": 1
37+
},
38+
"snapshot": {
39+
"keyids": [
40+
"314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600"
41+
],
42+
"threshold": 1
43+
},
44+
"targets": {
45+
"keyids": [
46+
"c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda"
47+
],
48+
"threshold": 1
49+
},
50+
"timestamp": {
51+
"keyids": [
52+
"314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600"
53+
],
54+
"threshold": 1
55+
}
56+
},
57+
"consistent_snapshot": true
58+
},
59+
"signatures": [
60+
{
61+
"keyid": "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda",
62+
"sig": "3044022006fe8fff51d18753aeff141f81a962b8ac33f49831bbbec1334b2733ea96890002206e6f343c9c7b98a2ebd1f0b51aa5286ed3a4d48e271c77d88ea77499231bff5c"
63+
}
64+
]
65+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
{
2+
"signatures": [
3+
{
4+
"keyid": "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda",
5+
"sig": "3045022016f788e5c90b169b4a9b28c56bf73df988b67c2d73f4e49205db50f9f0ae8066022100b4aabd9298ff12205724bae48bf9118a262581a7ca4b5d1a1b4c68498bd5fdde"
6+
},
7+
{
8+
"keyid": "762cb22caca65de5e9b7b6baecb84ca989d337280ce6914b6440aea95769ad93",
9+
"sig": "3045022100f5a9447b9d240905408106e183ef90914d248a43a869585e5f2001570663f51002207b359b6a39b7ee45c98aca93ba90043bc1f14f9f1223d0cc19eba1c9841e2e82"
10+
}
11+
],
12+
"signed": {
13+
"_type": "root",
14+
"consistent_snapshot": true,
15+
"expires": "2034-01-06T09:35:12Z",
16+
"keys": {
17+
"762cb22caca65de5e9b7b6baecb84ca989d337280ce6914b6440aea95769ad93": {
18+
"keytype": "ecdsa",
19+
"keyval": {
20+
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEohqIdE+yTl4OxpX8ZxNUPrg3SL9H\nBDnhZuceKkxy2oMhUOxhWweZeG3bfM1T4ZLnJimC6CAYVU5+F5jZCoftRw==\n-----END PUBLIC KEY-----\n"
21+
},
22+
"scheme": "ecdsa-sha2-nistp256",
23+
"x-tuf-on-ci-keyowner": "@jku"
24+
},
25+
"858f105a894358684339a8d05f7f07d09010b35bcb0808ac8b09c26fce5434b6": {
26+
"keytype": "ecdsa",
27+
"keyval": {
28+
"public": "-----BEGIN PUBLIC KEY-----\nMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEs+efoKU658vT/rNOsCalHpNadxVtbAei\n0xpIP4bpszlnrYYflOrdDr53rNiQJ33O4eR6Zv1NE6nauR7CKvfuuCNGrtJNEToU\nvWd0uw0zv2ZcL/s7ybmje3qvhhMcN5Ot\n-----END PUBLIC KEY-----\n"
29+
},
30+
"scheme": "ecdsa-sha2-nistp384",
31+
"x-tuf-on-ci-online-uri": "gcpkms:projects/projectsigstore-staging/locations/global/keyRings/tuf-keyring/cryptoKeys/tuf-staging-key/cryptoKeyVersions/1"
32+
},
33+
"c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda": {
34+
"keyid_hash_algorithms": [
35+
"sha256",
36+
"sha512"
37+
],
38+
"keytype": "ecdsa-sha2-nistp256",
39+
"keyval": {
40+
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEL3vL/VeaH6nBbo4rekyO4cc/QthS\n+nlyJXCXSnyIMAtLmVTa8Pf0qG6YIVaR0TmLkyk9YoSVsZakxuMTuaEwrg==\n-----END PUBLIC KEY-----\n"
41+
},
42+
"scheme": "ecdsa-sha2-nistp256",
43+
"x-tuf-on-ci-keyowner": "@-repo-import"
44+
}
45+
},
46+
"roles": {
47+
"root": {
48+
"keyids": [
49+
"c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda",
50+
"762cb22caca65de5e9b7b6baecb84ca989d337280ce6914b6440aea95769ad93"
51+
],
52+
"threshold": 1
53+
},
54+
"snapshot": {
55+
"keyids": [
56+
"858f105a894358684339a8d05f7f07d09010b35bcb0808ac8b09c26fce5434b6"
57+
],
58+
"threshold": 1,
59+
"x-tuf-on-ci-expiry-period": 3650,
60+
"x-tuf-on-ci-signing-period": 365
61+
},
62+
"targets": {
63+
"keyids": [
64+
"762cb22caca65de5e9b7b6baecb84ca989d337280ce6914b6440aea95769ad93"
65+
],
66+
"threshold": 1
67+
},
68+
"timestamp": {
69+
"keyids": [
70+
"858f105a894358684339a8d05f7f07d09010b35bcb0808ac8b09c26fce5434b6"
71+
],
72+
"threshold": 1,
73+
"x-tuf-on-ci-expiry-period": 14,
74+
"x-tuf-on-ci-signing-period": 7
75+
}
76+
},
77+
"spec_version": "1.0",
78+
"version": 5,
79+
"x-tuf-on-ci-expiry-period": 3650,
80+
"x-tuf-on-ci-signing-period": 365
81+
}
82+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Setup test data
2+
3+
There are generated by root-signing-staging and were tests that may not exist on the main branch anymore
4+
5+
`4.root.json` : https://github.com/sigstore/root-signing-staging/blob/fecfda76bb9a1721b37dd581f713b72e41270447/metadata/root_history/4.root.json
6+
`5.root.json` : https://github.com/sigstore/root-signing-staging/blob/fecfda76bb9a1721b37dd581f713b72e41270447/metadata/root_history/5.root.json

0 commit comments

Comments
 (0)