Skip to content

Commit

Permalink
Merge pull request #607 from sigstore/preserve-raw-signing-json
Browse files Browse the repository at this point in the history
Preserve raw signed json segments in TUF metadata
  • Loading branch information
loosebazooka authored Jan 20, 2024
2 parents 51f9270 + cc32d4b commit 7d0999f
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 9 deletions.
7 changes: 5 additions & 2 deletions sigstore-java/src/main/java/dev/sigstore/tuf/model/Root.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@

import org.immutables.gson.Gson;
import org.immutables.value.Value;
import org.immutables.value.Value.Derived;

/** Signed envelope of the Root metadata. */
@Gson.TypeAdapters
@Value.Immutable
public interface Root extends SignedTufMeta<RootMeta> {
@Override
@Gson.Named("signed")
RootMeta getSignedMeta();
@Derived
default RootMeta getSignedMeta() {
return getSignedMeta(RootMeta.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@
*/
package dev.sigstore.tuf.model;

import com.google.gson.JsonElement;
import dev.sigstore.json.GsonSupplier;
import dev.sigstore.json.canonicalizer.JsonCanonicalizer;
import java.io.IOException;
import java.util.List;
import org.immutables.gson.Gson;
import org.immutables.value.Value.Derived;
import org.immutables.value.Value.Lazy;

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

/** An internal helper to translate raw signed json to a useable type. */
@Derived
default T getSignedMeta(Class<T> type) {
return GsonSupplier.GSON.get().fromJson(getRawSignedMeta(), type);
}

/** The raw signed json, just verify signature over this to prevent loss of unknown fields */
@Gson.Named("signed")
JsonElement getRawSignedMeta();

@Lazy
default byte[] getCanonicalSignedBytes() throws IOException {
return new JsonCanonicalizer(GsonSupplier.GSON.get().toJson(getSignedMeta())).getEncodedUTF8();
return new JsonCanonicalizer(GsonSupplier.GSON.get().toJson(getRawSignedMeta()))
.getEncodedUTF8();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@

import org.immutables.gson.Gson;
import org.immutables.value.Value;
import org.immutables.value.Value.Derived;

/** Signed envelope of the Snapshot metadata. */
@Gson.TypeAdapters
@Value.Immutable
public interface Snapshot extends SignedTufMeta<SnapshotMeta> {
@Override
@Gson.Named("signed")
SnapshotMeta getSignedMeta();
@Derived
default SnapshotMeta getSignedMeta() {
return getSignedMeta(SnapshotMeta.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@

import org.immutables.gson.Gson;
import org.immutables.value.Value;
import org.immutables.value.Value.Derived;

/** Signed envelope of the Targets metadata. */
@Gson.TypeAdapters
@Value.Immutable
public interface Targets extends SignedTufMeta<TargetMeta> {
@Override
@Gson.Named("signed")
TargetMeta getSignedMeta();
@Derived
default TargetMeta getSignedMeta() {
return getSignedMeta(TargetMeta.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@

import org.immutables.gson.Gson;
import org.immutables.value.Value;
import org.immutables.value.Value.Derived;

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

@Override
@Gson.Named("signed")
TimestampMeta getSignedMeta();
@Derived
default TimestampMeta getSignedMeta() {
return getSignedMeta(TimestampMeta.class);
}
}
16 changes: 16 additions & 0 deletions sigstore-java/src/test/java/dev/sigstore/tuf/UpdaterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.hash.Hashing;
import com.google.common.io.Resources;
import com.google.gson.JsonSyntaxException;
import dev.sigstore.encryption.signers.Verifier;
import dev.sigstore.encryption.signers.Verifiers;
Expand Down Expand Up @@ -126,6 +127,21 @@ public void testRootUpdate_notEnoughSignatures()
}
}

@Test
public void testRootUpdate_newRootHasUnknownFields() throws Exception {
setupMirror("synthetic/root-update-with-unknown-fields", "4.root.json", "5.root.json");
Path startingRoot =
Path.of(
Resources.getResource(
"dev/sigstore/tuf/synthetic/root-update-with-unknown-fields/4.root.json")
.getPath());
var updater = createTimeStaticUpdater(localStorePath, startingRoot);

updater.updateRoot();
Root root = TestResources.loadRoot(localStorePath.resolve("root.json"));
assertEquals(5, root.getSignedMeta().getVersion());
}

@Test
public void testRootUpdate_expiredRoot()
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"signed": {
"_type": "root",
"spec_version": "1.0",
"version": 4,
"expires": "2029-03-05T22:50:21Z",
"keys": {
"314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600": {
"keytype": "ecdsa-sha2-nistp256",
"scheme": "ecdsa-sha2-nistp256",
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keyval": {
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXMZ7rD8tWDE4lK/+naJN7INMxNC7\nbMMANDqTQE7WpzyzffWOg59hc/MwbvJtvuxhO9mEu3GD3Cn0HffFlmVRiA==\n-----END PUBLIC KEY-----\n"
}
},
"c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda": {
"keytype": "ecdsa-sha2-nistp256",
"scheme": "ecdsa-sha2-nistp256",
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keyval": {
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEL3vL/VeaH6nBbo4rekyO4cc/QthS\n+nlyJXCXSnyIMAtLmVTa8Pf0qG6YIVaR0TmLkyk9YoSVsZakxuMTuaEwrg==\n-----END PUBLIC KEY-----\n"
}
}
},
"roles": {
"root": {
"keyids": [
"c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda"
],
"threshold": 1
},
"snapshot": {
"keyids": [
"314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600"
],
"threshold": 1
},
"targets": {
"keyids": [
"c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda"
],
"threshold": 1
},
"timestamp": {
"keyids": [
"314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600"
],
"threshold": 1
}
},
"consistent_snapshot": true
},
"signatures": [
{
"keyid": "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda",
"sig": "3044022006fe8fff51d18753aeff141f81a962b8ac33f49831bbbec1334b2733ea96890002206e6f343c9c7b98a2ebd1f0b51aa5286ed3a4d48e271c77d88ea77499231bff5c"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"signatures": [
{
"keyid": "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda",
"sig": "3045022016f788e5c90b169b4a9b28c56bf73df988b67c2d73f4e49205db50f9f0ae8066022100b4aabd9298ff12205724bae48bf9118a262581a7ca4b5d1a1b4c68498bd5fdde"
},
{
"keyid": "762cb22caca65de5e9b7b6baecb84ca989d337280ce6914b6440aea95769ad93",
"sig": "3045022100f5a9447b9d240905408106e183ef90914d248a43a869585e5f2001570663f51002207b359b6a39b7ee45c98aca93ba90043bc1f14f9f1223d0cc19eba1c9841e2e82"
}
],
"signed": {
"_type": "root",
"consistent_snapshot": true,
"expires": "2034-01-06T09:35:12Z",
"keys": {
"762cb22caca65de5e9b7b6baecb84ca989d337280ce6914b6440aea95769ad93": {
"keytype": "ecdsa",
"keyval": {
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEohqIdE+yTl4OxpX8ZxNUPrg3SL9H\nBDnhZuceKkxy2oMhUOxhWweZeG3bfM1T4ZLnJimC6CAYVU5+F5jZCoftRw==\n-----END PUBLIC KEY-----\n"
},
"scheme": "ecdsa-sha2-nistp256",
"x-tuf-on-ci-keyowner": "@jku"
},
"858f105a894358684339a8d05f7f07d09010b35bcb0808ac8b09c26fce5434b6": {
"keytype": "ecdsa",
"keyval": {
"public": "-----BEGIN PUBLIC KEY-----\nMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEs+efoKU658vT/rNOsCalHpNadxVtbAei\n0xpIP4bpszlnrYYflOrdDr53rNiQJ33O4eR6Zv1NE6nauR7CKvfuuCNGrtJNEToU\nvWd0uw0zv2ZcL/s7ybmje3qvhhMcN5Ot\n-----END PUBLIC KEY-----\n"
},
"scheme": "ecdsa-sha2-nistp384",
"x-tuf-on-ci-online-uri": "gcpkms:projects/projectsigstore-staging/locations/global/keyRings/tuf-keyring/cryptoKeys/tuf-staging-key/cryptoKeyVersions/1"
},
"c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda": {
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keytype": "ecdsa-sha2-nistp256",
"keyval": {
"public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEL3vL/VeaH6nBbo4rekyO4cc/QthS\n+nlyJXCXSnyIMAtLmVTa8Pf0qG6YIVaR0TmLkyk9YoSVsZakxuMTuaEwrg==\n-----END PUBLIC KEY-----\n"
},
"scheme": "ecdsa-sha2-nistp256",
"x-tuf-on-ci-keyowner": "@-repo-import"
}
},
"roles": {
"root": {
"keyids": [
"c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda",
"762cb22caca65de5e9b7b6baecb84ca989d337280ce6914b6440aea95769ad93"
],
"threshold": 1
},
"snapshot": {
"keyids": [
"858f105a894358684339a8d05f7f07d09010b35bcb0808ac8b09c26fce5434b6"
],
"threshold": 1,
"x-tuf-on-ci-expiry-period": 3650,
"x-tuf-on-ci-signing-period": 365
},
"targets": {
"keyids": [
"762cb22caca65de5e9b7b6baecb84ca989d337280ce6914b6440aea95769ad93"
],
"threshold": 1
},
"timestamp": {
"keyids": [
"858f105a894358684339a8d05f7f07d09010b35bcb0808ac8b09c26fce5434b6"
],
"threshold": 1,
"x-tuf-on-ci-expiry-period": 14,
"x-tuf-on-ci-signing-period": 7
}
},
"spec_version": "1.0",
"version": 5,
"x-tuf-on-ci-expiry-period": 3650,
"x-tuf-on-ci-signing-period": 365
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Setup test data

There are generated by root-signing-staging and were tests that may not exist on the main branch anymore

`4.root.json` : https://github.com/sigstore/root-signing-staging/blob/fecfda76bb9a1721b37dd581f713b72e41270447/metadata/root_history/4.root.json
`5.root.json` : https://github.com/sigstore/root-signing-staging/blob/fecfda76bb9a1721b37dd581f713b72e41270447/metadata/root_history/5.root.json

0 comments on commit 7d0999f

Please sign in to comment.