From 8b2888d12288eb4b847ffaa81db742fd532dbfec Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Tue, 21 Jul 2015 12:13:26 -0700 Subject: [PATCH 1/2] latest vendored gotuf Signed-off-by: David Lawrence (github: endophage) --- Godeps/Godeps.json | 2 +- .../endophage/gotuf/Godeps/Godeps.json | 4 -- .../endophage/gotuf/data/types_test.go | 38 +++++----- .../gotuf/encrypted/encrypted_test.go | 37 ++++------ .../github.com/endophage/gotuf/signed/sign.go | 8 +++ .../endophage/gotuf/signed/sign_test.go | 41 +++++++++++ .../endophage/gotuf/signed/verifiers_test.go | 35 ++++++++++ .../endophage/gotuf/signed/verify_test.go | 69 +++++++++---------- .../endophage/gotuf/store/dbstore_test.go | 4 +- .../endophage/gotuf/store/httpstore_test.go | 17 ++++- .../src/github.com/endophage/gotuf/tuf.go | 10 +-- .../endophage/gotuf/utils/util_test.go | 29 +++----- client/client.go | 17 ++++- client/client_root_validation_test.go | 4 ++ client/client_test.go | 4 ++ 15 files changed, 205 insertions(+), 114 deletions(-) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 047aa5e3d8..2dca12bdf5 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -63,7 +63,7 @@ }, { "ImportPath": "github.com/endophage/gotuf", - "Rev": "31d0377282dac4a9e5800933d9a920fb09a15331" + "Rev": "a0303e9689b5bf4cccb92b5ebb172f23159fcfbb" }, { "ImportPath": "github.com/go-sql-driver/mysql", diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/Godeps/Godeps.json b/Godeps/_workspace/src/github.com/endophage/gotuf/Godeps/Godeps.json index b87d830344..394e8c947f 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/Godeps/Godeps.json +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/Godeps/Godeps.json @@ -65,10 +65,6 @@ { "ImportPath": "golang.org/x/crypto/scrypt", "Rev": "bfc286917c5fcb7420d7e3092b50bbfd31b38a98" - }, - { - "ImportPath": "gopkg.in/check.v1", - "Rev": "64131543e7896d5bcc6bd5a76287eb75ea96c673" } ] } diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/data/types_test.go b/Godeps/_workspace/src/github.com/endophage/gotuf/data/types_test.go index e91ceba5be..4e584ce17d 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/data/types_test.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/data/types_test.go @@ -2,56 +2,54 @@ package data import ( "bytes" + "encoding/hex" "encoding/json" + "testing" - . "gopkg.in/check.v1" + "github.com/stretchr/testify/assert" ) -type TypesSuite struct{} - -var _ = Suite(&TypesSuite{}) - -func (TypesSuite) TestGenerateFileMetaDefault(c *C) { +func TestGenerateFileMetaDefault(t *testing.T) { // default is sha512 r := bytes.NewReader([]byte("foo")) meta, err := NewFileMeta(r, "sha512") - c.Assert(err, IsNil) - c.Assert(meta.Length, Equals, int64(3)) + assert.NoError(t, err, "Unexpected error.") + assert.Equal(t, meta.Length, int64(3), "Meta did not have expected Length field value") hashes := meta.Hashes - c.Assert(hashes, HasLen, 1) + assert.Len(t, hashes, 1, "Only expected one hash to be present") hash, ok := hashes["sha512"] if !ok { - c.Fatal("missing sha512 hash") + t.Fatal("missing sha512 hash") } - c.Assert(hash.String(), DeepEquals, "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7") + assert.Equal(t, "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7", hex.EncodeToString(hash), "Hashes not equal") } -func (TypesSuite) TestGenerateFileMetaExplicit(c *C) { +func TestGenerateFileMetaExplicit(t *testing.T) { r := bytes.NewReader([]byte("foo")) meta, err := NewFileMeta(r, "sha256", "sha512") - c.Assert(err, IsNil) - c.Assert(meta.Length, Equals, int64(3)) + assert.NoError(t, err) + assert.Equal(t, meta.Length, int64(3)) hashes := meta.Hashes - c.Assert(hashes, HasLen, 2) + assert.Len(t, hashes, 2) for name, val := range map[string]string{ "sha256": "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae", "sha512": "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7", } { hash, ok := hashes[name] if !ok { - c.Fatalf("missing %s hash", name) + t.Fatalf("missing %s hash", name) } - c.Assert(hash.String(), DeepEquals, val) + assert.Equal(t, hex.EncodeToString(hash), val) } } -func (TypesSuite) TestSignatureUnmarshalJSON(c *C) { +func TestSignatureUnmarshalJSON(t *testing.T) { signatureJSON := `{"keyid":"97e8e1b51b6e7cf8720a56b5334bd8692ac5b28233c590b89fab0b0cd93eeedc","method":"RSA","sig":"2230cba525e4f5f8fc744f234221ca9a92924da4cc5faf69a778848882fcf7a20dbb57296add87f600891f2569a9c36706314c240f9361c60fd36f5a915a0e9712fc437b761e8f480868d7a4444724daa0d29a2669c0edbd4046046649a506b3d711d0aa5e70cb9d09dec7381e7de27a3168e77731e08f6ed56fcce2478855e837816fb69aff53412477748cd198dce783850080d37aeb929ad0f81460ebd31e61b772b6c7aa56977c787d4281fa45dbdefbb38d449eb5bccb2702964a52c78811545939712c8280dee0b23b2fa9fbbdd6a0c42476689ace655eba0745b4a21ba108bcd03ad00fdefff416dc74e08486a0538f8fd24989e1b9fc89e675141b7c"}` var sig Signature err := json.Unmarshal([]byte(signatureJSON), &sig) - c.Assert(err, IsNil) + assert.NoError(t, err) // Check that the method string is lowercased - c.Assert(sig.Method.String(), Equals, "rsa") + assert.Equal(t, sig.Method.String(), "rsa") } diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/encrypted/encrypted_test.go b/Godeps/_workspace/src/github.com/endophage/gotuf/encrypted/encrypted_test.go index 31b058252f..a2ab37f5c1 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/encrypted/encrypted_test.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/encrypted/encrypted_test.go @@ -4,45 +4,38 @@ import ( "encoding/json" "testing" - . "gopkg.in/check.v1" + "github.com/stretchr/testify/assert" ) -// Hook up gocheck into the "go test" runner. -func Test(t *testing.T) { TestingT(t) } - -type EncryptedSuite struct{} - -var _ = Suite(&EncryptedSuite{}) - var plaintext = []byte("reallyimportant") -func (EncryptedSuite) TestRoundtrip(c *C) { +func TestRoundtrip(t *testing.T) { passphrase := []byte("supersecret") enc, err := Encrypt(plaintext, passphrase) - c.Assert(err, IsNil) + assert.NoError(t, err) // successful decrypt dec, err := Decrypt(enc, passphrase) - c.Assert(err, IsNil) - c.Assert(dec, DeepEquals, plaintext) + assert.NoError(t, err) + assert.Equal(t, dec, plaintext) // wrong passphrase passphrase[0] = 0 dec, err = Decrypt(enc, passphrase) - c.Assert(err, NotNil) - c.Assert(dec, IsNil) + assert.Error(t, err) + assert.Nil(t, dec) } -func (EncryptedSuite) TestTamperedRoundtrip(c *C) { +func TestTamperedRoundtrip(t *testing.T) { passphrase := []byte("supersecret") enc, err := Encrypt(plaintext, passphrase) - c.Assert(err, IsNil) + assert.NoError(t, err) data := &data{} err = json.Unmarshal(enc, data) - c.Assert(err, IsNil) + assert.NoError(t, err) data.Ciphertext[0] = 0 data.Ciphertext[1] = 0 @@ -50,15 +43,15 @@ func (EncryptedSuite) TestTamperedRoundtrip(c *C) { enc, _ = json.Marshal(data) dec, err := Decrypt(enc, passphrase) - c.Assert(err, NotNil) - c.Assert(dec, IsNil) + assert.Error(t, err) + assert.Nil(t, dec) } -func (EncryptedSuite) TestDecrypt(c *C) { +func TestDecrypt(t *testing.T) { enc := []byte(`{"kdf":{"name":"scrypt","params":{"N":32768,"r":8,"p":1},"salt":"N9a7x5JFGbrtB2uBR81jPwp0eiLR4A7FV3mjVAQrg1g="},"cipher":{"name":"nacl/secretbox","nonce":"2h8HxMmgRfuYdpswZBQaU3xJ1nkA/5Ik"},"ciphertext":"SEW6sUh0jf2wfdjJGPNS9+bkk2uB+Cxamf32zR8XkQ=="}`) passphrase := []byte("supersecret") dec, err := Decrypt(enc, passphrase) - c.Assert(err, IsNil) - c.Assert(dec, DeepEquals, plaintext) + assert.NoError(t, err) + assert.Equal(t, dec, plaintext) } diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign.go b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign.go index b9d5c9e660..7e833147e3 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign.go @@ -3,6 +3,8 @@ package signed import ( "github.com/Sirupsen/logrus" "github.com/endophage/gotuf/data" + "github.com/endophage/gotuf/errors" + "fmt" ) // Sign takes a data.Signed and a key, calculated and adds the signature @@ -28,6 +30,12 @@ func Sign(service CryptoService, s *data.Signed, keys ...data.PublicKey) error { if err != nil { return err } + if len(newSigs) < 1 { + return errors.ErrInsufficientSignatures{ + Name: fmt.Sprint("Cryptoservice failed to produce any signatures for keys %v", keyIDs), + Err: nil, + } + } logrus.Debugf("appending %d new signatures", len(newSigs)) s.Signatures = append(signatures, newSigs...) return nil diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign_test.go b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign_test.go index 99c2095135..949ba14f49 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign_test.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign_test.go @@ -15,6 +15,31 @@ const ( testKeyID2 = "26f2f5c0fbfa98823bf1ad39d5f3b32575895793baf80f1df675597d5b95dba8" ) +type FailingCryptoService struct { + testKey data.PublicKey +} + +func (mts *FailingCryptoService) Sign(keyIDs []string, _ []byte) ([]data.Signature, error) { + sigs := make([]data.Signature, 0, len(keyIDs)) + return sigs, nil +} + +func (mts *FailingCryptoService) Create(_ string, _ data.KeyAlgorithm) (data.PublicKey, error) { + return mts.testKey, nil +} + +func (mts *FailingCryptoService) GetKey(keyID string) data.PublicKey { + if keyID == "testID" { + return mts.testKey + } + return nil +} + +func (mts *FailingCryptoService) RemoveKey(keyID string) error { + return nil +} + + type MockCryptoService struct { testKey data.PublicKey } @@ -114,6 +139,22 @@ func TestMultiSign(t *testing.T) { } +func TestSignReturnsNoSigs(t *testing.T) { + failingCryptoService := &FailingCryptoService{} + testData := data.Signed{} + + testKey, _ := pem.Decode([]byte(testKeyPEM1)) + key := data.NewPublicKey(data.RSAKey, testKey.Bytes) + err := Sign(failingCryptoService, &testData, key) + + if err == nil { + t.Fatalf("Expected failure due to no signature being returned by the crypto service") + } + if len(testData.Signatures) != 0 { + t.Fatalf("Incorrect number of signatures, expected 0: %d", len(testData.Signatures)) + } +} + func TestCreate(t *testing.T) { testKey, _ := pem.Decode([]byte(testKeyPEM1)) k := data.NewPublicKey(data.RSAKey, testKey.Bytes) diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verifiers_test.go b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verifiers_test.go index 1ad92fc69b..56a34213c9 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verifiers_test.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verifiers_test.go @@ -4,6 +4,7 @@ import ( "bytes" "crypto" "crypto/ecdsa" + "crypto/elliptic" "crypto/rand" "crypto/rsa" "crypto/sha256" @@ -272,6 +273,40 @@ func TestECDSAVerifier(t *testing.T) { assert.NoError(t, err, "expecting success but got error while verifying data using ECDSA") } +func TestECDSAVerifierOtherCurves(t *testing.T) { + curves := []elliptic.Curve{elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521()} + + for _, curve := range curves { + ecdsaPrivKey, err := ecdsa.GenerateKey(curve, rand.Reader) + + // Get a DER-encoded representation of the PublicKey + ecdsaPubBytes, err := x509.MarshalPKIXPublicKey(&ecdsaPrivKey.PublicKey) + assert.NoError(t, err, "failed to marshal public key") + + // Get a DER-encoded representation of the PrivateKey + ecdsaPrivKeyBytes, err := x509.MarshalECPrivateKey(ecdsaPrivKey) + assert.NoError(t, err, "failed to marshal private key") + + testECDSAKey := data.NewPrivateKey(data.ECDSAKey, ecdsaPubBytes, ecdsaPrivKeyBytes) + + // 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") + + // Make sure an invalid signature fails verification + signedData[0]++ + err = ecdsaVerifier.Verify(testECDSAKey, signedData, message) + assert.Error(t, err, "expecting error but got success while verifying data using ECDSA") + } +} + func TestECDSAx509Verifier(t *testing.T) { var testECDSAKey data.TUFKey var jsonKey bytes.Buffer diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verify_test.go b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verify_test.go index 568040661d..a943a0e395 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verify_test.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verify_test.go @@ -4,21 +4,14 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" cjson "github.com/tent/canonical-json-go" - . "gopkg.in/check.v1" "github.com/endophage/gotuf/data" "github.com/endophage/gotuf/keys" ) -// Hook up gocheck into the "go test" runner. -func Test(t *testing.T) { TestingT(t) } - -type VerifySuite struct{} - -var _ = Suite(&VerifySuite{}) - -func (VerifySuite) Test(c *C) { +func Test(t *testing.T) { cryptoService := NewEd25519() type test struct { name string @@ -141,68 +134,68 @@ func (VerifySuite) Test(c *C) { err: ErrExpired{expiredTime.Format("2006-01-02 15:04:05 MST")}, }, } - for _, t := range tests { - if t.role == "" { - t.role = "root" + for _, run := range tests { + if run.role == "" { + run.role = "root" } - if t.ver == 0 { - t.ver = minVer + if run.ver == 0 { + run.ver = minVer } - if t.exp == nil { + if run.exp == nil { expires := time.Now().Add(time.Hour) - t.exp = &expires + run.exp = &expires } - if t.typ == "" { - t.typ = data.TUFTypes[t.role] + if run.typ == "" { + run.typ = data.TUFTypes[run.role] } - if t.keys == nil && t.s == nil { + if run.keys == nil && run.s == nil { k, _ := cryptoService.Create("root", data.ED25519Key) - meta := &signedMeta{Type: t.typ, Version: t.ver, Expires: t.exp.Format("2006-01-02 15:04:05 MST")} + meta := &signedMeta{Type: run.typ, Version: run.ver, Expires: run.exp.Format("2006-01-02 15:04:05 MST")} b, err := cjson.Marshal(meta) - c.Assert(err, IsNil) + assert.NoError(t, err) s := &data.Signed{Signed: b} Sign(cryptoService, s, k) - t.s = s - t.keys = []data.PublicKey{k} + run.s = s + run.keys = []data.PublicKey{k} } - if t.roles == nil { - t.roles = map[string]*data.Role{ + if run.roles == nil { + run.roles = map[string]*data.Role{ "root": &data.Role{ RootRole: data.RootRole{ - KeyIDs: []string{t.keys[0].ID()}, + KeyIDs: []string{run.keys[0].ID()}, Threshold: 1, }, Name: "root", }, } } - if t.mut != nil { - t.mut(&t) + if run.mut != nil { + run.mut(&run) } db := keys.NewDB() - for _, k := range t.keys { + for _, k := range run.keys { db.AddKey(k) } - for _, r := range t.roles { + for _, r := range run.roles { err := db.AddRole(r) - c.Assert(err, IsNil) + assert.NoError(t, err) } - err := Verify(t.s, t.role, minVer, db) - if e, ok := t.err.(ErrExpired); ok { - assertErrExpired(c, err, e) + err := Verify(run.s, run.role, minVer, db) + if e, ok := run.err.(ErrExpired); ok { + assertErrExpired(t, err, e) } else { - c.Assert(err, DeepEquals, t.err, Commentf("name = %s", t.name)) + assert.Equal(t, run.err, err) } } } -func assertErrExpired(c *C, err error, expected ErrExpired) { +func assertErrExpired(t *testing.T, err error, expected ErrExpired) { actual, ok := err.(ErrExpired) if !ok { - c.Fatalf("expected err to have type ErrExpired, got %T", err) + t.Fatalf("expected err to have type ErrExpired, got %T", err) } - c.Assert(actual.Expired, Equals, expected.Expired) + assert.Equal(t, actual.Expired, expected.Expired) } diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/store/dbstore_test.go b/Godeps/_workspace/src/github.com/endophage/gotuf/store/dbstore_test.go index 3d1c566e99..c888bb5558 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/store/dbstore_test.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/store/dbstore_test.go @@ -80,11 +80,11 @@ func TestAddBlob(t *testing.T) { t.Fatal("Hashes map has been modified") } - hash := []bytes{0x01, 0x02} + hash := []byte{0x01, 0x02} if sha256[0] != hash[0] || sha256[1] != hash[1] { t.Fatal("SHA256 has been modified") } - hash = []bytes{0x03, 0x04} + hash = []byte{0x03, 0x04} if sha512[0] != hash[0] || sha512[1] != hash[1] { t.Fatal("SHA512 has been modified") } diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/store/httpstore_test.go b/Godeps/_workspace/src/github.com/endophage/gotuf/store/httpstore_test.go index 2c0be9f585..043a1998e4 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/store/httpstore_test.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/store/httpstore_test.go @@ -2,6 +2,7 @@ package store import ( "bytes" + "encoding/base64" "encoding/hex" "encoding/json" "io" @@ -11,12 +12,17 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "github.com/tent/canonical-json-go" "github.com/endophage/gotuf/data" "github.com/endophage/gotuf/signed" ) +const testRoot = `{"signed":{"_type":"Root","consistent_snapshot":false,"expires":"2025-07-17T16:19:21.101698314-07:00","keys":{"1ca15c7f4b2b0c6efce202a545e7267152da28ab7c91590b3b60bdb4da723aad":{"keytype":"ecdsa","keyval":{"private":null,"public":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEb0720c99Cj6ZmuDlznEZ52NA6YpeY9Sj45z51XvPnG63Bi2RSBezMJlPzbSfP39mXKXqOJyT+z9BZhi3FVWczg=="}},"b1d6813b55442ecbfb1f4b40eb1fcdb4290e53434cfc9ba2da24c26c9143873b":{"keytype":"ecdsa-x509","keyval":{"private":null,"public":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJVekNCKzZBREFnRUNBaEFCWDNKLzkzaW8zbHcrZUsvNFhvSHhNQW9HQ0NxR1NNNDlCQU1DTUJFeER6QU4KQmdOVkJBTVRCbVY0Y0dseVpUQWVGdzB4TlRBM01qQXlNekU1TVRkYUZ3MHlOVEEzTVRjeU16RTVNVGRhTUJFeApEekFOQmdOVkJBTVRCbVY0Y0dseVpUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJFTDhOTFhQCitreUJZYzhYY0FTMXB2S2l5MXRQUDlCZHJ1dEdrWlR3Z0dEYTM1THMzSUFXaWlrUmlPbGRuWmxVVEE5cG5JekoKOFlRQThhTjQ1TDQvUlplak5UQXpNQTRHQTFVZER3RUIvd1FFQXdJQW9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRgpCUWNEQXpBTUJnTlZIUk1CQWY4RUFqQUFNQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJRVJ1ZUVURG5xMlRqRFBmClhGRStqUFJqMEtqdXdEOG9HSmtoVGpMUDAycjhBaUI5cUNyL2ZqSXpJZ1NQcTJVSXZqR0hlYmZOYXh1QlpZZUUKYW8xNjd6dHNYZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"}},"fbddae7f25a6c23ca735b017206a849d4c89304a4d8de4dcc4b3d6f3eb22ce3b":{"keytype":"ecdsa","keyval":{"private":null,"public":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/xS5fBHK2HKmlGcvAr06vwPITvmxWP4P3CMDCgY25iSaIiM21OiXA1/Uvo3Pa3xh5G3cwCtDvi+4FpflW2iB/w=="}},"fd75751f010c3442e23b3e3e99a1442a112f2f21038603cb8609d8b17c9e912a":{"keytype":"ed25519","keyval":{"private":null,"public":"rc+glN01m+q8jmX8SolGsjTfk6NMhUQTWyj10hjmne0="}}},"roles":{"root":{"keyids":["b1d6813b55442ecbfb1f4b40eb1fcdb4290e53434cfc9ba2da24c26c9143873b"],"threshold":1},"snapshot":{"keyids":["1ca15c7f4b2b0c6efce202a545e7267152da28ab7c91590b3b60bdb4da723aad"],"threshold":1},"targets":{"keyids":["fbddae7f25a6c23ca735b017206a849d4c89304a4d8de4dcc4b3d6f3eb22ce3b"],"threshold":1},"timestamp":{"keyids":["fd75751f010c3442e23b3e3e99a1442a112f2f21038603cb8609d8b17c9e912a"],"threshold":1}},"version":2},"signatures":[{"keyid":"b1d6813b55442ecbfb1f4b40eb1fcdb4290e53434cfc9ba2da24c26c9143873b","method":"ecdsa","sig":"A2lNVwxHBnD9ViFtRre8r5oG6VvcvJnC6gdvvxv/Jyag40q/fNMjllCqyHrb+6z8XDZcrTTDsFU1R3/e+92d1A=="}]}` + +const testRootKey = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJVekNCKzZBREFnRUNBaEFCWDNKLzkzaW8zbHcrZUsvNFhvSHhNQW9HQ0NxR1NNNDlCQU1DTUJFeER6QU4KQmdOVkJBTVRCbVY0Y0dseVpUQWVGdzB4TlRBM01qQXlNekU1TVRkYUZ3MHlOVEEzTVRjeU16RTVNVGRhTUJFeApEekFOQmdOVkJBTVRCbVY0Y0dseVpUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJFTDhOTFhQCitreUJZYzhYY0FTMXB2S2l5MXRQUDlCZHJ1dEdrWlR3Z0dEYTM1THMzSUFXaWlrUmlPbGRuWmxVVEE5cG5JekoKOFlRQThhTjQ1TDQvUlplak5UQXpNQTRHQTFVZER3RUIvd1FFQXdJQW9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRgpCUWNEQXpBTUJnTlZIUk1CQWY4RUFqQUFNQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJRVJ1ZUVURG5xMlRqRFBmClhGRStqUFJqMEtqdXdEOG9HSmtoVGpMUDAycjhBaUI5cUNyL2ZqSXpJZ1NQcTJVSXZqR0hlYmZOYXh1QlpZZUUKYW8xNjd6dHNYZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" + type TestRoundTripper struct{} func (rt *TestRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { @@ -24,8 +30,12 @@ func (rt *TestRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) } 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( - "http://mirror1.poly.edu/test-pypi/", + server.URL, "metadata", "txt", "targets", @@ -44,8 +54,9 @@ func TestHTTPStoreGetMeta(t *testing.T) { 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)) + rootKey, err := base64.StdEncoding.DecodeString(testRootKey) + assert.NoError(t, err) + k := data.NewPublicKey("ecdsa-x509", rootKey) sigBytes := p.Signatures[0].Signature if err != nil { diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/tuf.go b/Godeps/_workspace/src/github.com/endophage/gotuf/tuf.go index 3e63ea929e..57efe02fcd 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/tuf.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/tuf.go @@ -225,15 +225,15 @@ func (tr *TufRepo) InitTargets() error { } func (tr *TufRepo) InitSnapshot() error { - signedRoot, err := tr.SignRoot(data.DefaultExpires("root"), nil) + root, err := tr.Root.ToSigned() if err != nil { return err } - signedTargets, err := tr.SignTargets("targets", data.DefaultExpires("targets"), nil) + targets, err := tr.Targets[data.ValidRoles["targets"]].ToSigned() if err != nil { return err } - snapshot, err := data.NewSnapshot(signedRoot, signedTargets) + snapshot, err := data.NewSnapshot(root, targets) if err != nil { return err } @@ -242,11 +242,11 @@ func (tr *TufRepo) InitSnapshot() error { } func (tr *TufRepo) InitTimestamp() error { - signedSnapshot, err := tr.SignSnapshot(data.DefaultExpires("snapshot"), nil) + snap, err := tr.Snapshot.ToSigned() if err != nil { return err } - timestamp, err := data.NewTimestamp(signedSnapshot) + timestamp, err := data.NewTimestamp(snap) if err != nil { return err } diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/utils/util_test.go b/Godeps/_workspace/src/github.com/endophage/gotuf/utils/util_test.go index ff13e04b7d..ce7fbefe25 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/utils/util_test.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/utils/util_test.go @@ -5,17 +5,10 @@ import ( "testing" "github.com/endophage/gotuf/data" - . "gopkg.in/check.v1" + "github.com/stretchr/testify/assert" ) -// Hook up gocheck into the "go test" runner. -func Test(t *testing.T) { TestingT(t) } - -type UtilSuite struct{} - -var _ = Suite(&UtilSuite{}) - -func (UtilSuite) TestFileMetaEqual(c *C) { +func TestFileMetaEqual(t *testing.T) { type test struct { name string b data.FileMeta @@ -26,7 +19,7 @@ func (UtilSuite) TestFileMetaEqual(c *C) { m := data.FileMeta{Length: length, Hashes: make(map[string][]byte, len(hashes))} for typ, hash := range hashes { v, err := hex.DecodeString(hash) - c.Assert(err, IsNil) + assert.NoError(t, err, "hash not in hex") m.Hashes[typ] = v } return m @@ -57,12 +50,12 @@ func (UtilSuite) TestFileMetaEqual(c *C) { err: func(t test) error { return ErrNoCommonHash{t.b.Hashes, t.a.Hashes} }, }, } - for _, t := range tests { - c.Assert(FileMetaEqual(t.a, t.b), DeepEquals, t.err(t), Commentf("name = %s", t.name)) + for _, run := range tests { + assert.Equal(t, FileMetaEqual(run.a, run.b), run.err(run), "Files not equivalent") } } -func (UtilSuite) TestNormalizeTarget(c *C) { +func TestNormalizeTarget(t *testing.T) { for before, after := range map[string]string{ "": "/", "foo.txt": "/foo.txt", @@ -71,14 +64,14 @@ func (UtilSuite) TestNormalizeTarget(c *C) { "/with/./a/dot": "/with/a/dot", "/with/double/../dot": "/with/dot", } { - c.Assert(NormalizeTarget(before), Equals, after) + assert.Equal(t, NormalizeTarget(before), after, "Path normalization did not output expected.") } } -func (UtilSuite) TestHashedPaths(c *C) { +func TestHashedPaths(t *testing.T) { hexBytes := func(s string) []byte { v, err := hex.DecodeString(s) - c.Assert(err, IsNil) + assert.NoError(t, err, "String was not hex") return v } hashes := data.Hashes{ @@ -87,11 +80,11 @@ func (UtilSuite) TestHashedPaths(c *C) { } paths := HashedPaths("foo/bar.txt", hashes) // cannot use DeepEquals as the returned order is non-deterministic - c.Assert(paths, HasLen, 2) + assert.Len(t, paths, 2, "Expected 2 paths") expected := map[string]struct{}{"foo/abc123.bar.txt": {}, "foo/def456.bar.txt": {}} for _, path := range paths { if _, ok := expected[path]; !ok { - c.Fatalf("unexpected path: %s", path) + t.Fatalf("unexpected path: %s", path) } delete(expected, path) } diff --git a/client/client.go b/client/client.go index 2623a3a70a..a0731d33a2 100644 --- a/client/client.go +++ b/client/client.go @@ -19,6 +19,7 @@ import ( "github.com/endophage/gotuf" tufclient "github.com/endophage/gotuf/client" "github.com/endophage/gotuf/data" + tuferrors "github.com/endophage/gotuf/errors" "github.com/endophage/gotuf/keys" "github.com/endophage/gotuf/signed" "github.com/endophage/gotuf/store" @@ -207,7 +208,21 @@ func (r *NotaryRepository) Initialize(uCryptoService *cryptoservice.UnlockedCryp r.tufRepo = tuf.NewTufRepo(kdb, r.cryptoService) - if err := r.tufRepo.InitRepo(false); err != nil { + err = r.tufRepo.InitRoot(false) + if err != nil { + logrus.Debug("Error on InitRoot: ", err.Error()) + if _, ok := err.(tuferrors.ErrInsufficientSignatures); !ok { + 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 } diff --git a/client/client_root_validation_test.go b/client/client_root_validation_test.go index 8aa3511d4c..86474d05ee 100644 --- a/client/client_root_validation_test.go +++ b/client/client_root_validation_test.go @@ -66,6 +66,10 @@ func validateRootSuccessfully(t *testing.T, rootType data.KeyAlgorithm) { err = repo.Initialize(rootCryptoService) 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() diff --git a/client/client_test.go b/client/client_test.go index 451e31e0b6..5bb4f031ff 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -219,6 +219,10 @@ func testAddListTarget(t *testing.T, rootType data.KeyAlgorithm) { err = repo.Initialize(rootCryptoService) 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. From 1f53e171bcce58a34bf00b7749b4a536d9ea8883 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Tue, 21 Jul 2015 14:04:05 -0700 Subject: [PATCH 2/2] updating vendored gotuf with updating signing error messages Signed-off-by: David Lawrence (github: endophage) --- Godeps/Godeps.json | 2 +- .../src/github.com/endophage/gotuf/signed/sign.go | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 2dca12bdf5..bb89f04816 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -63,7 +63,7 @@ }, { "ImportPath": "github.com/endophage/gotuf", - "Rev": "a0303e9689b5bf4cccb92b5ebb172f23159fcfbb" + "Rev": "5be7693587dc2f3c6b35fd1394fcc4e098b4f643" }, { "ImportPath": "github.com/go-sql-driver/mysql", diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign.go b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign.go index 7e833147e3..8bab441009 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign.go @@ -1,10 +1,11 @@ package signed import ( + "fmt" "github.com/Sirupsen/logrus" "github.com/endophage/gotuf/data" "github.com/endophage/gotuf/errors" - "fmt" + "strings" ) // Sign takes a data.Signed and a key, calculated and adds the signature @@ -19,7 +20,7 @@ func Sign(service CryptoService, s *data.Signed, keys ...data.PublicKey) error { keyIDMemb[key.ID()] = struct{}{} keyIDs = append(keyIDs, key.ID()) } - logrus.Debugf("Generated list of signing IDs: %v", keyIDs) + logrus.Debugf("Generated list of signing IDs: %s", strings.Join(keyIDs, ", ")) for _, sig := range s.Signatures { if _, ok := keyIDMemb[sig.KeyID]; ok { continue @@ -32,7 +33,7 @@ func Sign(service CryptoService, s *data.Signed, keys ...data.PublicKey) error { } if len(newSigs) < 1 { return errors.ErrInsufficientSignatures{ - Name: fmt.Sprint("Cryptoservice failed to produce any signatures for keys %v", keyIDs), + Name: fmt.Sprint("Cryptoservice failed to produce any signatures for keys with IDs: %s", strings.Join(keyIDs, ", ")), Err: nil, } }