// GetOrCreateTimestampKey returns the timestamp key for the gun. It uses the store to // lookup an existing timestamp key and the crypto to generate a new one if none is // found. It attempts to handle the race condition that may occur if 2 servers try to // create the key at the same time by simply querying the store a second time if it // receives a conflict when writing. func GetOrCreateTimestampKey(gun string, store storage.MetaStore, crypto signed.CryptoService, fallBackAlgorithm data.KeyAlgorithm) (data.PublicKey, error) { keyAlgorithm, public, err := store.GetTimestampKey(gun) if err == nil { return data.NewPublicKey(keyAlgorithm, public), nil } if _, ok := err.(*storage.ErrNoKey); ok { key, err := crypto.Create("timestamp", fallBackAlgorithm) if err != nil { return nil, err } logrus.Debug("Creating new timestamp key for ", gun, ". With algo: ", key.Algorithm()) err = store.SetTimestampKey(gun, key.Algorithm(), key.Public()) if err == nil { return key, nil } if _, ok := err.(*storage.ErrTimestampKeyExists); ok { keyAlgorithm, public, err = store.GetTimestampKey(gun) if err != nil { return nil, err } return data.NewPublicKey(keyAlgorithm, public), nil } return nil, err } return nil, err }
func TestRSAPyCryptoVerifierInvalidKeyType(t *testing.T) { key := data.NewPublicKey("bad_type", nil) v := RSAPyCryptoVerifier{} err := v.Verify(key, nil, nil) assert.Error(t, err) assert.IsType(t, ErrInvalidKeyType{}, err) }
// CreateTimestamp creates a new timestamp. If a prev timestamp is provided, it // is assumed this is the immediately previous one, and the new one will have a // version number one higher than prev. The store is used to lookup the current // snapshot, this function does not save the newly generated timestamp. func CreateTimestamp(gun string, prev *data.SignedTimestamp, snapshot []byte, store storage.MetaStore, cryptoService signed.CryptoService) (*data.Signed, int, error) { algorithm, public, err := store.GetTimestampKey(gun) if err != nil { // owner of gun must have generated a timestamp key otherwise // we won't proceed with generating everything. return nil, 0, err } key := data.NewPublicKey(algorithm, public) sn := &data.Signed{} err = json.Unmarshal(snapshot, sn) if err != nil { // couldn't parse snapshot return nil, 0, err } ts, err := data.NewTimestamp(sn) if err != nil { return nil, 0, err } if prev != nil { ts.Signed.Version = prev.Signed.Version + 1 } sgndTs, err := cjson.Marshal(ts.Signed) if err != nil { return nil, 0, err } out := &data.Signed{ Signatures: ts.Signatures, Signed: sgndTs, } err = signed.Sign(cryptoService, out, key) if err != nil { return nil, 0, err } return out, ts.Signed.Version, nil }
// GetKey retrieves a key func (trust *NotarySigner) GetKey(keyid string) data.PublicKey { publicKey, err := trust.kmClient.GetKeyInfo(context.Background(), &pb.KeyID{ID: keyid}) if err != nil { return nil } return data.NewPublicKey(data.KeyAlgorithm(publicKey.KeyInfo.Algorithm.Algorithm), publicKey.PublicKey) }
// ID implements a method of the data.Key interface func (rsa *HSMRSAKey) ID() string { if rsa.id == "" { pubK := data.NewPublicKey(rsa.Algorithm(), rsa.Public()) rsa.id = pubK.ID() } return rsa.id }
func (tr *TufRepo) InitRoot(consistent bool) error { rootRoles := make(map[string]*data.RootRole) rootKeys := make(map[string]data.PublicKey) for _, r := range data.ValidRoles { role := tr.keysDB.GetRole(r) if role == nil { return errors.ErrInvalidRole{} } rootRoles[r] = &role.RootRole for _, kid := range role.KeyIDs { // don't need to check if GetKey returns nil, Key presence was // checked by KeyDB when role was added. key := tr.keysDB.GetKey(kid) // Create new key object to doubly ensure private key is excluded k := data.NewPublicKey(key.Algorithm(), key.Public()) rootKeys[kid] = k } } root, err := data.NewRoot(rootKeys, rootRoles, consistent) if err != nil { return err } tr.Root = root return nil }
// Create creates a remote key and returns the PublicKey associated with the remote private key func (trust *NotarySigner) Create(role string, algorithm data.KeyAlgorithm) (data.PublicKey, error) { publicKey, err := trust.kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: algorithm.String()}) if err != nil { return nil, err } public := data.NewPublicKey(data.KeyAlgorithm(publicKey.KeyInfo.Algorithm.Algorithm), publicKey.PublicKey) return public, nil }
// Create creates a remote key and returns the PublicKey associated with the remote private key func (trust *RufusSigner) Create(role string) (*data.PublicKey, error) { publicKey, err := trust.kmClient.CreateKey(context.Background(), &pb.Void{}) if err != nil { return nil, err } //TODO(mccauley): Update API to return algorithm and/or take it as a param public := data.NewPublicKey(publicKey.Algorithm, publicKey.PublicKey) return public, nil }
// Create creates a remote key and returns the PublicKey associated with the remote private key // TODO(diogo): Ignoring algorithm for now until notary-signer supports it func (trust *NotarySigner) Create(role string, algorithm data.KeyAlgorithm) (*data.PublicKey, error) { publicKey, err := trust.kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: algorithm.String()}) if err != nil { return nil, err } //TODO(mccauley): Update API to return algorithm and/or take it as a param public := data.NewPublicKey(data.KeyAlgorithm(publicKey.KeyInfo.Algorithm.Algorithm), publicKey.PublicKey) return public, nil }
func (trust *Ed25519) Create(role string) (*data.PublicKey, error) { pub, priv, err := ed25519.GenerateKey(rand.Reader) if err != nil { return nil, err } public := data.NewPublicKey("ed25519", pub[:]) private := data.NewPrivateKey("ed25519", pub[:], priv[:]) trust.addKey(private) return public, nil }
// InitRepo creates the base files for a repo. It inspects data.ValidRoles and // data.ValidTypes to determine what the role names and filename should be. It // also relies on the keysDB having already been populated with the keys and // roles. func (tr *TufRepo) InitRepo(consistent bool) error { rootRoles := make(map[string]*data.RootRole) rootKeys := make(map[string]*data.PublicKey) for _, r := range data.ValidRoles { role := tr.keysDB.GetRole(r) if role == nil { return errors.ErrInvalidRole{} } rootRoles[r] = &role.RootRole for _, kid := range role.KeyIDs { // don't need to check if GetKey returns nil, Key presence was // checked by KeyDB when role was added. key := tr.keysDB.GetKey(kid) // Create new key object to doubly ensure private key is excluded k := data.NewPublicKey(key.Cipher(), key.Public()) rootKeys[kid] = k } } root, err := data.NewRoot(rootKeys, rootRoles, consistent) if err != nil { return err } tr.Root = root targets := data.NewTargets() tr.Targets[data.ValidRoles["targets"]] = targets signedRoot, err := tr.SignRoot(data.DefaultExpires("root")) if err != nil { return err } signedTargets, err := tr.SignTargets("targets", data.DefaultExpires("targets")) if err != nil { return err } snapshot, err := data.NewSnapshot(signedRoot, signedTargets) if err != nil { return err } tr.Snapshot = snapshot signedSnapshot, err := tr.SignSnapshot(data.DefaultExpires("snapshot")) if err != nil { return err } timestamp, err := data.NewTimestamp(signedSnapshot) if err != nil { return err } tr.Timestamp = timestamp return nil }
// PublicKeys returns the public key(s) associated with the passed in keyIDs func (trust *RufusSigner) PublicKeys(keyIDs ...string) (map[string]*data.PublicKey, error) { publicKeys := make(map[string]*data.PublicKey) for _, ID := range keyIDs { keyID := pb.KeyID{ID: ID} sig, err := trust.kmClient.GetKeyInfo(context.Background(), &keyID) if err != nil { return nil, err } publicKeys[sig.KeyID.ID] = data.NewPublicKey("TODOALGORITHM", string(sig.PublicKey)) } return publicKeys, nil }
// PublicKeys returns the public key(s) associated with the passed in keyIDs func (trust *RufusSigner) PublicKeys(keyIDs ...string) (map[string]*data.PublicKey, error) { publicKeys := make(map[string]*data.PublicKey) for _, ID := range keyIDs { keyID := pb.KeyID{ID: ID} public, err := trust.kmClient.GetKeyInfo(context.Background(), &keyID) if err != nil { return nil, err } publicKeys[public.KeyID.ID] = data.NewPublicKey(public.Algorithm, public.PublicKey) } return publicKeys, nil }
// AddBaseKeys is used to add keys to the role in root.json func (tr *TufRepo) AddBaseKeys(role string, keys ...data.Key) error { if tr.Root == nil { return &ErrNotLoaded{role: "root"} } for _, k := range keys { key := data.NewPublicKey(k.Cipher(), k.Public()) tr.Root.Signed.Keys[key.ID()] = key tr.keysDB.AddKey(key) tr.Root.Signed.Roles[role].KeyIDs = append(tr.Root.Signed.Roles[role].KeyIDs, key.ID()) } tr.Root.Dirty = true return nil }
func (e *Ed25519) Create(role string, algorithm data.KeyAlgorithm) (data.PublicKey, error) { if algorithm != data.ED25519Key { return nil, errors.New("only ED25519 supported by this cryptoservice") } pub, priv, err := ed25519.GenerateKey(rand.Reader) if err != nil { return nil, err } public := data.NewPublicKey(data.ED25519Key, pub[:]) private := data.NewPrivateKey(data.ED25519Key, pub[:], priv[:]) e.addKey(private) return public, nil }
func TestMultiSign(t *testing.T) { signer := Signer{&MockCryptoService{}} testData := data.Signed{} testKey, _ := pem.Decode([]byte(testKeyPEM1)) key := data.NewPublicKey("rsa", testKey.Bytes) signer.Sign(&testData, key) testKey, _ = pem.Decode([]byte(testKeyPEM2)) key = data.NewPublicKey("rsa", testKey.Bytes) signer.Sign(&testData, key) if len(testData.Signatures) != 2 { t.Fatalf("Incorrect number of signatures: %d", len(testData.Signatures)) } keyIDs := map[string]struct{}{testKeyID1: struct{}{}, testKeyID2: struct{}{}} for _, sig := range testData.Signatures { if _, ok := keyIDs[sig.KeyID]; !ok { t.Fatalf("Got a signature we didn't expect: %s", sig.KeyID) } } }
func TestHTTPStoreGetMeta(t *testing.T) { handler := func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(testRoot)) } server := httptest.NewServer(http.HandlerFunc(handler)) store, err := NewHTTPStore( server.URL, "metadata", "txt", "targets", "key", &http.Transport{}, ) if err != nil { t.Fatal(err) } j, err := store.GetMeta("root", 4801) if err != nil { t.Fatal(err) } p := &data.Signed{} err = json.Unmarshal(j, p) if err != nil { t.Fatal(err) } rootKey, err := base64.StdEncoding.DecodeString(testRootKey) assert.NoError(t, err) k := data.NewPublicKey("ecdsa-x509", rootKey) sigBytes := p.Signatures[0].Signature if err != nil { t.Fatal(err) } var decoded map[string]interface{} if err := json.Unmarshal(p.Signed, &decoded); err != nil { t.Fatal(err) } msg, err := json.MarshalCanonical(decoded) if err != nil { t.Fatal(err) } method := p.Signatures[0].Method err = signed.Verifiers[method].Verify(k, sigBytes, msg) if err != nil { t.Fatal(err) } }
func TestPyNaCled25519Compat(t *testing.T) { pubHex := "846612b43cef909a0e4ea9c818379bca4723a2020619f95e7a0ccc6f0850b7dc" //privHex := "bf3cdb9b2a664b0460e6755cb689ffca15b6e294f79f9f1fcf90b52e5b063a76" testStr := "The quick brown fox jumps over the lazy dog." sigHex := "166e7013e48f26dccb4e68fe4cf558d1cd3af902f8395534336a7f8b4c56588694aa3ac671767246298a59d5ef4224f02c854f41bfcfe70241db4be1546d6a00" pub, _ := hex.DecodeString(pubHex) k := data.NewPublicKey(data.ED25519Key, pub) sigBytes, _ := hex.DecodeString(sigHex) err := signed.Verifiers[data.EDDSASignature].Verify(k, sigBytes, []byte(testStr)) if err != nil { t.Fatal(err) } }
func TestCreate(t *testing.T) { testKey, _ := pem.Decode([]byte(testKeyPEM1)) k := data.NewPublicKey("rsa", testKey.Bytes) signer := Signer{&MockCryptoService{ testKey: *k, }} key, err := signer.Create("root") if err != nil { t.Fatal(err) } if key.ID() != testKeyID1 { t.Fatalf("Expected key ID not found: %s", key.ID()) } }
func TestPyCryptoRSAPSSCompat(t *testing.T) { pubPem := "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAnKuXZeefa2LmgxaL5NsM\nzKOHNe+x/nL6ik+lDBCTV6OdcwAhHQS+PONGhrChIUVR6Vth3hUCrreLzPO73Oo5\nVSCuRJ53UronENl6lsa5mFKP8StYLvIDITNvkoT3j52BJIjyNUK9UKY9As2TNqDf\nBEPIRp28ev/NViwGOEkBu2UAbwCIdnDXm8JQErCZA0Ydm7PKGgjLbFsFGrVzqXHK\n6pdzJXlhr9yap3UpgQ/iO9JtoEYB2EXsnSrPc9JRjR30bNHHtnVql3fvinXrAEwq\n3xmN4p+R4VGzfdQN+8Kl/IPjqWB535twhFYEG/B7Ze8IwbygBjK3co/KnOPqMUrM\nBI8ztvPiogz+MvXb8WvarZ6TMTh8ifZI96r7zzqyzjR1hJulEy3IsMGvz8XS2J0X\n7sXoaqszEtXdq5ef5zKVxkiyIQZcbPgmpHLq4MgfdryuVVc/RPASoRIXG4lKaTJj\n1ANMFPxDQpHudCLxwCzjCb+sVa20HBRPTnzo8LSZkI6jAgMBAAE=\n-----END PUBLIC KEY-----" //privPem := "-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----" testStr := "The quick brown fox jumps over the lazy dog." sigHex := "4e05ee9e435653549ac4eddbc43e1a6868636e8ea6dbec2564435afcb0de47e0824cddbd88776ddb20728c53ecc90b5d543d5c37575fda8bd0317025fc07de62ee8084b1a75203b1a23d1ef4ac285da3d1fc63317d5b2cf1aafa3e522acedd366ccd5fe4a7f02a42922237426ca3dc154c57408638b9bfaf0d0213855d4e9ee621db204151bcb13d4dbb18f930ec601469c992c84b14e9e0b6f91ac9517bb3b749dd117e1cbac2e4acb0e549f44558a2005898a226d5b6c8b9291d7abae0d9e0a16858b89662a085f74a202deb867acab792bdbd2c36731217caea8b17bd210c29b890472f11e5afdd1dd7b69004db070e04201778f2c49f5758643881403d45a58d08f51b5c63910c6185892f0b590f191d760b669eff2464456f130239bba94acf54a0cb98f6939ff84ae26a37f9b890be259d9b5d636f6eb367b53e895227d7d79a3a88afd6d28c198ee80f6527437c5fbf63accb81709925c4e03d1c9eaee86f58e4bd1c669d6af042dbd412de0d13b98b1111e2fadbe34b45de52125e9a" k := data.NewPublicKey(data.RSAKey, []byte(pubPem)) sigBytes, err := hex.DecodeString(sigHex) if err != nil { t.Fatal(err) } v := signed.RSAPyCryptoVerifier{} err = v.Verify(k, sigBytes, []byte(testStr)) if err != nil { t.Fatal(err) } }
// Create is used to generate keys for targets, snapshots and timestamps func (ccs *CliCryptoService) Create(role string) (*data.PublicKey, error) { _, cert, err := generateKeyAndCert(ccs.gun) if err != nil { return nil, err } // PEM ENcode the certificate, which will be put directly inside of TUF's root.json block := pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw} pemdata := pem.EncodeToMemory(&block) // If this key has the role root, save it as a trusted certificate on our certificateStore if role == "root" { certificateStore.AddCertFromPEM(pemdata) } return data.NewPublicKey("RSA", pemdata), nil }
func fingerprintCert(cert *x509.Certificate) (CertID, error) { block := pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw} pemdata := pem.EncodeToMemory(&block) var keyType data.KeyAlgorithm switch cert.PublicKeyAlgorithm { case x509.RSA: keyType = data.RSAx509Key case x509.ECDSA: keyType = data.ECDSAx509Key default: return "", fmt.Errorf("got Unknown key type while fingerprinting certificate") } // Create new TUF Key so we can compute the TUF-compliant CertID tufKey := data.NewPublicKey(keyType, pemdata) return CertID(tufKey.ID()), nil }
func TestGetMeta(t *testing.T) { store, err := NewHTTPStore( "http://mirror1.poly.edu/test-pypi/", "metadata", "txt", "targets", "key", &http.Transport{}, ) if err != nil { t.Fatal(err) } j, err := store.GetMeta("root", 4801) if err != nil { t.Fatal(err) } p := &data.Signed{} err = json.Unmarshal(j, p) if err != nil { t.Fatal(err) } rootPem := "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEArvqUPYb6JJROPJQglPTj\n5uDrsxQKl34Mo+3pSlBVuD6puE4lDnG649a2YksJy+C8ZIPJgokn5w+C3alh+dMe\nzbdWHHxrY1h9CLpYz5cbMlE16303ubkt1rvwDqEezG0HDBzPaKj4oP9YJ9x7wbsq\ndvFcy+Qc3wWd7UWcieo6E0ihbJkYcY8chRXVLg1rL7EfZ+e3bq5+ojA2ECM5JqzZ\nzgDpqCv5hTCYYZp72MZcG7dfSPAHrcSGIrwg7whzz2UsEtCOpsJTuCl96FPN7kAu\n4w/WyM3+SPzzr4/RQXuY1SrLCFD8ebM2zHt/3ATLhPnGmyG5I0RGYoegFaZ2AViw\nlqZDOYnBtgDvKP0zakMtFMbkh2XuNBUBO7Sjs0YcZMjLkh9gYUHL1yWS3Aqus1Lw\nlI0gHS22oyGObVBWkZEgk/Foy08sECLGao+5VvhmGpfVuiz9OKFUmtPVjWzRE4ng\niekEu4drSxpH41inLGSvdByDWLpcTvWQI9nkgclh3AT/AgMBAAE=\n-----END PUBLIC KEY-----" k := data.NewPublicKey("RSA", []byte(rootPem)) sigBytes, err := hex.DecodeString(p.Signatures[0].Signature.String()) if err != nil { t.Fatal(err) } var decoded map[string]interface{} if err := json.Unmarshal(p.Signed, &decoded); err != nil { t.Fatal(err) } msg, err := cjson.Marshal(decoded) if err != nil { t.Fatal(err) } method := p.Signatures[0].Method err = signed.Verifiers[method].Verify(k, sigBytes, msg) if err != nil { t.Fatal(err) } }
// Test signing with the same key multiple times only registers a single signature // for the key (N.B. MockCryptoService.Sign will still be called again, but Signer.Sign // should be cleaning previous signatures by the KeyID when asked to sign again) func TestReSign(t *testing.T) { testKey, _ := pem.Decode([]byte(testKeyPEM1)) k := data.NewPublicKey("rsa", testKey.Bytes) signer := Signer{&MockCryptoService{ testKey: *k, }} testData := data.Signed{} signer.Sign(&testData, k) signer.Sign(&testData, k) if len(testData.Signatures) != 1 { t.Fatalf("Incorrect number of signatures: %d", len(testData.Signatures)) } if testData.Signatures[0].KeyID != testKeyID1 { t.Fatalf("Wrong signature ID returned: %s", testData.Signatures[0].KeyID) } }
// X509PublickeyID returns the public key ID of a RSA X509 key rather than the // cert ID func TestRSAX509PublickeyID(t *testing.T) { fileBytes, err := ioutil.ReadFile("../fixtures/notary-server.key") assert.NoError(t, err) privKey, err := ParsePEMPrivateKey(fileBytes, "") assert.NoError(t, err) expectedTufID := privKey.ID() cert, err := LoadCertFromFile("../fixtures/notary-server.crt") assert.NoError(t, err) rsaKeyBytes, err := x509.MarshalPKIXPublicKey(cert.PublicKey) assert.NoError(t, err) sameWayTufID := data.NewPublicKey(data.RSAKey, rsaKeyBytes).ID() actualTufKey := CertToKey(cert) actualTufID, err := X509PublicKeyID(actualTufKey) assert.Equal(t, sameWayTufID, actualTufID) assert.Equal(t, expectedTufID, actualTufID) }
func applyRootRoleChange(repo *tuf.Repo, c changelist.Change) error { switch c.Action() { case changelist.ActionCreate: // replaces all keys for a role d := &changelist.TufRootData{} err := json.Unmarshal(c.Content(), d) if err != nil { return err } k := []data.PublicKey{} for _, key := range d.Keys { k = append(k, data.NewPublicKey(key.Algorithm(), key.Public())) } err = repo.ReplaceBaseKeys(d.RoleName, k...) if err != nil { return err } default: logrus.Debug("action not yet supported for root: ", c.Action()) } return nil }
// UpdateDelegations updates the appropriate delegations, either adding // a new delegation or updating an existing one. If keys are // provided, the IDs will be added to the role (if they do not exist // there already), and the keys will be added to the targets file. // The "before" argument specifies another role which this new role // will be added in front of (i.e. higher priority) in the delegation list. // An empty before string indicates to add the role to the end of the // delegation list. // A new, empty, targets file will be created for the new role. func (tr *TufRepo) UpdateDelegations(role *data.Role, keys []data.Key, before string) error { if !role.IsDelegation() || !role.IsValid() { return errors.ErrInvalidRole{} } parent := filepath.Dir(role.Name) p, ok := tr.Targets[parent] if !ok { return errors.ErrInvalidRole{} } for _, k := range keys { key := data.NewPublicKey(k.Algorithm(), k.Public()) if !utils.StrSliceContains(role.KeyIDs, key.ID()) { role.KeyIDs = append(role.KeyIDs, key.ID()) } p.Signed.Delegations.Keys[key.ID()] = key tr.keysDB.AddKey(key) } i := -1 var r *data.Role for i, r = range p.Signed.Delegations.Roles { if r.Name == role.Name { break } } if i >= 0 { p.Signed.Delegations.Roles[i] = role } else { p.Signed.Delegations.Roles = append(p.Signed.Delegations.Roles, role) } p.Dirty = true roleTargets := data.NewTargets() // NewTargets always marked Dirty tr.Targets[role.Name] = roleTargets tr.keysDB.AddRole(role) return nil }
// CertsToKeys transforms each of the input certificates into it's corresponding // PublicKey func CertsToKeys(certs []*x509.Certificate) map[string]data.PublicKey { keys := make(map[string]data.PublicKey) for _, cert := range certs { block := pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw} pemdata := pem.EncodeToMemory(&block) var keyType data.KeyAlgorithm switch cert.PublicKeyAlgorithm { case x509.RSA: keyType = data.RSAx509Key case x509.ECDSA: keyType = data.ECDSAx509Key default: logrus.Debugf("unknown certificate type found, ignoring") } // Create new the appropriate PublicKey newKey := data.NewPublicKey(keyType, pemdata) keys[newKey.ID()] = newKey } return keys }
// checkRoot returns true if no rotation, or a valid // rotation has taken place, and the threshold number of signatures // are valid. func checkRoot(oldRoot, newRoot *data.SignedRoot) error { rootRole := data.RoleName(data.CanonicalRootRole) targetsRole := data.RoleName(data.CanonicalTargetsRole) snapshotRole := data.RoleName(data.CanonicalSnapshotRole) timestampRole := data.RoleName(data.CanonicalTimestampRole) var oldRootRole *data.RootRole newRootRole, ok := newRoot.Signed.Roles[rootRole] if !ok { return errors.New("new root is missing role entry for root role") } oldThreshold := 1 rotation := false oldKeys := map[string]data.PublicKey{} newKeys := map[string]data.PublicKey{} if oldRoot != nil { // check for matching root key IDs oldRootRole = oldRoot.Signed.Roles[rootRole] oldThreshold = oldRootRole.Threshold for _, kid := range oldRootRole.KeyIDs { k, ok := oldRoot.Signed.Keys[kid] if !ok { // if the key itself wasn't contained in the root // we're skipping it because it could never have // been used to validate this root. continue } oldKeys[kid] = data.NewPublicKey(k.Algorithm(), k.Public()) } // super simple check for possible rotation rotation = len(oldKeys) != len(newRootRole.KeyIDs) } // if old and new had the same number of keys, iterate // to see if there's a difference. for _, kid := range newRootRole.KeyIDs { k, ok := newRoot.Signed.Keys[kid] if !ok { // if the key itself wasn't contained in the root // we're skipping it because it could never have // been used to validate this root. continue } newKeys[kid] = data.NewPublicKey(k.Algorithm(), k.Public()) if oldRoot != nil { if _, ok := oldKeys[kid]; !ok { // if there is any difference in keys, a key rotation may have // occurred. rotation = true } } } newSigned, err := newRoot.ToSigned() if err != nil { return err } if rotation { err = signed.VerifyRoot(newSigned, oldThreshold, oldKeys) if err != nil { return fmt.Errorf("rotation detected and new root was not signed with at least %d old keys", oldThreshold) } } err = signed.VerifyRoot(newSigned, newRootRole.Threshold, newKeys) if err != nil { return err } root, err := data.RootFromSigned(newSigned) if err != nil { return err } // at a minimum, check the 4 required roles are present for _, r := range []string{rootRole, targetsRole, snapshotRole, timestampRole} { role, ok := root.Signed.Roles[r] if !ok { return fmt.Errorf("missing required %s role from root", r) } if role.Threshold < 1 { return fmt.Errorf("%s role has invalid threshold", r) } if len(role.KeyIDs) < role.Threshold { return fmt.Errorf("%s role has insufficient number of keys", r) } } return nil }
// Initialize creates a new repository by using rootKey as the root Key for the // TUF repository. func (r *NotaryRepository) Initialize(uCryptoService *cryptoservice.UnlockedCryptoService) error { rootCert, err := uCryptoService.GenerateCertificate(r.gun) if err != nil { return err } r.KeyStoreManager.AddTrustedCert(rootCert) // The root key gets stored in the TUF metadata X509 encoded, linking // the tuf root.json to our X509 PKI. // If the key is RSA, we store it as type RSAx509, if it is ECDSA we store it // as ECDSAx509 to allow the gotuf verifiers to correctly decode the // key on verification of signatures. var algorithmType data.KeyAlgorithm algorithm := uCryptoService.PrivKey.Algorithm() switch algorithm { case data.RSAKey: algorithmType = data.RSAx509Key case data.ECDSAKey: algorithmType = data.ECDSAx509Key default: return fmt.Errorf("invalid format for root key: %s", algorithm) } // Generate a x509Key using the rootCert as the public key rootKey := data.NewPublicKey(algorithmType, trustmanager.CertToPEM(rootCert)) // Creates a symlink between the certificate ID and the real public key it // is associated with. This is used to be able to retrieve the root private key // associated with a particular certificate logrus.Debugf("Linking %s to %s.", rootKey.ID(), uCryptoService.ID()) err = r.KeyStoreManager.RootKeyStore().Link(uCryptoService.ID()+"_root", rootKey.ID()+"_root") if err != nil { return err } // All the timestamp keys are generated by the remote server. remote, err := getRemoteStore(r.baseURL, r.gun, r.roundTrip) rawTSKey, err := remote.GetKey("timestamp") if err != nil { return err } parsedKey := &data.TUFKey{} err = json.Unmarshal(rawTSKey, parsedKey) if err != nil { return err } // Turn the JSON timestamp key from the remote server into a TUFKey timestampKey := data.NewPublicKey(parsedKey.Algorithm(), parsedKey.Public()) logrus.Debugf("got remote %s timestamp key with keyID: %s", parsedKey.Algorithm(), timestampKey.ID()) // This is currently hardcoding the targets and snapshots keys to ECDSA // Targets and snapshot keys are always generated locally. targetsKey, err := r.cryptoService.Create("targets", data.ECDSAKey) if err != nil { return err } snapshotKey, err := r.cryptoService.Create("snapshot", data.ECDSAKey) if err != nil { return err } kdb := keys.NewDB() kdb.AddKey(rootKey) kdb.AddKey(targetsKey) kdb.AddKey(snapshotKey) kdb.AddKey(timestampKey) err = initRoles(kdb, rootKey, targetsKey, snapshotKey, timestampKey) if err != nil { return err } r.tufRepo = tuf.NewTufRepo(kdb, r.cryptoService) err = r.tufRepo.InitRoot(false) if err != nil { logrus.Debug("Error on InitRoot: ", err.Error()) switch err.(type) { case tuferrors.ErrInsufficientSignatures, trustmanager.ErrPasswordInvalid: default: return err } } err = r.tufRepo.InitTargets() if err != nil { logrus.Debug("Error on InitTargets: ", err.Error()) return err } err = r.tufRepo.InitSnapshot() if err != nil { logrus.Debug("Error on InitSnapshot: ", err.Error()) return err } return r.saveMetadata(uCryptoService.CryptoService) }