From 2522b3f6dfec55a37f2a26b9a514a13b660ff9f9 Mon Sep 17 00:00:00 2001 From: Diogo Monica Date: Sun, 12 Jul 2015 22:49:35 -0700 Subject: [PATCH] Updating gotuf Signed-off-by: Diogo Monica --- Godeps/Godeps.json | 2 +- .../github.com/endophage/gotuf/data/keys.go | 2 - .../endophage/gotuf/data/snapshot.go | 2 +- .../github.com/endophage/gotuf/data/types.go | 12 +- .../github.com/endophage/gotuf/signed/sign.go | 10 +- .../endophage/gotuf/signed/sign_test.go | 10 +- .../endophage/gotuf/signed/verifiers.go | 123 ++++++-- .../endophage/gotuf/signed/verifiers_test.go | 295 +++++++++++++++++- .../endophage/gotuf/signed/verify.go | 7 +- .../src/github.com/endophage/gotuf/tuf.go | 12 +- 10 files changed, 410 insertions(+), 65 deletions(-) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 4119fb5871..483e3e2512 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -47,7 +47,7 @@ }, { "ImportPath": "github.com/endophage/gotuf", - "Rev": "af7152a51a0663dc47768e591ffdfa1f60e5308a" + "Rev": "ab4ba80203ffa5bfd742e6891bd28bfbf43a9453" }, { "ImportPath": "github.com/go-sql-driver/mysql", diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/data/keys.go b/Godeps/_workspace/src/github.com/endophage/gotuf/data/keys.go index aeb837fef7..4287ef8ec4 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/data/keys.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/data/keys.go @@ -41,9 +41,7 @@ func (k TUFKey) Cipher() string { } func (k *TUFKey) ID() string { - logrus.Debug("Generating Key ID") if k.id == "" { - logrus.Debug("Generating Key ID") pubK := NewTUFKey(k.Cipher(), k.Public(), nil) data, err := cjson.Marshal(&pubK) if err != nil { diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/data/snapshot.go b/Godeps/_workspace/src/github.com/endophage/gotuf/data/snapshot.go index b3acdd7713..06290cd972 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/data/snapshot.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/data/snapshot.go @@ -23,7 +23,7 @@ type Snapshot struct { } func NewSnapshot(root *Signed, targets *Signed) (*SignedSnapshot, error) { - logrus.Debug("NewSnapshot") + logrus.Debug("generating new snapshot...") targetsJSON, err := json.Marshal(targets) if err != nil { logrus.Debug("Error Marshalling Targets") diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/data/types.go b/Godeps/_workspace/src/github.com/endophage/gotuf/data/types.go index f35e11cca6..eccaf2e3ef 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/data/types.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/data/types.go @@ -13,7 +13,17 @@ import ( "github.com/Sirupsen/logrus" ) -const defaultHashAlgorithm = "sha256" +const ( + defaultHashAlgorithm = "sha256" + EDDSASignature = "eddsa" + RSAPSSSignature = "rsapss" + ECDSASignature = "ecdsa" + RSAKey = "rsa" + RSAx509Key = "rsa-x509" + ECDSAKey = "ecdsa" + ECDSAx509Key = "ecdsa-x509" + PyCryptoSignature = "pycrypto-pkcs#1 pss" +) var TUFTypes = map[string]string{ "targets": "Targets", 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 c0bfa5450c..3095e2a78f 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign.go @@ -18,29 +18,27 @@ func NewSigner(service CryptoService) *Signer { // Sign takes a data.Signed and a key, calculated and adds the signature // to the data.Signed func (signer *Signer) Sign(s *data.Signed, keys ...*data.PublicKey) error { - logrus.Debug("signed/sign.go:Sign") + logrus.Debugf("sign called with %d keys", len(keys)) signatures := make([]data.Signature, 0, len(s.Signatures)+1) keyIDMemb := make(map[string]struct{}) keyIDs := make([]string, 0, len(keys)) - logrus.Debug("Generate list of signing IDs") + for _, key := range keys { keyIDMemb[key.ID()] = struct{}{} keyIDs = append(keyIDs, key.ID()) } - logrus.Debug("Filter out sigs we will be resigning") + logrus.Debugf("Generated list of signing IDs: %v", keyIDs) for _, sig := range s.Signatures { if _, ok := keyIDMemb[sig.KeyID]; ok { continue } signatures = append(signatures, sig) } - logrus.Debug("Performing Signing") newSigs, err := signer.service.Sign(keyIDs, s.Signed) if err != nil { return err } - - logrus.Debug("Updating signatures slice") + 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 64a799b40e..7a565f7c3a 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 @@ -41,7 +41,7 @@ var _ CryptoService = &MockCryptoService{} // Test signing and ensure the expected signature is added func TestBasicSign(t *testing.T) { testKey, _ := pem.Decode([]byte(testKeyPEM1)) - k := data.NewPublicKey("RSA", testKey.Bytes) + k := data.NewPublicKey(data.RSAKey, testKey.Bytes) signer := Signer{&MockCryptoService{ testKey: *k, }} @@ -68,7 +68,7 @@ func TestBasicSign(t *testing.T) { // 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) + k := data.NewPublicKey(data.RSAKey, testKey.Bytes) signer := Signer{&MockCryptoService{ testKey: *k, }} @@ -92,11 +92,11 @@ func TestMultiSign(t *testing.T) { testData := data.Signed{} testKey, _ := pem.Decode([]byte(testKeyPEM1)) - key := data.NewPublicKey("RSA", testKey.Bytes) + key := data.NewPublicKey(data.RSAKey, testKey.Bytes) signer.Sign(&testData, key) testKey, _ = pem.Decode([]byte(testKeyPEM2)) - key = data.NewPublicKey("RSA", testKey.Bytes) + key = data.NewPublicKey(data.RSAKey, testKey.Bytes) signer.Sign(&testData, key) if len(testData.Signatures) != 2 { @@ -114,7 +114,7 @@ func TestMultiSign(t *testing.T) { func TestCreate(t *testing.T) { testKey, _ := pem.Decode([]byte(testKeyPEM1)) - k := data.NewPublicKey("RSA", testKey.Bytes) + k := data.NewPublicKey(data.RSAKey, testKey.Bytes) signer := Signer{&MockCryptoService{ testKey: *k, }} diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verifiers.go b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verifiers.go index 90f66a491c..2a3c0fb3ac 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verifiers.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verifiers.go @@ -2,10 +2,12 @@ package signed import ( "crypto" + "crypto/ecdsa" "crypto/rsa" "crypto/sha256" "crypto/x509" "encoding/pem" + "math/big" "reflect" "github.com/Sirupsen/logrus" @@ -17,10 +19,10 @@ import ( // can be injected into a verificationService. For testing and configuration // purposes, it will not be used by default. var Verifiers = map[string]Verifier{ - "ed25519": Ed25519Verifier{}, - "rsassa-pss": RSAPSSVerifier{}, - "rsassa-pss-x509": RSAPSSX509Verifier{}, - "pycrypto-pkcs#1 pss": RSAPyCryptoVerifier{}, + data.RSAPSSSignature: RSAPSSVerifier{}, + data.PyCryptoSignature: RSAPyCryptoVerifier{}, + data.ECDSASignature: ECDSAVerifier{}, + data.EDDSASignature: Ed25519Verifier{}, } // RegisterVerifier provides a convenience function for init() functions @@ -31,12 +33,12 @@ func RegisterVerifier(name string, v Verifier) { typOld := reflect.TypeOf(curr) typNew := reflect.TypeOf(v) logrus.Debugf( - "Replacing already loaded verifier %s:%s with %s:%s", + "replacing already loaded verifier %s:%s with %s:%s", typOld.PkgPath(), typOld.Name(), typNew.PkgPath(), typNew.Name(), ) } else { - logrus.Debug("Adding verifier for: ", name) + logrus.Debug("adding verifier for: ", name) } Verifiers[name] = v } @@ -46,7 +48,7 @@ type Ed25519Verifier struct{} func (v Ed25519Verifier) Verify(key data.Key, sig []byte, msg []byte) error { var sigBytes [ed25519.SignatureSize]byte if len(sig) != len(sigBytes) { - logrus.Infof("Signature length is incorrect, must be %d, was %d.", ed25519.SignatureSize, len(sig)) + logrus.Infof("signature length is incorrect, must be %d, was %d.", ed25519.SignatureSize, len(sig)) return ErrInvalid } copy(sigBytes[:], sig) @@ -55,7 +57,7 @@ func (v Ed25519Verifier) Verify(key data.Key, sig []byte, msg []byte) error { copy(keyBytes[:], key.Public()) if !ed25519.Verify(&keyBytes, msg, &sigBytes) { - logrus.Infof("Failed ed25519 verification") + logrus.Infof("failed ed25519 verification") return ErrInvalid } return nil @@ -64,13 +66,13 @@ func (v Ed25519Verifier) Verify(key data.Key, sig []byte, msg []byte) error { func verifyPSS(key interface{}, digest, sig []byte) error { rsaPub, ok := key.(*rsa.PublicKey) if !ok { - logrus.Infof("Value was not an RSA public key") + logrus.Infof("value was not an RSA public key") return ErrInvalid } opts := rsa.PSSOptions{SaltLength: sha256.Size, Hash: crypto.SHA256} if err := rsa.VerifyPSS(rsaPub, crypto.SHA256, digest[:], sig, &opts); err != nil { - logrus.Infof("Failed verification: %s", err) + logrus.Infof("failed RSAPSS verification: %s", err) return ErrInvalid } return nil @@ -81,15 +83,37 @@ type RSAPSSVerifier struct{} // Verify does the actual check. func (v RSAPSSVerifier) Verify(key data.Key, sig []byte, msg []byte) error { - digest := sha256.Sum256(msg) + cipher := key.Cipher() + var pubKey crypto.PublicKey - pub, err := x509.ParsePKIXPublicKey(key.Public()) - if err != nil { - logrus.Infof("Failed to parse public key: %s\n", err) + switch cipher { + case data.RSAx509Key: + pemCert, _ := pem.Decode([]byte(key.Public())) + if pemCert == nil { + logrus.Infof("failed to decode PEM-encoded x509 certificate") + return ErrInvalid + } + cert, err := x509.ParseCertificate(pemCert.Bytes) + if err != nil { + logrus.Infof("failed to parse x509 certificate: %s\n", err) + return ErrInvalid + } + pubKey = cert.PublicKey + case data.RSAKey: + var err error + pubKey, err = x509.ParsePKIXPublicKey(key.Public()) + if err != nil { + logrus.Infof("failed to parse public key: %s\n", err) + return ErrInvalid + } + default: + logrus.Infof("invalid key type for RSAPSS verifier: %s", cipher) return ErrInvalid } - return verifyPSS(pub, digest[:], sig) + digest := sha256.Sum256(msg) + + return verifyPSS(pubKey, digest[:], sig) } // RSAPSSVerifier checks RSASSA-PSS signatures @@ -103,37 +127,76 @@ func (v RSAPyCryptoVerifier) Verify(key data.Key, sig []byte, msg []byte) error k, _ := pem.Decode([]byte(key.Public())) if k == nil { - logrus.Infof("Failed to decode PEM-encoded x509 certificate") + logrus.Infof("failed to decode PEM-encoded x509 certificate") return ErrInvalid } pub, err := x509.ParsePKIXPublicKey(k.Bytes) if err != nil { - logrus.Infof("Failed to parse public key: %s\n", err) + logrus.Infof("failed to parse public key: %s\n", err) return ErrInvalid } return verifyPSS(pub, digest[:], sig) } -// RSAPSSPEMVerifier checks RSASSA-PSS signatures, extracting the public key -// from an X509 certificate. -type RSAPSSX509Verifier struct{} +// ECDSAVerifier checks ECDSA signatures, decoding the keyType appropriately +type ECDSAVerifier struct{} // Verify does the actual check. -func (v RSAPSSX509Verifier) Verify(key data.Key, sig []byte, msg []byte) error { +func (v ECDSAVerifier) Verify(key data.Key, sig []byte, msg []byte) error { + cipher := key.Cipher() + var pubKey crypto.PublicKey + + switch cipher { + case data.ECDSAx509Key: + pemCert, _ := pem.Decode([]byte(key.Public())) + if pemCert == nil { + logrus.Infof("failed to decode PEM-encoded x509 certificate for keyID: %s", key.ID()) + logrus.Debugf("certificate bytes: %s", string(key.Public())) + return ErrInvalid + } + cert, err := x509.ParseCertificate(pemCert.Bytes) + if err != nil { + logrus.Infof("failed to parse x509 certificate: %s\n", err) + return ErrInvalid + } + pubKey = cert.PublicKey + case data.ECDSAKey: + var err error + pubKey, err = x509.ParsePKIXPublicKey(key.Public()) + if err != nil { + logrus.Infof("Failed to parse private key for keyID: %s, %s\n", key.ID(), err) + return ErrInvalid + } + default: + logrus.Infof("invalid key type for ECDSA verifier: %s", cipher) + return ErrInvalid + } + + ecdsaPubKey, ok := pubKey.(*ecdsa.PublicKey) + if !ok { + logrus.Infof("value isn't an ECDSA public key") + return ErrInvalid + } + + sigLength := len(sig) + expectedOctetLength := 2 * ((ecdsaPubKey.Params().BitSize + 7) >> 3) + if sigLength != expectedOctetLength { + logrus.Infof("signature had an unexpected length") + return ErrInvalid + } + + rBytes, sBytes := sig[:sigLength/2], sig[sigLength/2:] + r := new(big.Int).SetBytes(rBytes) + s := new(big.Int).SetBytes(sBytes) + digest := sha256.Sum256(msg) - k, _ := pem.Decode([]byte(key.Public())) - if k == nil { - logrus.Infof("Failed to decode PEM-encoded x509 certificate") - return ErrInvalid - } - cert, err := x509.ParseCertificate(k.Bytes) - if err != nil { - logrus.Infof("Failed to parse x509 certificate: %s\n", err) + if !ecdsa.Verify(ecdsaPubKey, digest[:], r, s) { + logrus.Infof("failed ECDSA signature validation") return ErrInvalid } - return verifyPSS(cert.PublicKey, digest[:], sig) + return nil } 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 4f57d2ea6b..279442511e 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 @@ -1,13 +1,298 @@ package signed import ( - _ "crypto" - _ "crypto/rsa" - _ "crypto/sha256" - _ "crypto/x509" + "bytes" + "crypto" + "crypto/ecdsa" + "crypto/rand" + "crypto/rsa" + "crypto/sha256" + "crypto/x509" + "encoding/hex" + "encoding/json" + "fmt" "testing" + "text/template" + + "github.com/endophage/gotuf/data" + "github.com/stretchr/testify/assert" ) -func TestRSAVerify(t *testing.T) { +type KeyTemplate struct { + KeyType string +} + +const baseRSAKey = `{"keytype":"{{.KeyType}}","keyval":{"public":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyyvBtTg2xzYS+MTTIBqSpI4V78tt8Yzqi7Jki/Z6NqjiDvcnbgcTqNR2t6B2W5NjGdp/hSaT2jyHM+kdmEGaPxg/zIuHbL3NIp4e0qwovWiEgACPIaELdn8O/kt5swsSKl1KMvLCH1sM86qMibNMAZ/hXOwd90TcHXCgZ91wHEAmsdjDC3dB0TT+FBgOac8RM01Y196QrZoOaDMTWh0EQfw7YbXAElhFVDFxBzDdYWbcIHSIogXQmq0CP+zaL/1WgcZZIClt2M6WCaxxF1S34wNn45gCvVZiZQ/iKWHerSr/2dGQeGo+7ezMSutRzvJ+01fInD86RS/CEtBCFZ1VyQIDAQAB","private":"MIIEpAIBAAKCAQEAyyvBtTg2xzYS+MTTIBqSpI4V78tt8Yzqi7Jki/Z6NqjiDvcnbgcTqNR2t6B2W5NjGdp/hSaT2jyHM+kdmEGaPxg/zIuHbL3NIp4e0qwovWiEgACPIaELdn8O/kt5swsSKl1KMvLCH1sM86qMibNMAZ/hXOwd90TcHXCgZ91wHEAmsdjDC3dB0TT+FBgOac8RM01Y196QrZoOaDMTWh0EQfw7YbXAElhFVDFxBzDdYWbcIHSIogXQmq0CP+zaL/1WgcZZIClt2M6WCaxxF1S34wNn45gCvVZiZQ/iKWHerSr/2dGQeGo+7ezMSutRzvJ+01fInD86RS/CEtBCFZ1VyQIDAQABAoIBAHar8FFxrE1gAGTeUpOF8fG8LIQMRwO4U6eVY7V9GpWiv6gOJTHXYFxU/aL0Ty3eQRxwy9tyVRo8EJz5pRex+e6ws1M+jLOviYqW4VocxQ8dZYd+zBvQfWmRfah7XXJ/HPUx2I05zrmR7VbGX6Bu4g5w3KnyIO61gfyQNKF2bm2Q3yblfupx3URvX0bl180R/+QN2Aslr4zxULFE6b+qJqBydrztq+AAP3WmskRxGa6irFnKxkspJqUpQN1mFselj6iQrzAcwkRPoCw0RwCCMq1/OOYvQtgxTJcO4zDVlbw54PvnxPZtcCWw7fO8oZ2Fvo2SDo75CDOATOGaT4Y9iqECgYEAzWZSpFbN9ZHmvq1lJQg//jFAyjsXRNn/nSvyLQILXltz6EHatImnXo3v+SivG91tfzBI1GfDvGUGaJpvKHoomB+qmhd8KIQhO5MBdAKZMf9fZqZofOPTD9xRXECCwdi+XqHBmL+l1OWz+O9Bh+Qobs2as/hQVgHaoXhQpE0NkTcCgYEA/Tjf6JBGl1+WxQDoGZDJrXoejzG9OFW19RjMdmPrg3t4fnbDtqTpZtCzXxPTCSeMrvplKbqAqZglWyq227ksKw4p7O6YfyhdtvC58oJmivlLr6sFaTsER7mDcYce8sQpqm+XQ8IPbnOk0Z1l6g56euTwTnew49uy25M6U1xL0P8CgYEAxEXv2Kw+OVhHV5PX4BBHHj6we88FiDyMfwM8cvfOJ0datekf9X7ImZkmZEAVPJpWBMD+B0J0jzU2b4SLjfFVkzBHVOH2Ob0xCH2MWPAWtekin7OKizUlPbW5ZV8b0+Kq30DQ/4a7D3rEhK8UPqeuX1tHZox1MAqrgbq3zJj4yvcCgYEAktYPKPm4pYCdmgFrlZ+bA0iEPf7Wvbsd91F5BtHsOOM5PQQ7e0bnvWIaEXEad/2CG9lBHlBy2WVLjDEZthILpa/h6e11ao8KwNGY0iKBuebT17rxOVMqqTjPGt8CuD2994IcEgOPFTpkAdUmyvG4XlkxbB8F6St17NPUB5DGuhsCgYA//Lfytk0FflXEeRQ16LT1YXgV7pcR2jsha4+4O5pxSFw/kTsOfJaYHg8StmROoyFnyE3sg76dCgLn0LENRCe5BvDhJnp5bMpQldG3XwcAxH8FGFNY4LtV/2ZKnJhxcONkfmzQPOmTyedOzrKQ+bNURsqLukCypP7/by6afBY4dA=="}}` +const baseRSAx509Key = `{"keytype":"{{.KeyType}}","keyval":{"public":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZLekNDQXhXZ0F3SUJBZ0lRSGZoeWdIbWFkenNMRW9vR0tUbzNuekFMQmdrcWhraUc5dzBCQVFzd09ERWEKTUJnR0ExVUVDaE1SWkc5amEyVnlMbU52YlM5dWIzUmhjbmt4R2pBWUJnTlZCQU1URVdSdlkydGxjaTVqYjIwdgpibTkwWVhKNU1CNFhEVEUxTURjeE16QTBNell4TTFvWERURTNNRGN4TWpBME16WXhNMW93T0RFYU1CZ0dBMVVFCkNoTVJaRzlqYTJWeUxtTnZiUzl1YjNSaGNua3hHakFZQmdOVkJBTVRFV1J2WTJ0bGNpNWpiMjB2Ym05MFlYSjUKTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUFuVUZoelBSeUgyOG90SWRJSnlEdApXZDBMcURqQkZMUXNxZXRiTC90QS9hdmxVNE1UQk44eFBJQmJrazNjWDU2bTdOQVBwWDBaZkUzMGc3UXBkVElNCjJteUpNMUtLN2lnQkJzd3czMkpUOVhHRW15K0lWb1Nwc1lCdzJkMWF5dGdxWUI4UXZhZ01zamc4eEc2aWVhUGwKcG9tcUVYdEt1YzBoOTEyaTQ4YURpUzlIK3ExMmlvcmlkVDRmazFrcm1sZ1orMHMrSlZobUFlQ0FiMmZvTFc5YworUDErUnlEQ3FZN2NyaXhZcUJ3c3ZIZ00zbUw4SitmWlZVUWZLYTVmQlA1dFp5MGk3UE9QVFZpdVl3R20rSHlYCmhyQnRpalF0b0R3Y1U4VEVEdDAyelJSd0N3elZKMFhwdGhrVmRqZUNrSkFFcGpyOHVGQ1ZKYlJXOWgrWXRLQlYKMCtzMWl5elFqVWwydklEczRiSVc0RzVaeVp0OHNSaTAzRFhHTnNtNDhrRWlaVWswd0RuNGpzMW8vdUJEVUN6YwphdHdrN2t1aVhrcFFNMVdkRmF6TCtmYWJueWR3Z285bWI2c1FKQlRxMDdvNEI0M0JWYTBHZm5ZSFRsVUtWSHZ6CmNwb1pNWTMyb1AyN0t5TXlybkxETzducUlBQnA1UEFvMUpNU09GWWdKa3R1Sk5LT2h0Sm9qcUgyV21wajRvbzkKQmZMY2d6TFNQd2ZTbytXS0FaVmQzYU1FcnFCQ3RBcVN2aUdmdVRaT3FkK2JKZGY4aW1jZ3ZCeWdacVVRb0J2aAo4Q1hSWGxUNTdKSUFrVkY3aUxrVUZoUkhxY2lwVjZqVzFWeEFXVzJiZ0xrMEhzTnpRQkN2NjQ2YzkwU2d3cGZvCmxLTEJPNFE0QUdsaFFQUmxNQUNPMFRFQ0F3RUFBYU0xTURNd0RnWURWUjBQQVFIL0JBUURBZ0NnTUJNR0ExVWQKSlFRTU1Bb0dDQ3NHQVFVRkJ3TURNQXdHQTFVZEV3RUIvd1FDTUFBd0N3WUpLb1pJaHZjTkFRRUxBNElDQVFCbQo4QWU2RWw5WHlNWHlyRzN0Vkd3clZBZWFYUkNiTFllNDh2b3d1QTA2Ykx1VTh0L0dXcVBRMHhZVFBtRzdsdS9qCjJNalVIeXphZ2hpVUNOdWFvNDhDbGwyemJEajlHZkMvQWJKQUFybGRHc2lReWMwbDY1QUJJaHo5aml1dXlXQ0YKMnBsWFc4RCtldlQxSm5RanRiUXB4c2Q0Um1UOC9NRjVnK29mN0RJU0dGekFIQkNicFFjbTJWRytIZ3NSOEFGcgp6VTg4YU1uakJSNm9CN0IvU0tuaytHNDFrczZLWVJqcmNCS2tBMjlIYUVNUVk5eVNEN2pYUmdJb1pqY2FMR3hlCjAyYldnZTJ2d2hGRkZoYVhaZCtDSWFVWXhvcEVBM3ZCUzlTS1N3UFNQNEpuWDFCZU1KRS8zWElIUVFXdFZuREoKL05YbnFxUTJCNkF1azhMZGRsREpQSDRiNnpZMmdzNmVvVlFRU2FSdUEyd1Q2bkY4WHVIa2dEcUttQ2E4WHVMTgo5bFV0Y0dBeHc0WitUVXlSK2lyRVQwWk14TkNwU01zcUJieGtwU29DaFd2ekgyQTMrMklmSXhielNxWnZoaVF3Ck5zVlpSZTVWNVBSQlE4TVZ3L0FBUE96V0hzWjJCZEw4UXNFQ3Y5dDBlWWxEb3BwMlp5K3RSMkM1SDFQYTg4Y0kKbFFycEs4NGlhVnRYN1ZLek1nZ3hJK0ZsczZaRVR6WnlnT1dvZ0JKMUp5MnJsZ0Z6eFFRYks5S2dCWnl4RnkvZQp3VEVDdW1SSExPN0RucmR2ZU1LY1ZnVTlsaGViQ2ZaNlZiWERUSWFYcGZXYVZSYmpnS1ZwanJSdnZPZTZHVUsyClN3S005dG4wcGRIM09iczV3RzlSZ3pTUkxSUFByMU9TalhTSTI1UGlpUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K","private":null}}` +const baseECDSAKey = ` +{"keytype":"{{.KeyType}}","keyval":{"public":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgl3rzMPMEKhS1k/AX16MM4PdidpjJr+z4pj0Td+30QnpbOIARgpyR1PiFztU8BZlqG3cUazvFclr2q/xHvfrqw==","private":"MHcCAQEEIDqtcdzU7H3AbIPSQaxHl9+xYECt7NpK7B1+6ep5cv9CoAoGCCqGSM49AwEHoUQDQgAEgl3rzMPMEKhS1k/AX16MM4PdidpjJr+z4pj0Td+30QnpbOIARgpyR1PiFztU8BZlqG3cUazvFclr2q/xHvfrqw=="}}` +const baseECDSAx509Key = `{"keytype":"ecdsa-x509","keyval":{"public":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJwRENDQVVtZ0F3SUJBZ0lRQlBWc1NoUmRMdG45WEtRZ29JaDIvREFLQmdncWhrak9QUVFEQWpBNE1Sb3cKR0FZRFZRUUtFeEZrYjJOclpYSXVZMjl0TDI1dmRHRnllVEVhTUJnR0ExVUVBeE1SWkc5amEyVnlMbU52YlM5dQpiM1JoY25rd0hoY05NVFV3TnpFek1EVXdORFF4V2hjTk1UY3dOekV5TURVd05EUXhXakE0TVJvd0dBWURWUVFLCkV4RmtiMk5yWlhJdVkyOXRMMjV2ZEdGeWVURWFNQmdHQTFVRUF4TVJaRzlqYTJWeUxtTnZiUzl1YjNSaGNua3cKV1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVI3SjNSOGpWODV5Rnp0dGFTV3FMRDFHa042UHlhWAowUUdmOHh2Rzd6MUYwUG5DQUdSWk9QQ01aWWpZSGVkdzNXY0FmQWVVcDY5OVExSjNEYW9kbzNBcm96VXdNekFPCkJnTlZIUThCQWY4RUJBTUNBS0F3RXdZRFZSMGxCQXd3Q2dZSUt3WUJCUVVIQXdNd0RBWURWUjBUQVFIL0JBSXcKQURBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQWppVkJjaTBDRTBaazgwZ2ZqbytYdE9xM3NURGJkSWJRRTZBTQpoL29mN1RFQ0lRRGxlbXB5MDRhY0RKODNnVHBvaFNtcFJYdjdJbnRLc0lRTU1oLy9VZzliU2c9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==","private":null}}` + +func TestRSAVerifier(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}) + + json.Unmarshal(jsonKey.Bytes(), &testRSAKey) + + // Sign some data using RSAPSS + message := []byte("test data for signing") + hash := crypto.SHA256 + hashed := sha256.Sum256(message) + signedData, err := rsaSign(&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 TestRSAx509Verifier(t *testing.T) { + // Unmarshal our private RSA Key + var testRSAKey data.PublicKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseRSAx509Key) + templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAx509Key}) + + json.Unmarshal(jsonKey.Bytes(), &testRSAKey) + + // Valid signed message + signedData, _ := hex.DecodeString("9a196a3458e0a9077772c1b3cf6f1605ac69576711d55a89ba390d68723a135aa851cf7a574074ae35fa5c22b0f8e28d31ab05ef66c96456707be2bfa3487edd4531996593bd3f0dd2a6d2034bf4adc1828f5502240a1c4a70506e2b218419d2498487725c22917455617c659087de2a6cb73023bd40dfa868c7e70f1e22e86a4c588f97294f0da1ba537c20a6f06692c6de34c305d3be0bfbeaabb712531d9b52e3118f252c87b27467587b457ae906f73183bec68ae2b56fda41757193b0b7f97fe27cf9efb6be101cad2edd014f5862df6b8fdcd939504f846624349bc480ef3b074b69d5096796c480bf8c6e41b95c2aefa54c6c34d22742c93e82e6dd42080a8d9841057130306f194b07b60c9cb54e5a16b1755f5a1180ab86c2bb244f17c9ccc9c326debacc35dc14a4d8226d75e7cd40b9843e7eacc138d59406d1a5e5f907c8bea588346441f2c464f74e18a0c063bd3ee27ec475929929dd248bcb2972812dc7ce3ab1513bc445f00a43fb98321cae75da6bf8f07ac4f26dd782db57338aa97350814eea55f160ba5c6c893d064edaf8f31d98d2fb544f0b54b5b4e30786dca9f8ef8ea4fa3d1a07335ae2a252079f1ffcadc8f9c53b8c8e32e0e4f9677ef781dba894a49442008d209d3a9b89a03f1ecb191fb1e56f4b894e2c073fe41d41d06a8261804e7321feb095d6da97b4c41aee4180718ee0d9bd964a4e") + 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 TestRSAVerifierWithInvalidKeyType(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"}) + + json.Unmarshal(jsonKey.Bytes(), &testRSAKey) + + // 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 TestRSAVerifierWithInvalidKey(t *testing.T) { + var testRSAKey data.PrivateKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseECDSAKey) + templ.Execute(&jsonKey, KeyTemplate{KeyType: "ecdsa"}) + + json.Unmarshal(jsonKey.Bytes(), &testRSAKey) + + // 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: ecdsa") +} + +func TestRSAVerifierWithInvalidSignature(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}) + + json.Unmarshal(jsonKey.Bytes(), &testRSAKey) + + // Sign some data using RSAPSS + message := []byte("test data for signing") + hash := crypto.SHA256 + hashed := sha256.Sum256(message) + signedData, err := rsaSign(&testRSAKey, hash, hashed[:]) + assert.NoError(t, err) + + // Modify the signature + signedData[0] = []byte("a")[0] + + // Create and call Verify on the verifier + rsaVerifier := RSAPSSVerifier{} + err = rsaVerifier.Verify(&testRSAKey, signedData, message) + assert.Error(t, err, "signature verification failed") +} + +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}) + + json.Unmarshal(jsonKey.Bytes(), &testECDSAKey) + + // 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 TestECDSAx509Verifier(t *testing.T) { + var testECDSAKey data.PrivateKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseECDSAx509Key) + templ.Execute(&jsonKey, KeyTemplate{KeyType: data.ECDSAx509Key}) + + json.Unmarshal(jsonKey.Bytes(), &testECDSAKey) + + // Valid signature for message + signedData, _ := hex.DecodeString("b82e0ed5c5dddd74c8d3602bfd900c423511697c3cfe54e1d56b9c1df599695c53aa0caafcdc40df3ef496d78ccf67750ba9413f1ccbd8b0ef137f0da1ee9889") + message := []byte("test data for signing") + + // 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 and an x509 encoded key") +} + +func TestECDSAVerifierWithInvalidKeyType(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: "ecdsa-invalid"}) + + json.Unmarshal(jsonKey.Bytes(), &testECDSAKey) + + // 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: ecdsa-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"}) + + json.Unmarshal(jsonKey.Bytes(), &testECDSAKey) + + // 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 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}) + + json.Unmarshal(jsonKey.Bytes(), &testECDSAKey) + + // 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] = []byte("a")[0] + + // Create and call Verify on the verifier + ecdsaVerifier := ECDSAVerifier{} + err = ecdsaVerifier.Verify(&testECDSAKey, signedData, message) + assert.Error(t, err, "signature verification failed") } + +func rsaSign(privKey *data.PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) { + if privKey.Cipher() != data.RSAKey { + return nil, fmt.Errorf("private key type not supported: %s", privKey.Cipher()) + } + + // Create an rsa.PrivateKey out of the private key bytes + rsaPrivKey, err := x509.ParsePKCS1PrivateKey(privKey.Private()) + if err != nil { + return nil, err + } + + // Use the RSA key to RSASSA-PSS sign the data + sig, err := rsa.SignPSS(rand.Reader, rsaPrivKey, hash, hashed[:], &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash}) + if err != nil { + return nil, err + } + + return sig, nil +} + +func ecdsaSign(privKey *data.PrivateKey, hashed []byte) ([]byte, error) { + if privKey.Cipher() != data.ECDSAKey { + return nil, fmt.Errorf("private key type not supported: %s", privKey.Cipher()) + } + + // Create an ecdsa.PrivateKey out of the private key bytes + ecdsaPrivKey, err := x509.ParseECPrivateKey(privKey.Private()) + if err != nil { + return nil, err + } + + // Use the ECDSA key to sign the data + r, s, err := ecdsa.Sign(rand.Reader, ecdsaPrivKey, hashed[:]) + if err != nil { + return nil, err + } + + rBytes, sBytes := r.Bytes(), s.Bytes() + octetLength := (ecdsaPrivKey.Params().BitSize + 7) >> 3 + + // MUST include leading zeros in the output + rBuf := make([]byte, octetLength-len(rBytes), octetLength) + sBuf := make([]byte, octetLength-len(sBytes), octetLength) + + rBuf = append(rBuf, rBytes...) + sBuf = append(sBuf, sBytes...) + + return append(rBuf, sBuf...), nil +} diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verify.go b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verify.go index bdc3bb89d5..1767e3e62f 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verify.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verify.go @@ -49,7 +49,7 @@ func VerifyRoot(s *data.Signed, minVersion int, keys map[string]*data.PublicKey, method := strings.ToLower(sig.Method) verifier, ok := Verifiers[method] if !ok { - logrus.Debugf("continuing b/c signing method is not supported: %s\n", sig.Method) + logrus.Debugf("continuing b/c signing method is not supported for verify root: %s\n", sig.Method) continue } @@ -78,11 +78,6 @@ func verifyMeta(s *data.Signed, role string, minVersion int) error { if err := json.Unmarshal(s.Signed, sm); err != nil { return err } - // This is not the valid way to check types as all targets files will - // have the "Targets" type. - //if strings.ToLower(sm.Type) != strings.ToLower(role) { - // return ErrWrongType - //} if !data.ValidTUFType(sm.Type) { return ErrWrongType } diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/tuf.go b/Godeps/_workspace/src/github.com/endophage/gotuf/tuf.go index ce5c7f036f..eb9410e830 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/tuf.go +++ b/Godeps/_workspace/src/github.com/endophage/gotuf/tuf.go @@ -260,9 +260,8 @@ func (tr *TufRepo) SetRoot(s *data.Signed) error { if err != nil { return err } - for kid, key := range r.Signed.Keys { + for _, key := range r.Signed.Keys { tr.keysDB.AddKey(key) - logrus.Debug("Given Key ID:", kid, "\nGenerated Key ID:", key.ID()) } for roleName, role := range r.Signed.Roles { baseRole, err := data.NewRole( @@ -451,7 +450,7 @@ func (tr *TufRepo) UpdateTimestamp(s *data.Signed) error { } func (tr *TufRepo) SignRoot(expires time.Time, signer *signed.Signer) (*data.Signed, error) { - logrus.Debug("SignRoot") + logrus.Debug("signing root...") if tr.Root.Dirty { tr.Root.Signed.Version++ } @@ -469,8 +468,7 @@ func (tr *TufRepo) SignRoot(expires time.Time, signer *signed.Signer) (*data.Sig } func (tr *TufRepo) SignTargets(role string, expires time.Time, signer *signed.Signer) (*data.Signed, error) { - logrus.Debug("SignTargets") - logrus.Debug("Got targets data.Signed object") + logrus.Debugf("sign targets called for role %s", role) if tr.Targets[role].Dirty { tr.Targets[role].Signed.Version++ signed, err := tr.Targets[role].ToSigned() @@ -479,13 +477,11 @@ func (tr *TufRepo) SignTargets(role string, expires time.Time, signer *signed.Si return nil, err } targets := tr.keysDB.GetRole(role) - logrus.Debug("About to sign ", role) signed, err = tr.sign(signed, *targets, signer) if err != nil { logrus.Debug("errored signing ", role) return nil, err } - logrus.Debug("success signing ", role) tr.Targets[role].Signatures = signed.Signatures return signed, nil } else { @@ -499,7 +495,7 @@ func (tr *TufRepo) SignTargets(role string, expires time.Time, signer *signed.Si } func (tr *TufRepo) SignSnapshot(expires time.Time, signer *signed.Signer) (*data.Signed, error) { - logrus.Debug("SignSnapshot") + logrus.Debug("signing snapshot...") if tr.Root.Dirty { signedRoot, err := tr.SignRoot(data.DefaultExpires("root"), signer) if err != nil {