G1: Parse TUF-1.0 key ids if present
To ease transition to TUF-1.0, this patch allows go-tuf to both
consume TUF-0.9 and TUF-1.0 metadata, but produce TUF-0.9 metadata
that's still compatible with the original go-tuf 0.9. It does
this by defaulting to generating TUF-0.9 key ids, but if go-tuf
receives metadata produced by TUF-1.0, it will parse out both
the 0.9 and 1.0 key ids.
Note that it is only safe for this version of go-tuf to produce
TUF-0.9 metadata based off of other TUF-0.9 metadata. It will produce
incorrect metadata or error out if it is used to advance TUF-1.0
metadata.
Change-Id: I87fffdc17a5456f7e04f990fbd2a0e060340125a
diff --git a/client/interop_test.go b/client/interop_test.go
index 5a16f88..e03e4ea 100644
--- a/client/interop_test.go
+++ b/client/interop_test.go
@@ -38,6 +38,7 @@
"go-tuf-transition-M1",
"go-tuf-transition-M2",
"go-tuf-transition-M3",
+ "go-tuf-transition-M4",
}
for _, version := range versions {
diff --git a/data/types.go b/data/types.go
index c7c79b7..7eda908 100644
--- a/data/types.go
+++ b/data/types.go
@@ -11,9 +11,15 @@
)
const (
- KeyIDLength = sha256.Size * 2
- KeyTypeEd25519 = "ed25519"
- KeyTypeECDSA_SHA2_P256 = "ecdsa-sha2-nistp256"
+ KeyIDLength = sha256.Size * 2
+ KeyTypeEd25519 = "ed25519"
+ KeyTypeECDSA_SHA2_P256 = "ecdsa-sha2-nistp256"
+ KeySchemeEd25519 = "ed25519"
+ KeySchemeECDSA_SHA2_P256 = "ecdsa-sha2-nistp256"
+)
+
+var (
+ KeyAlgorithms = []string{"sha256"}
)
type Signed struct {
@@ -22,14 +28,20 @@
}
type Signature struct {
- KeyID string `json:"keyid"`
- Method string `json:"method"`
+ KeyID string `json:"keyid"`
+
+ // FIXME(TUF-0.9) removed in TUF 1.0, keeping it around for backwards
+ // compatibility with TUF 0.9.
+ Method string `json:"method"`
+
Signature HexBytes `json:"sig"`
}
type Key struct {
- Type string `json:"keytype"`
- Value KeyValue `json:"keyval"`
+ Type string `json:"keytype"`
+ Scheme string `json:"scheme,omitempty"`
+ Algorithms []string `json:"keyid_hash_algorithms,omitempty"`
+ Value KeyValue `json:"keyval"`
ids []string
idOnce sync.Once
@@ -40,6 +52,19 @@
data, _ := cjson.Marshal(k)
digest := sha256.Sum256(data)
k.ids = []string{hex.EncodeToString(digest[:])}
+
+ // FIXME(TUF-0.9) If we receive TUF-1.0 compatible metadata,
+ // the key id we just calculated won't be compatible with
+ // TUF-0.9. So we also need to calculate the TUF-0.9 key id to
+ // be backwards compatible.
+ if k.Scheme != "" || len(k.Algorithms) != 0 {
+ data, _ = cjson.Marshal(Key{
+ Type: k.Type,
+ Value: k.Value,
+ })
+ digest = sha256.Sum256(data)
+ k.ids = append(k.ids, hex.EncodeToString(digest[:]))
+ }
})
return k.ids
}
diff --git a/data/types_test.go b/data/types_test.go
new file mode 100644
index 0000000..1239224
--- /dev/null
+++ b/data/types_test.go
@@ -0,0 +1,51 @@
+package data
+
+import (
+ "encoding/json"
+
+ . "gopkg.in/check.v1"
+)
+
+type TypesSuite struct{}
+
+var _ = Suite(&TypesSuite{})
+
+func (TypesSuite) TestKeyIDs(c *C) {
+ // This public key is from the TUF specs:
+ //
+ // https://github.com/theupdateframework/specification
+ //
+ // Unfortunately there was a bug in the 1.0 spec, which reused the 0.9
+ // key ids. This patch fixes it:
+ //
+ // https://github.com/theupdateframework/specification/pull/43
+ public := `"72378e5bc588793e58f81c8533da64a2e8f1565c1fcc7f253496394ffc52542c"`
+ keyid09 := "1a2b4110927d4cba257262f614896179ff85ca1f1353a41b5224ac474ca71cb4"
+ keyid10 := "1bf1c6e3cdd3d3a8420b19199e27511999850f4b376c4547b2f32fba7e80fca3"
+ keyid10algos := "8e1824bd4e2de736e1388208c41e439fa1cfa19f4852f9ca80015e1da981cad5"
+
+ var hexbytes HexBytes
+ err := json.Unmarshal([]byte(public), &hexbytes)
+ c.Assert(err, IsNil)
+
+ key := Key{
+ Type: KeyTypeEd25519,
+ Value: KeyValue{Public: hexbytes},
+ }
+ c.Assert(key.IDs(), DeepEquals, []string{keyid09})
+
+ key = Key{
+ Type: KeyTypeEd25519,
+ Scheme: KeySchemeEd25519,
+ Value: KeyValue{Public: hexbytes},
+ }
+ c.Assert(key.IDs(), DeepEquals, []string{keyid10, keyid09})
+
+ key = Key{
+ Type: KeyTypeEd25519,
+ Scheme: KeySchemeEd25519,
+ Algorithms: KeyAlgorithms,
+ Value: KeyValue{Public: hexbytes},
+ }
+ c.Assert(key.IDs(), DeepEquals, []string{keyid10algos, keyid09})
+}