func TestECDSAVerifierWithInvalidSignature(t *testing.T) { var testECDSAKey data.PrivateKey var jsonKey bytes.Buffer // Execute our template templ, _ := template.New("KeyTemplate").Parse(baseECDSAKey) templ.Execute(&jsonKey, KeyTemplate{KeyType: data.ECDSAKey}) testECDSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes()) assert.NoError(t, err) // Sign some data using ECDSA message := []byte("test data for signing") hashed := sha256.Sum256(message) signedData, err := ecdsaSign(testECDSAKey, hashed[:]) assert.NoError(t, err) // Modify the signature signedData[0]++ // Create and call Verify on the verifier ecdsaVerifier := ECDSAVerifier{} err = ecdsaVerifier.Verify(testECDSAKey, signedData, message) assert.Error(t, err, "signature verification failed") }
func TestRSAPKCS1v15VerifierWithInvalidSignature(t *testing.T) { var testRSAKey data.PrivateKey var jsonKey bytes.Buffer // Execute our template templ, _ := template.New("KeyTemplate").Parse(baseRSAKey) templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAKey}) testRSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes()) require.NoError(t, err) // Sign some data using RSAPKCS1v15 message := []byte("test data for signing") hash := crypto.SHA256 hashed := sha256.Sum256(message) signedData, err := rsaPKCS1v15Sign(testRSAKey, hash, hashed[:]) require.NoError(t, err) // Modify the signature signedData[0]++ // Create and call Verify on the verifier rsaVerifier := RSAPKCS1v15Verifier{} err = rsaVerifier.Verify(testRSAKey, signedData, message) require.Error(t, err, "signature verification failed") }
// reads data from the repository in order to fake data being served via // the ServeMux. func fakeServerData(t *testing.T, repo *NotaryRepository, mux *http.ServeMux) { tempKey, err := data.UnmarshalPrivateKey([]byte(timestampECDSAKeyJSON)) assert.NoError(t, err) savedTUFRepo := repo.tufRepo // in case this is overwritten fileStore, err := trustmanager.NewKeyFileStore(repo.baseDir, passphraseRetriever) assert.NoError(t, err) fileStore.AddKey( filepath.Join(filepath.FromSlash(repo.gun), tempKey.ID()), "nonroot", tempKey) rootJSONFile := filepath.Join(repo.baseDir, "tuf", filepath.FromSlash(repo.gun), "metadata", "root.json") rootFileBytes, err := ioutil.ReadFile(rootJSONFile) signedTargets, err := savedTUFRepo.SignTargets( "targets", data.DefaultExpires("targets")) assert.NoError(t, err) signedSnapshot, err := savedTUFRepo.SignSnapshot( data.DefaultExpires("snapshot")) assert.NoError(t, err) signedTimestamp, err := savedTUFRepo.SignTimestamp( data.DefaultExpires("timestamp")) assert.NoError(t, err) mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/root.json", func(w http.ResponseWriter, r *http.Request) { assert.NoError(t, err) fmt.Fprint(w, string(rootFileBytes)) }) mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/timestamp.json", func(w http.ResponseWriter, r *http.Request) { timestampJSON, _ := json.Marshal(signedTimestamp) fmt.Fprint(w, string(timestampJSON)) }) mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/snapshot.json", func(w http.ResponseWriter, r *http.Request) { snapshotJSON, _ := json.Marshal(signedSnapshot) fmt.Fprint(w, string(snapshotJSON)) }) mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/targets.json", func(w http.ResponseWriter, r *http.Request) { targetsJSON, _ := json.Marshal(signedTargets) fmt.Fprint(w, string(targetsJSON)) }) }
func TestRSAPSSVerifierWithInvalidKeyType(t *testing.T) { var testRSAKey data.PrivateKey var jsonKey bytes.Buffer // Execute our template templ, _ := template.New("KeyTemplate").Parse(baseRSAKey) templ.Execute(&jsonKey, KeyTemplate{KeyType: "rsa-invalid"}) testRSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes()) assert.NoError(t, err) // Valid signed data with invalidRsaKeyJSON signedData, _ := hex.DecodeString("2741a57a5ef89f841b4e0a6afbcd7940bc982cd919fbd11dfc21b5ccfe13855b9c401e3df22da5480cef2fa585d0f6dfc6c35592ed92a2a18001362c3a17f74da3906684f9d81c5846bf6a09e2ede6c009ae164f504e6184e666adb14eadf5f6e12e07ff9af9ad49bf1ea9bcfa3bebb2e33be7d4c0fabfe39534f98f1e3c4bff44f637cff3dae8288aea54d86476a3f1320adc39008eae24b991c1de20744a7967d2e685ac0bcc0bc725947f01c9192ffd3e9300eba4b7faa826e84478493fdf97c705dd331dd46072050d6c5e317c2d63df21694dbaf909ebf46ce0ff04f3979fe13723ae1a823c65f27e56efa19e88f9e7b8ee56eac34353b944067deded3a") message := []byte("test data for signing") // Create and call Verify on the verifier rsaVerifier := RSAPSSVerifier{} err = rsaVerifier.Verify(testRSAKey, signedData, message) assert.Error(t, err, "invalid key type for RSAPSS verifier: rsa-invalid") }
func TestECDSAVerifierWithInvalidKey(t *testing.T) { var testECDSAKey data.PrivateKey var jsonKey bytes.Buffer // Execute our template templ, _ := template.New("KeyTemplate").Parse(baseRSAKey) templ.Execute(&jsonKey, KeyTemplate{KeyType: "rsa"}) testECDSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes()) assert.NoError(t, err) // Valid signature using invalidECDSAx509Key signedData, _ := hex.DecodeString("7b1c45a4dd488a087db46ee459192d890d4f52352620cb84c2c10e0ce8a67fd6826936463a91ffdffab8e6f962da6fc3d3e5735412f7cd161a9fcf97ba1a7033") message := []byte("test data for signing") // Create and call Verify on the verifier ecdsaVerifier := ECDSAVerifier{} err = ecdsaVerifier.Verify(testECDSAKey, signedData, message) assert.Error(t, err, "invalid key type for ECDSA verifier: rsa") }
func TestRSAPSSx509Verifier(t *testing.T) { // Unmarshal our public RSA Key var testRSAKey data.PrivateKey var jsonKey bytes.Buffer // Execute our template templ, _ := template.New("KeyTemplate").Parse(baseRSAx509Key) templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAx509Key}) testRSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes()) assert.NoError(t, err) // Valid signed message signedData, _ := hex.DecodeString("3de02fa54cdba45c67860f058b7cff1ba264610dc3c5b466b7df027bc52068bdf2956fe438dba08b0b71daa0780a3037bf8f50a09d91ca81fa872bbdbbbff6ef17e04df8741ad5c2f2c3ea5de97d6ffaf4999c83fdfba4b6cb2443da11c7b7eea84123c2fdaf3319fa6342cbbdbd1aa25d1ac20aeee687e48cbf191cc8f68049230261469eeada33dec0af74287766bd984dd01820a7edfb8b0d030e2fcf00886c578b07eb905a2eebc81fd982a578e717c7ac773cab345950c71e1eaf81b70401e5bf3c67cdcb9068bf4b50ff0456b530b3cec5586827eb39b123f9d666a65f4b418a355438ed1753da8a27577ab9cd791d7b840c7e34ecc1290c46d98aa0dd73c0427f6ef8f63e36af42e9657520b8f56c9231ba7e0172dfc3456c63c54e9eae95d06bafe571e91afa1e42d4010e60dd5c441df112cc8474253eee7f1d6c5350039ffcd1f8b0bb013e4403c16fc5b40d6bd56b742ea1ed82c87880147db194b33b022077cc2e8d31ef3eada3e46683ad437ad8ef7ecbe03c29d7a53a9771e42cc4f9d782813c491186fde2cd1dfa408c4e21dd4c3ca1664e901772ffe1713e37b07c9287572114865a05e17cbe29d8622c6b033dcb43c9721d0943c58098607cc28bd58b3caf3dfc1f66d01ebfaf1aa5c2c5945c23af83fe114e587fa7bcbaea6bdccff3c0ad03ce3328f67af30168e225e5827ad9e94b4702de984e6dd775") message := []byte("test data for signing") // Create and call Verify on the verifier rsaVerifier := RSAPSSVerifier{} err = rsaVerifier.Verify(testRSAKey, signedData, message) assert.NoError(t, err, "expecting success but got error while verifying data using RSAPSS and an X509 encoded Key") }
func TestRSAPKCS1v15x509Verifier(t *testing.T) { // Unmarshal our public RSA Key var testRSAKey data.PrivateKey var jsonKey bytes.Buffer // Execute our template templ, _ := template.New("KeyTemplate").Parse(baseRSAx509Key) templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAx509Key}) testRSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes()) assert.NoError(t, err) // Valid signed message signedData, _ := hex.DecodeString("a19602f609646d57f3d0db930bbe491a997baf33f13191916713734ae778ddb4898ece2078741bb0c24d726514c6b4538c3665c374b0b8ec9ff234b45459633268224c9962756ad3684aca5f13a286657375e798ddcb857ed2707c900f097666b958df56b43b790357430c2e7a5c379ba9972c8b008363c144aac5c7e0fbfad83cf6855cf73baf8e3ad774e910ba6ac8dc4cce58fe19cffb7b0a1feaa73d23ebd2d59de2d7d9e98a809d73a310c5396df64ff7a22d735e661e39d37a6c4a013caa6005e91f597ea35db24e6c750d704d292a180128dcf72a818c53a96b0a83ba0414a3611097905262eb79a6ced1484af27c7da6809aa21ae7c6f05ae6568d5e5d9c170470213a30caf2340c3d52e7bd4056d22074daffee6e29d0a6fd3ca6dbd001831fb1e48573f3663b63e110cde19efaf56e49a835aeda82e4d7286de591376ecd03de36d402ec703f39f79b2f764f991d8950a119f2618f6d4e4618114900597a1e89ced609949410623a17b97095afe08babc4c295ade954f055ca01b7909f5585e98eb99bd916583476aa877d20da8f4fe35c0867e934f41c935d469664b80904a93f9f4d9432cabd9383e08559d6452f8e12b2d861412c450709ff874ad63c25a640605a41c4073f0eb4e16e1965abf8e088e210cbf9d3ca884ec2c13fc8a288cfcef2425d9607fcab01dab45c5c346671a9ae1d0e52c81379fa212c") message := []byte("test data for signing") // Create and call Verify on the verifier rsaVerifier := RSAPKCS1v15Verifier{} err = rsaVerifier.Verify(testRSAKey, signedData, message) assert.NoError(t, err, "expecting success but got error while verifying data using RSAPKCS1v15 and an X509 encoded Key") }
func TestECDSAVerifier(t *testing.T) { var testECDSAKey data.PrivateKey var jsonKey bytes.Buffer // Execute our template templ, _ := template.New("KeyTemplate").Parse(baseECDSAKey) templ.Execute(&jsonKey, KeyTemplate{KeyType: data.ECDSAKey}) testECDSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes()) assert.NoError(t, err) // Sign some data using ECDSA message := []byte("test data for signing") hashed := sha256.Sum256(message) signedData, err := ecdsaSign(testECDSAKey, hashed[:]) assert.NoError(t, err) // Create and call Verify on the verifier ecdsaVerifier := ECDSAVerifier{} err = ecdsaVerifier.Verify(testECDSAKey, signedData, message) assert.NoError(t, err, "expecting success but got error while verifying data using ECDSA") }
func TestRSAPSSVerifier(t *testing.T) { // Unmarshal our private RSA Key var testRSAKey data.PrivateKey var jsonKey bytes.Buffer // Execute our template templ, _ := template.New("KeyTemplate").Parse(baseRSAKey) templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAKey}) testRSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes()) assert.NoError(t, err) // Sign some data using RSAPSS message := []byte("test data for signing") hash := crypto.SHA256 hashed := sha256.Sum256(message) signedData, err := rsaPSSSign(testRSAKey, hash, hashed[:]) assert.NoError(t, err) // Create and call Verify on the verifier rsaVerifier := RSAPSSVerifier{} err = rsaVerifier.Verify(testRSAKey, signedData, message) assert.NoError(t, err, "expecting success but got error while verifying data using RSA PSS") }
func testAddListTarget(t *testing.T, rootType string) { // Temporary directory where test files will be created tempBaseDir, err := ioutil.TempDir("", "notary-test-") defer os.RemoveAll(tempBaseDir) assert.NoError(t, err, "failed to create a temporary directory: %s", err) gun := "docker.com/notary" ts, mux := createTestServer(t) defer ts.Close() repo, err := NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, passphraseRetriever) assert.NoError(t, err, "error creating repository: %s", err) rootKeyID, err := repo.KeyStoreManager.GenRootKey(rootType) assert.NoError(t, err, "error generating root key: %s", err) err = repo.Initialize(rootKeyID) assert.NoError(t, err, "error creating repository: %s", err) // tests need to manually boostrap timestamp as client doesn't generate it err = repo.tufRepo.InitTimestamp() assert.NoError(t, err, "error creating repository: %s", err) // Add fixtures/intermediate-ca.crt as a target. There's no particular reason // for using this file except that it happens to be available as // a fixture. latestTarget, err := NewTarget("latest", "../fixtures/intermediate-ca.crt") assert.NoError(t, err, "error creating target") err = repo.AddTarget(latestTarget) assert.NoError(t, err, "error adding target") // Look for the changelist file changelistDirPath := filepath.Join(tempBaseDir, "tuf", filepath.FromSlash(gun), "changelist") changelistDir, err := os.Open(changelistDirPath) assert.NoError(t, err, "could not open changelist directory") fileInfos, err := changelistDir.Readdir(0) assert.NoError(t, err, "could not read changelist directory") // Should only be one file in the directory assert.Len(t, fileInfos, 1, "wrong number of changelist files found") clName := fileInfos[0].Name() raw, err := ioutil.ReadFile(filepath.Join(changelistDirPath, clName)) assert.NoError(t, err, "could not read changelist file %s", clName) c := &changelist.TufChange{} err = json.Unmarshal(raw, c) assert.NoError(t, err, "could not unmarshal changelist file %s", clName) assert.EqualValues(t, changelist.ActionCreate, c.Actn) assert.Equal(t, "targets", c.Role) assert.Equal(t, "target", c.ChangeType) assert.Equal(t, "latest", c.ChangePath) assert.NotEmpty(t, c.Data) changelistDir.Close() // Create a second target currentTarget, err := NewTarget("current", "../fixtures/intermediate-ca.crt") assert.NoError(t, err, "error creating target") err = repo.AddTarget(currentTarget) assert.NoError(t, err, "error adding target") changelistDir, err = os.Open(changelistDirPath) assert.NoError(t, err, "could not open changelist directory") // There should now be a second file in the directory fileInfos, err = changelistDir.Readdir(0) assert.NoError(t, err, "could not read changelist directory") assert.Len(t, fileInfos, 2, "wrong number of changelist files found") newFileFound := false for _, fileInfo := range fileInfos { if fileInfo.Name() != clName { clName2 := fileInfo.Name() raw, err := ioutil.ReadFile(filepath.Join(changelistDirPath, clName2)) assert.NoError(t, err, "could not read changelist file %s", clName2) c := &changelist.TufChange{} err = json.Unmarshal(raw, c) assert.NoError(t, err, "could not unmarshal changelist file %s", clName2) assert.EqualValues(t, changelist.ActionCreate, c.Actn) assert.Equal(t, "targets", c.Role) assert.Equal(t, "target", c.ChangeType) assert.Equal(t, "current", c.ChangePath) assert.NotEmpty(t, c.Data) newFileFound = true break } } assert.True(t, newFileFound, "second changelist file not found") changelistDir.Close() // Now test ListTargets. In preparation, we need to expose some signed // metadata files on the internal HTTP server. // Apply the changelist. Normally, this would be done by Publish // load the changelist for this repo cl, err := changelist.NewFileChangelist(filepath.Join(tempBaseDir, "tuf", filepath.FromSlash(gun), "changelist")) assert.NoError(t, err, "could not open changelist") // apply the changelist to the repo err = applyChangelist(repo.tufRepo, cl) assert.NoError(t, err, "could not apply changelist") tempKey, err := data.UnmarshalPrivateKey([]byte(timestampECDSAKeyJSON)) assert.NoError(t, err) repo.KeyStoreManager.KeyStore.AddKey(filepath.Join(filepath.FromSlash(gun), tempKey.ID()), "nonroot", tempKey) // Because ListTargets will clear this savedTUFRepo := repo.tufRepo rootJSONFile := filepath.Join(tempBaseDir, "tuf", filepath.FromSlash(gun), "metadata", "root.json") rootFileBytes, err := ioutil.ReadFile(rootJSONFile) signedTargets, err := savedTUFRepo.SignTargets("targets", data.DefaultExpires("targets")) assert.NoError(t, err) signedSnapshot, err := savedTUFRepo.SignSnapshot(data.DefaultExpires("snapshot")) assert.NoError(t, err) signedTimestamp, err := savedTUFRepo.SignTimestamp(data.DefaultExpires("timestamp")) assert.NoError(t, err) mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/root.json", func(w http.ResponseWriter, r *http.Request) { assert.NoError(t, err) fmt.Fprint(w, string(rootFileBytes)) }) mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/timestamp.json", func(w http.ResponseWriter, r *http.Request) { timestampJSON, _ := json.Marshal(signedTimestamp) fmt.Fprint(w, string(timestampJSON)) }) mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/snapshot.json", func(w http.ResponseWriter, r *http.Request) { snapshotJSON, _ := json.Marshal(signedSnapshot) fmt.Fprint(w, string(snapshotJSON)) }) mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/targets.json", func(w http.ResponseWriter, r *http.Request) { targetsJSON, _ := json.Marshal(signedTargets) fmt.Fprint(w, string(targetsJSON)) }) targets, err := repo.ListTargets() assert.NoError(t, err) // Should be two targets assert.Len(t, targets, 2, "unexpected number of targets returned by ListTargets") if targets[0].Name == "latest" { assert.Equal(t, latestTarget, targets[0], "latest target does not match") assert.Equal(t, currentTarget, targets[1], "current target does not match") } else if targets[0].Name == "current" { assert.Equal(t, currentTarget, targets[0], "current target does not match") assert.Equal(t, latestTarget, targets[1], "latest target does not match") } else { t.Fatalf("unexpected target name: %s", targets[0].Name) } // Also test GetTargetByName newLatestTarget, err := repo.GetTargetByName("latest") assert.NoError(t, err) assert.Equal(t, latestTarget, newLatestTarget, "latest target does not match") newCurrentTarget, err := repo.GetTargetByName("current") assert.NoError(t, err) assert.Equal(t, currentTarget, newCurrentTarget, "current target does not match") }
func validateRootSuccessfully(t *testing.T, rootType string) { // Temporary directory where test files will be created tempBaseDir, err := ioutil.TempDir("", "notary-test-") defer os.RemoveAll(tempBaseDir) assert.NoError(t, err, "failed to create a temporary directory: %s", err) gun := "docker.com/notary" ts, mux := createTestServer(t) defer ts.Close() repo, err := NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, passphraseRetriever) assert.NoError(t, err, "error creating repository: %s", err) rootKeyID, err := repo.KeyStoreManager.GenRootKey(rootType) assert.NoError(t, err, "error generating root key: %s", err) err = repo.Initialize(rootKeyID) assert.NoError(t, err, "error creating repository: %s", err) // tests need to manually boostrap timestamp as client doesn't generate it err = repo.tufRepo.InitTimestamp() assert.NoError(t, err, "error creating repository: %s", err) // Initialize is supposed to have created new certificate for this repository // Lets check for it and store it for later use allCerts := repo.KeyStoreManager.TrustedCertificateStore().GetCertificates() assert.Len(t, allCerts, 1) // Now test ListTargets. In preparation, we need to expose some signed // metadata files on the internal HTTP server. tempKey, err := data.UnmarshalPrivateKey([]byte(timestampECDSAKeyJSON)) assert.NoError(t, err) repo.KeyStoreManager.KeyStore.AddKey(filepath.Join(filepath.FromSlash(gun), tempKey.ID()), "root", tempKey) // Because ListTargets will clear this savedTUFRepo := repo.tufRepo rootJSONFile := filepath.Join(tempBaseDir, "tuf", filepath.FromSlash(gun), "metadata", "root.json") rootFileBytes, err := ioutil.ReadFile(rootJSONFile) signedTargets, err := savedTUFRepo.SignTargets("targets", data.DefaultExpires("targets")) assert.NoError(t, err) signedSnapshot, err := savedTUFRepo.SignSnapshot(data.DefaultExpires("snapshot")) assert.NoError(t, err) signedTimestamp, err := savedTUFRepo.SignTimestamp(data.DefaultExpires("timestamp")) assert.NoError(t, err) mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/root.json", func(w http.ResponseWriter, r *http.Request) { assert.NoError(t, err) fmt.Fprint(w, string(rootFileBytes)) }) mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/timestamp.json", func(w http.ResponseWriter, r *http.Request) { timestampJSON, _ := json.Marshal(signedTimestamp) fmt.Fprint(w, string(timestampJSON)) }) mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/snapshot.json", func(w http.ResponseWriter, r *http.Request) { snapshotJSON, _ := json.Marshal(signedSnapshot) fmt.Fprint(w, string(snapshotJSON)) }) mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/targets.json", func(w http.ResponseWriter, r *http.Request) { targetsJSON, _ := json.Marshal(signedTargets) fmt.Fprint(w, string(targetsJSON)) }) _, err = repo.ListTargets() assert.NoError(t, err) // // Test TOFUS logic. We remove all certs and expect a new one to be added after ListTargets // err = repo.KeyStoreManager.TrustedCertificateStore().RemoveAll() assert.NoError(t, err) assert.Len(t, repo.KeyStoreManager.TrustedCertificateStore().GetCertificates(), 0) // This list targets is expected to succeed and the certificate store to have the new certificate _, err = repo.ListTargets() assert.NoError(t, err) assert.Len(t, repo.KeyStoreManager.TrustedCertificateStore().GetCertificates(), 1) // // Test certificate mismatch logic. We remove all certs, add a different cert to the // same CN, and expect ValidateRoot to fail // // First, remove all certs err = repo.KeyStoreManager.TrustedCertificateStore().RemoveAll() assert.NoError(t, err) assert.Len(t, repo.KeyStoreManager.TrustedCertificateStore().GetCertificates(), 0) // Add a previously generated certificate with CN=docker.com/notary err = repo.KeyStoreManager.TrustedCertificateStore().AddCertFromFile("../fixtures/self-signed_docker.com-notary.crt") assert.NoError(t, err) // This list targets is expected to fail, since there already exists a certificate // in the store for the dnsName docker.com/notary, so TOFUS doesn't apply _, err = repo.ListTargets() if assert.Error(t, err, "An error was expected") { assert.Equal(t, err, &keystoremanager.ErrValidationFail{Reason: "failed to validate data with current trusted certificates"}) } }