Repository: docker/notary
Pull request #229 (2015-10-19 20:14:32)

Factor out TLS configuration code for server and TLS
So that mutual authentication can be supported between notary-server and notary-signer as well as notary and notary-server.


Patch:
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index d2d04a5c..33090266 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -96,7 +96,7 @@
 		},
 		{
 			"ImportPath": "github.com/endophage/gotuf",
-			"Rev": "e1345f72687ad0443c25b3c58d4502c717c4936a"
+			"Rev": "876c31a61bc4aa0dae09bb8ef3946dc26dd04924"
 		},
 		{
 			"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 71f5992d..e887dea5 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/Godeps/Godeps.json
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/Godeps/Godeps.json
@@ -1,6 +1,6 @@
 {
 	"ImportPath": "github.com/endophage/gotuf",
-	"GoVersion": "go1.5.1",
+	"GoVersion": "go1.4.2",
 	"Packages": [
 		"./..."
 	],
@@ -14,21 +14,6 @@
 			"ImportPath": "github.com/agl/ed25519",
 			"Rev": "d2b94fd789ea21d12fac1a4443dd3a3f79cda72c"
 		},
-		{
-			"ImportPath": "github.com/docker/docker/pkg/term",
-			"Comment": "v1.7.1",
-			"Rev": "786b29d4db80a6175e72b47a794ee044918ba734"
-		},
-		{
-			"ImportPath": "github.com/docker/notary/pkg/passphrase",
-			"Comment": "docker-v1.8.0-rc1-229-ge646033",
-			"Rev": "e6460330bdbef7d9a7a9a3dc51df2be83861c1b0"
-		},
-		{
-			"ImportPath": "github.com/docker/notary/trustmanager",
-			"Comment": "docker-v1.8.0-rc1-229-ge646033",
-			"Rev": "e6460330bdbef7d9a7a9a3dc51df2be83861c1b0"
-		},
 		{
 			"ImportPath": "github.com/google/gofuzz",
 			"Rev": "bbcb9da2d746f8bdbd6a936686a0a6067ada0ec5"
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/client/client.go b/Godeps/_workspace/src/github.com/endophage/gotuf/client/client.go
index 5ed1b653..532e4747 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/client/client.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/client/client.go
@@ -22,16 +22,14 @@ import (
 
 const maxSize int64 = 5 << 20
 
-// Client is a usability wrapper around a raw TUF repo
 type Client struct {
-	local  *tuf.Repo
+	local  *tuf.TufRepo
 	remote store.RemoteStore
 	keysDB *keys.KeyDB
 	cache  store.MetadataStore
 }
 
-// NewClient initialized a Client with the given repo, remote source of content, key database, and cache
-func NewClient(local *tuf.Repo, remote store.RemoteStore, keysDB *keys.KeyDB, cache store.MetadataStore) *Client {
+func NewClient(local *tuf.TufRepo, remote store.RemoteStore, keysDB *keys.KeyDB, cache store.MetadataStore) *Client {
 	return &Client{
 		local:  local,
 		remote: remote,
@@ -40,7 +38,6 @@ func NewClient(local *tuf.Repo, remote store.RemoteStore, keysDB *keys.KeyDB, ca
 	}
 }
 
-// Update performs an update to the TUF repo as defined by the TUF spec
 func (c *Client) Update() error {
 	// 1. Get timestamp
 	//   a. If timestamp error (verification, expired, etc...) download new root and return to 1.
@@ -55,7 +52,7 @@ func (c *Client) Update() error {
 	if err != nil {
 		logrus.Debug("Error occurred. Root will be downloaded and another update attempted")
 		if err := c.downloadRoot(); err != nil {
-			logrus.Error("client Update (Root):", err)
+			logrus.Errorf("client Update (Root):", err)
 			return err
 		}
 		// If we error again, we now have the latest root and just want to fail
@@ -132,7 +129,7 @@ func (c Client) checkRoot() error {
 func (c *Client) downloadRoot() error {
 	role := data.RoleName("root")
 	size := maxSize
-	var expectedSha256 []byte
+	var expectedSha256 []byte = nil
 	if c.local.Snapshot != nil {
 		size = c.local.Snapshot.Signed.Meta[role].Length
 		expectedSha256 = c.local.Snapshot.Signed.Meta[role].Hashes["sha256"]
@@ -143,7 +140,7 @@ func (c *Client) downloadRoot() error {
 	// interpreted as 0.
 	var download bool
 	var err error
-	var cachedRoot []byte
+	var cachedRoot []byte = nil
 	old := &data.Signed{}
 	version := 0
 
@@ -264,7 +261,8 @@ func (c *Client) downloadTimestamp() error {
 	}
 	// unlike root, targets and snapshot, always try and download timestamps
 	// from remote, only using the cache one if we couldn't reach remote.
-	raw, s, err := c.downloadSigned(role, maxSize, nil)
+	raw, err := c.remote.GetMeta(role, maxSize)
+	var s *data.Signed
 	if err != nil || len(raw) == 0 {
 		if err, ok := err.(store.ErrMetaNotFound); ok {
 			return err
@@ -281,6 +279,11 @@ func (c *Client) downloadTimestamp() error {
 		s = old
 	} else {
 		download = true
+		s = &data.Signed{}
+		err = json.Unmarshal(raw, s)
+		if err != nil {
+			return err
+		}
 	}
 	err = signed.Verify(s, role, version, c.keysDB)
 	if err != nil {
@@ -302,13 +305,10 @@ func (c *Client) downloadTimestamp() error {
 func (c *Client) downloadSnapshot() error {
 	logrus.Debug("downloadSnapshot")
 	role := data.RoleName("snapshot")
-	if c.local.Timestamp == nil {
-		return ErrMissingMeta{role: "snapshot"}
-	}
 	size := c.local.Timestamp.Signed.Meta[role].Length
 	expectedSha256, ok := c.local.Timestamp.Signed.Meta[role].Hashes["sha256"]
 	if !ok {
-		return ErrMissingMeta{role: "snapshot"}
+		return fmt.Errorf("Sha256 is currently the only hash supported by this client. No Sha256 found for snapshot")
 	}
 
 	var download bool
@@ -373,9 +373,6 @@ func (c *Client) downloadSnapshot() error {
 // including delegates roles.
 func (c *Client) downloadTargets(role string) error {
 	role = data.RoleName(role) // this will really only do something for base targets role
-	if c.local.Snapshot == nil {
-		return ErrMissingMeta{role: role}
-	}
 	snap := c.local.Snapshot.Signed
 	root := c.local.Root.Signed
 	r := c.keysDB.GetRole(role)
@@ -383,7 +380,7 @@ func (c *Client) downloadTargets(role string) error {
 		return fmt.Errorf("Invalid role: %s", role)
 	}
 	keyIDs := r.KeyIDs
-	s, err := c.getTargetsFile(role, keyIDs, snap.Meta, root.ConsistentSnapshot, r.Threshold)
+	s, err := c.GetTargetsFile(role, keyIDs, snap.Meta, root.ConsistentSnapshot, r.Threshold)
 	if err != nil {
 		logrus.Error("Error getting targets file:", err)
 		return err
@@ -401,12 +398,13 @@ func (c *Client) downloadTargets(role string) error {
 }
 
 func (c *Client) downloadSigned(role string, size int64, expectedSha256 []byte) ([]byte, *data.Signed, error) {
+	logrus.Debugf("downloading new %s", role)
 	raw, err := c.remote.GetMeta(role, size)
 	if err != nil {
 		return nil, nil, err
 	}
 	genHash := sha256.Sum256(raw)
-	if expectedSha256 != nil && !bytes.Equal(genHash[:], expectedSha256) {
+	if !bytes.Equal(genHash[:], expectedSha256) {
 		return nil, nil, ErrChecksumMismatch{role: role}
 	}
 	s := &data.Signed{}
@@ -417,15 +415,15 @@ func (c *Client) downloadSigned(role string, size int64, expectedSha256 []byte)
 	return raw, s, nil
 }
 
-func (c Client) getTargetsFile(role string, keyIDs []string, snapshotMeta data.Files, consistent bool, threshold int) (*data.Signed, error) {
+func (c Client) GetTargetsFile(role string, keyIDs []string, snapshotMeta data.Files, consistent bool, threshold int) (*data.Signed, error) {
 	// require role exists in snapshots
 	roleMeta, ok := snapshotMeta[role]
 	if !ok {
-		return nil, ErrMissingMeta{role: role}
+		return nil, fmt.Errorf("Snapshot does not contain target role")
 	}
 	expectedSha256, ok := snapshotMeta[role].Hashes["sha256"]
 	if !ok {
-		return nil, ErrMissingMeta{role: role}
+		return nil, fmt.Errorf("Sha256 is currently the only hash supported by this client. No Sha256 found for targets role %s", role)
 	}
 
 	// try to get meta file from content addressed cache
@@ -541,7 +539,6 @@ func (c Client) TargetMeta(path string) (*data.FileMeta, error) {
 	return meta, nil
 }
 
-// DownloadTarget downloads the target to dst from the remote
 func (c Client) DownloadTarget(dst io.Writer, path string, meta *data.FileMeta) error {
 	reader, err := c.remote.GetTarget(path)
 	if err != nil {
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/client/errors.go b/Godeps/_workspace/src/github.com/endophage/gotuf/client/errors.go
index 0fb1a8d0..311e74a8 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/client/errors.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/client/errors.go
@@ -5,13 +5,11 @@ import (
 	"fmt"
 )
 
-// Simple client errors
 var (
 	ErrNoRootKeys       = errors.New("tuf: no root keys found in local meta store")
 	ErrInsufficientKeys = errors.New("tuf: insufficient keys to meet threshold")
 )
 
-// ErrChecksumMismatch - a checksum failed verification
 type ErrChecksumMismatch struct {
 	role string
 }
@@ -20,16 +18,6 @@ func (e ErrChecksumMismatch) Error() string {
 	return fmt.Sprintf("tuf: checksum for %s did not match", e.role)
 }
 
-// ErrMissingMeta - couldn't find the FileMeta object for a role or target
-type ErrMissingMeta struct {
-	role string
-}
-
-func (e ErrMissingMeta) Error() string {
-	return fmt.Sprintf("tuf: sha256 checksum required for %s", e.role)
-}
-
-// ErrMissingRemoteMetadata - remote didn't have requested metadata
 type ErrMissingRemoteMetadata struct {
 	Name string
 }
@@ -38,7 +26,6 @@ func (e ErrMissingRemoteMetadata) Error() string {
 	return fmt.Sprintf("tuf: missing remote metadata %s", e.Name)
 }
 
-// ErrDownloadFailed - a download failed
 type ErrDownloadFailed struct {
 	File string
 	Err  error
@@ -48,7 +35,6 @@ func (e ErrDownloadFailed) Error() string {
 	return fmt.Sprintf("tuf: failed to download %s: %s", e.File, e.Err)
 }
 
-// ErrDecodeFailed - couldn't parse a download
 type ErrDecodeFailed struct {
 	File string
 	Err  error
@@ -66,7 +52,6 @@ func isDecodeFailedWithErr(err, expected error) bool {
 	return e.Err == expected
 }
 
-// ErrNotFound - didn't find a file
 type ErrNotFound struct {
 	File string
 }
@@ -75,13 +60,11 @@ func (e ErrNotFound) Error() string {
 	return fmt.Sprintf("tuf: file not found: %s", e.File)
 }
 
-// IsNotFound - check if an error is an ErrNotFound type
 func IsNotFound(err error) bool {
 	_, ok := err.(ErrNotFound)
 	return ok
 }
 
-// ErrWrongSize - the size is wrong
 type ErrWrongSize struct {
 	File     string
 	Actual   int64
@@ -92,7 +75,44 @@ func (e ErrWrongSize) Error() string {
 	return fmt.Sprintf("tuf: unexpected file size: %s (expected %d bytes, got %d bytes)", e.File, e.Expected, e.Actual)
 }
 
-// ErrCorruptedCache - local data is incorrect
+type ErrLatestSnapshot struct {
+	Version int
+}
+
+func (e ErrLatestSnapshot) Error() string {
+	return fmt.Sprintf("tuf: the local snapshot version (%d) is the latest", e.Version)
+}
+
+func IsLatestSnapshot(err error) bool {
+	_, ok := err.(ErrLatestSnapshot)
+	return ok
+}
+
+type ErrUnknownTarget struct {
+	Name string
+}
+
+func (e ErrUnknownTarget) Error() string {
+	return fmt.Sprintf("tuf: unknown target file: %s", e.Name)
+}
+
+type ErrMetaTooLarge struct {
+	Name string
+	Size int64
+}
+
+func (e ErrMetaTooLarge) Error() string {
+	return fmt.Sprintf("tuf: %s size %d bytes greater than maximum", e.Name, e.Size)
+}
+
+type ErrInvalidURL struct {
+	URL string
+}
+
+func (e ErrInvalidURL) Error() string {
+	return fmt.Sprintf("tuf: invalid repository URL %s", e.URL)
+}
+
 type ErrCorruptedCache struct {
 	file string
 }
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 d3989b67..eccccc42 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/data/keys.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/data/keys.go
@@ -8,27 +8,22 @@ import (
 	"github.com/jfrazelle/go/canonical/json"
 )
 
-// Key is the minimal interface for a public key. It is declared
-// independently of PublicKey for composability.
 type Key interface {
 	ID() string
 	Algorithm() KeyAlgorithm
 	Public() []byte
 }
 
-// PublicKey is the necessary interface for public keys
 type PublicKey interface {
 	Key
 }
 
-// PrivateKey adds the ability to access the private key
 type PrivateKey interface {
 	Key
 
 	Private() []byte
 }
 
-// KeyPair holds the public and private key bytes
 type KeyPair struct {
 	Public  []byte `json:"public"`
 	Private []byte `json:"private"`
@@ -40,13 +35,11 @@ type KeyPair struct {
 // JSON would be different). This structure should normally be accessed through
 // the PublicKey or PrivateKey interfaces.
 type TUFKey struct {
-	id    string
+	id    string       `json:"-"`
 	Type  KeyAlgorithm `json:"keytype"`
 	Value KeyPair      `json:"keyval"`
 }
 
-// NewPrivateKey instantiates a new TUFKey with the private key component
-// populated
 func NewPrivateKey(algorithm KeyAlgorithm, public, private []byte) *TUFKey {
 	return &TUFKey{
 		Type: algorithm,
@@ -57,12 +50,10 @@ func NewPrivateKey(algorithm KeyAlgorithm, public, private []byte) *TUFKey {
 	}
 }
 
-// Algorithm returns the algorithm of the key
 func (k TUFKey) Algorithm() KeyAlgorithm {
 	return k.Type
 }
 
-// ID efficiently generates if necessary, and caches the ID of the key
 func (k *TUFKey) ID() string {
 	if k.id == "" {
 		pubK := NewPublicKey(k.Algorithm(), k.Public())
@@ -76,18 +67,14 @@ func (k *TUFKey) ID() string {
 	return k.id
 }
 
-// Public returns the public bytes
 func (k TUFKey) Public() []byte {
 	return k.Value.Public
 }
 
-// Private returns the private bytes
 func (k TUFKey) Private() []byte {
 	return k.Value.Private
 }
 
-// NewPublicKey instantiates a new TUFKey where the private bytes are
-// guaranteed to be nil
 func NewPublicKey(algorithm KeyAlgorithm, public []byte) PublicKey {
 	return &TUFKey{
 		Type: algorithm,
@@ -98,8 +85,6 @@ func NewPublicKey(algorithm KeyAlgorithm, public []byte) PublicKey {
 	}
 }
 
-// PublicKeyFromPrivate returns a new TUFKey based on a private key, with
-// the private key bytes guaranteed to be nil.
 func PublicKeyFromPrivate(pk PrivateKey) PublicKey {
 	return &TUFKey{
 		Type: pk.Algorithm(),
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/data/roles.go b/Godeps/_workspace/src/github.com/endophage/gotuf/data/roles.go
index 12b76b23..1034393e 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/data/roles.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/data/roles.go
@@ -15,10 +15,6 @@ const (
 	CanonicalTimestampRole = "timestamp"
 )
 
-// ValidRoles holds an overrideable mapping of canonical role names
-// to any custom roles names a user wants to make use of. This allows
-// us to be internally consistent while using different roles in the
-// public TUF files.
 var ValidRoles = map[string]string{
 	CanonicalRootRole:      CanonicalRootRole,
 	CanonicalTargetsRole:   CanonicalTargetsRole,
@@ -26,7 +22,6 @@ var ValidRoles = map[string]string{
 	CanonicalTimestampRole: CanonicalTimestampRole,
 }
 
-// SetValidRoles is a utility function to override some or all of the roles
 func SetValidRoles(rs map[string]string) {
 	// iterate ValidRoles
 	for k := range ValidRoles {
@@ -36,17 +31,13 @@ func SetValidRoles(rs map[string]string) {
 	}
 }
 
-// RoleName returns the (possibly overridden) role name for the provided
-// canonical role name
-func RoleName(canonicalRole string) string {
-	if r, ok := ValidRoles[canonicalRole]; ok {
+func RoleName(role string) string {
+	if r, ok := ValidRoles[role]; ok {
 		return r
 	}
-	return canonicalRole
+	return role
 }
 
-// CanonicalRole does a reverse lookup to get the canonical role name
-// from the (possibly overridden) role name
 func CanonicalRole(role string) string {
 	name := strings.ToLower(role)
 	if _, ok := ValidRoles[name]; ok {
@@ -88,13 +79,10 @@ func ValidRole(name string) bool {
 	return false
 }
 
-// RootRole is a cut down role as it appears in the root.json
 type RootRole struct {
 	KeyIDs    []string `json:"keyids"`
 	Threshold int      `json:"threshold"`
 }
-
-// Role is a more verbose role as they appear in targets delegations
 type Role struct {
 	RootRole
 	Name             string   `json:"name"`
@@ -103,7 +91,6 @@ type Role struct {
 	Email            string   `json:"email,omitempty"`
 }
 
-// NewRole creates a new Role object from the given parameters
 func NewRole(name string, threshold int, keyIDs, paths, pathHashPrefixes []string) (*Role, error) {
 	if len(paths) > 0 && len(pathHashPrefixes) > 0 {
 		return nil, errors.ErrInvalidRole{}
@@ -126,13 +113,10 @@ func NewRole(name string, threshold int, keyIDs, paths, pathHashPrefixes []strin
 
 }
 
-// IsValid checks if the role has defined both paths and path hash prefixes,
-// having both is invalid
 func (r Role) IsValid() bool {
 	return !(len(r.Paths) > 0 && len(r.PathHashPrefixes) > 0)
 }
 
-// ValidKey checks if the given id is a recognized signing key for the role
 func (r Role) ValidKey(id string) bool {
 	for _, key := range r.KeyIDs {
 		if key == id {
@@ -142,7 +126,6 @@ func (r Role) ValidKey(id string) bool {
 	return false
 }
 
-// CheckPaths checks if a given path is valid for the role
 func (r Role) CheckPaths(path string) bool {
 	for _, p := range r.Paths {
 		if strings.HasPrefix(path, p) {
@@ -152,7 +135,6 @@ func (r Role) CheckPaths(path string) bool {
 	return false
 }
 
-// CheckPrefixes checks if a given hash matches the prefixes for the role
 func (r Role) CheckPrefixes(hash string) bool {
 	for _, p := range r.PathHashPrefixes {
 		if strings.HasPrefix(hash, p) {
@@ -162,7 +144,6 @@ func (r Role) CheckPrefixes(hash string) bool {
 	return false
 }
 
-// IsDelegation checks if the role is a delegation or a root role
 func (r Role) IsDelegation() bool {
 	targetsBase := fmt.Sprintf("%s/", ValidRoles[CanonicalTargetsRole])
 	return strings.HasPrefix(r.Name, targetsBase)
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/data/root.go b/Godeps/_workspace/src/github.com/endophage/gotuf/data/root.go
index 69b92e8e..5730e9bf 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/data/root.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/data/root.go
@@ -6,14 +6,12 @@ import (
 	"github.com/jfrazelle/go/canonical/json"
 )
 
-// SignedRoot is a fully unpacked root.json
 type SignedRoot struct {
 	Signatures []Signature
 	Signed     Root
 	Dirty      bool
 }
 
-// Root is the Signed component of a root.json
 type Root struct {
 	Type    string    `json:"_type"`
 	Version int       `json:"version"`
@@ -25,7 +23,6 @@ type Root struct {
 	ConsistentSnapshot bool                 `json:"consistent_snapshot"`
 }
 
-// NewRoot initializes a new SignedRoot with a set of keys, roles, and the consistent flag
 func NewRoot(keys map[string]PublicKey, roles map[string]*RootRole, consistent bool) (*SignedRoot, error) {
 	signedRoot := &SignedRoot{
 		Signatures: make([]Signature, 0),
@@ -59,7 +56,6 @@ func NewRoot(keys map[string]PublicKey, roles map[string]*RootRole, consistent b
 	return signedRoot, nil
 }
 
-// ToSigned partially serializes a SignedRoot for further signing
 func (r SignedRoot) ToSigned() (*Signed, error) {
 	s, err := json.MarshalCanonical(r.Signed)
 	if err != nil {
@@ -78,7 +74,6 @@ func (r SignedRoot) ToSigned() (*Signed, error) {
 	}, nil
 }
 
-// RootFromSigned fully unpacks a Signed object into a SignedRoot
 func RootFromSigned(s *Signed) (*SignedRoot, error) {
 	r := Root{}
 	err := json.Unmarshal(s.Signed, &r)
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 d242a761..5b61e46f 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/data/snapshot.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/data/snapshot.go
@@ -8,14 +8,12 @@ import (
 	"github.com/jfrazelle/go/canonical/json"
 )
 
-// SignedSnapshot is a fully unpacked snapshot.json
 type SignedSnapshot struct {
 	Signatures []Signature
 	Signed     Snapshot
 	Dirty      bool
 }
 
-// Snapshot is the Signed component of a snapshot.json
 type Snapshot struct {
 	Type    string    `json:"_type"`
 	Version int       `json:"version"`
@@ -23,8 +21,6 @@ type Snapshot struct {
 	Meta    Files     `json:"meta"`
 }
 
-// NewSnapshot initilizes a SignedSnapshot with a given top level root
-// and targets objects
 func NewSnapshot(root *Signed, targets *Signed) (*SignedSnapshot, error) {
 	logrus.Debug("generating new snapshot...")
 	targetsJSON, err := json.Marshal(targets)
@@ -63,7 +59,6 @@ func (sp *SignedSnapshot) hashForRole(role string) []byte {
 	return sp.Signed.Meta[role].Hashes["sha256"]
 }
 
-// ToSigned partially serializes a SignedSnapshot for further signing
 func (sp SignedSnapshot) ToSigned() (*Signed, error) {
 	s, err := json.MarshalCanonical(sp.Signed)
 	if err != nil {
@@ -82,13 +77,11 @@ func (sp SignedSnapshot) ToSigned() (*Signed, error) {
 	}, nil
 }
 
-// AddMeta updates a role in the snapshot with new meta
 func (sp *SignedSnapshot) AddMeta(role string, meta FileMeta) {
 	sp.Signed.Meta[role] = meta
 	sp.Dirty = true
 }
 
-// SnapshotFromSigned fully unpacks a Signed object into a SignedSnapshot
 func SnapshotFromSigned(s *Signed) (*SignedSnapshot, error) {
 	sp := Snapshot{}
 	err := json.Unmarshal(s.Signed, &sp)
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/data/targets.go b/Godeps/_workspace/src/github.com/endophage/gotuf/data/targets.go
index 776e1b69..a51f60d2 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/data/targets.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/data/targets.go
@@ -7,22 +7,18 @@ import (
 	"github.com/jfrazelle/go/canonical/json"
 )
 
-// SignedTargets is a fully unpacked targets.json, or target delegation
-// json file
 type SignedTargets struct {
 	Signatures []Signature
 	Signed     Targets
 	Dirty      bool
 }
 
-// Targets is the Signed components of a targets.json or delegation json file
 type Targets struct {
 	SignedCommon
 	Targets     Files       `json:"targets"`
 	Delegations Delegations `json:"delegations,omitempty"`
 }
 
-// NewTargets intiializes a new empty SignedTargets object
 func NewTargets() *SignedTargets {
 	return &SignedTargets{
 		Signatures: make([]Signature, 0),
@@ -57,7 +53,7 @@ func (t SignedTargets) GetMeta(path string) *FileMeta {
 // to the role slice on Delegations per TUF spec proposal on using
 // order to determine priority.
 func (t SignedTargets) GetDelegations(path string) []*Role {
-	var roles []*Role
+	roles := make([]*Role, 0)
 	pathHashBytes := sha256.Sum256([]byte(path))
 	pathHash := hex.EncodeToString(pathHashBytes[:])
 	for _, r := range t.Signed.Delegations.Roles {
@@ -78,20 +74,15 @@ func (t SignedTargets) GetDelegations(path string) []*Role {
 	return roles
 }
 
-// AddTarget adds or updates the meta for the given path
 func (t *SignedTargets) AddTarget(path string, meta FileMeta) {
 	t.Signed.Targets[path] = meta
 	t.Dirty = true
 }
 
-// AddDelegation will add a new delegated role with the given keys,
-// ensuring the keys either already exist, or are added to the map
-// of delegation keys
 func (t *SignedTargets) AddDelegation(role *Role, keys []*PublicKey) error {
 	return nil
 }
 
-// ToSigned partially serializes a SignedTargets for further signing
 func (t SignedTargets) ToSigned() (*Signed, error) {
 	s, err := json.MarshalCanonical(t.Signed)
 	if err != nil {
@@ -110,7 +101,6 @@ func (t SignedTargets) ToSigned() (*Signed, error) {
 	}, nil
 }
 
-// TargetsFromSigned fully unpacks a Signed object into a SignedTargets
 func TargetsFromSigned(s *Signed) (*SignedTargets, error) {
 	t := Targets{}
 	err := json.Unmarshal(s.Signed, &t)
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/data/timestamp.go b/Godeps/_workspace/src/github.com/endophage/gotuf/data/timestamp.go
index 912682a2..e8a0de7c 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/data/timestamp.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/data/timestamp.go
@@ -7,14 +7,12 @@ import (
 	"github.com/jfrazelle/go/canonical/json"
 )
 
-// SignedTimestamp is a fully unpacked timestamp.json
 type SignedTimestamp struct {
 	Signatures []Signature
 	Signed     Timestamp
 	Dirty      bool
 }
 
-// Timestamp is the Signed component of a timestamp.json
 type Timestamp struct {
 	Type    string    `json:"_type"`
 	Version int       `json:"version"`
@@ -22,7 +20,6 @@ type Timestamp struct {
 	Meta    Files     `json:"meta"`
 }
 
-// NewTimestamp initializes a timestamp with an existing snapshot
 func NewTimestamp(snapshot *Signed) (*SignedTimestamp, error) {
 	snapshotJSON, err := json.Marshal(snapshot)
 	if err != nil {
@@ -45,8 +42,6 @@ func NewTimestamp(snapshot *Signed) (*SignedTimestamp, error) {
 	}, nil
 }
 
-// ToSigned partially serializes a SignedTimestamp such that it can
-// be signed
 func (ts SignedTimestamp) ToSigned() (*Signed, error) {
 	s, err := json.MarshalCanonical(ts.Signed)
 	if err != nil {
@@ -65,8 +60,6 @@ func (ts SignedTimestamp) ToSigned() (*Signed, error) {
 	}, nil
 }
 
-// TimestampFromSigned parsed a Signed object into a fully unpacked
-// SignedTimestamp
 func TimestampFromSigned(s *Signed) (*SignedTimestamp, error) {
 	ts := Timestamp{}
 	err := json.Unmarshal(s.Signed, &ts)
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 7aaf9fbf..7cc84874 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/data/types.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/data/types.go
@@ -14,33 +14,27 @@ import (
 	"github.com/jfrazelle/go/canonical/json"
 )
 
-// KeyAlgorithm for types of keys
 type KeyAlgorithm string
 
 func (k KeyAlgorithm) String() string {
 	return string(k)
 }
 
-// SigAlgorithm for types of signatures
 type SigAlgorithm string
 
 func (k SigAlgorithm) String() string {
 	return string(k)
 }
 
-const defaultHashAlgorithm = "sha256"
-
-// Signature types
 const (
+	defaultHashAlgorithm = "sha256"
+
 	EDDSASignature       SigAlgorithm = "eddsa"
 	RSAPSSSignature      SigAlgorithm = "rsapss"
 	RSAPKCS1v15Signature SigAlgorithm = "rsapkcs1v15"
 	ECDSASignature       SigAlgorithm = "ecdsa"
 	PyCryptoSignature    SigAlgorithm = "pycrypto-pkcs#1 pss"
-)
 
-// Key types
-const (
 	ED25519Key   KeyAlgorithm = "ed25519"
 	RSAKey       KeyAlgorithm = "rsa"
 	RSAx509Key   KeyAlgorithm = "rsa-x509"
@@ -48,7 +42,6 @@ const (
 	ECDSAx509Key KeyAlgorithm = "ecdsa-x509"
 )
 
-// TUFTypes is the set of metadata types
 var TUFTypes = map[string]string{
 	CanonicalRootRole:      "Root",
 	CanonicalTargetsRole:   "Targets",
@@ -64,7 +57,6 @@ func SetTUFTypes(ts map[string]string) {
 	}
 }
 
-// ValidTUFType checks if the given type is valid for the role
 func ValidTUFType(typ, role string) bool {
 	if ValidRole(role) {
 		// All targets delegation roles must have
@@ -88,54 +80,38 @@ func ValidTUFType(typ, role string) bool {
 	return false
 }
 
-// Signed is the high level, partially deserialized metadata object
-// used to verify signatures before fully unpacking, or to add signatures
-// before fully packing
 type Signed struct {
 	Signed     json.RawMessage `json:"signed"`
 	Signatures []Signature     `json:"signatures"`
 }
 
-// SignedCommon contains the fields common to the Signed component of all
-// TUF metadata files
 type SignedCommon struct {
 	Type    string    `json:"_type"`
 	Expires time.Time `json:"expires"`
 	Version int       `json:"version"`
 }
 
-// SignedMeta is used in server validation where we only need signatures
-// and common fields
 type SignedMeta struct {
 	Signed     SignedCommon `json:"signed"`
 	Signatures []Signature  `json:"signatures"`
 }
 
-// Signature is a signature on a piece of metadata
 type Signature struct {
 	KeyID     string       `json:"keyid"`
 	Method    SigAlgorithm `json:"method"`
 	Signature []byte       `json:"sig"`
 }
 
-// Files is the map of paths to file meta container in targets and delegations
-// metadata files
 type Files map[string]FileMeta
 
-// Hashes is the map of hash type to digest created for each metadata
-// and target file
 type Hashes map[string][]byte
 
-// FileMeta contains the size and hashes for a metadata or target file. Custom
-// data can be optionally added.
 type FileMeta struct {
 	Length int64           `json:"length"`
 	Hashes Hashes          `json:"hashes"`
 	Custom json.RawMessage `json:"custom,omitempty"`
 }
 
-// NewFileMeta generates a FileMeta object from the reader, using the
-// hash algorithms provided
 func NewFileMeta(r io.Reader, hashAlgorithms ...string) (FileMeta, error) {
 	if len(hashAlgorithms) == 0 {
 		hashAlgorithms = []string{defaultHashAlgorithm}
@@ -165,13 +141,11 @@ func NewFileMeta(r io.Reader, hashAlgorithms ...string) (FileMeta, error) {
 	return m, nil
 }
 
-// Delegations holds a tier of targets delegations
 type Delegations struct {
 	Keys  map[string]PublicKey `json:"keys"`
 	Roles []*Role              `json:"roles"`
 }
 
-// NewDelegations initializes an empty Delegations object
 func NewDelegations() *Delegations {
 	return &Delegations{
 		Keys:  make(map[string]PublicKey),
@@ -198,7 +172,6 @@ func SetDefaultExpiryTimes(times map[string]int) {
 	}
 }
 
-// DefaultExpires gets the default expiry time for the given role
 func DefaultExpires(role string) time.Time {
 	var t time.Time
 	if t, ok := defaultExpiryTimes[role]; ok {
@@ -209,7 +182,6 @@ func DefaultExpires(role string) time.Time {
 
 type unmarshalledSignature Signature
 
-// UnmarshalJSON does a custom unmarshalling of the signature JSON
 func (s *Signature) UnmarshalJSON(data []byte) error {
 	uSignature := unmarshalledSignature{}
 	err := json.Unmarshal(data, &uSignature)
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/errors/errors.go b/Godeps/_workspace/src/github.com/endophage/gotuf/errors/errors.go
index 763be52f..b5bb40a7 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/errors/errors.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/errors/errors.go
@@ -6,12 +6,8 @@ import (
 	"time"
 )
 
-// ErrInitNotAllowed - repo has already been initialized
 var ErrInitNotAllowed = errors.New("tuf: repository already initialized")
 
-// ErrMissingMetadata - cannot find the file meta being requested.
-// Specifically, could not find the FileMeta object in the expected
-// location.
 type ErrMissingMetadata struct {
 	Name string
 }
@@ -20,7 +16,6 @@ func (e ErrMissingMetadata) Error() string {
 	return fmt.Sprintf("tuf: missing metadata %s", e.Name)
 }
 
-// ErrFileNotFound - could not find a file
 type ErrFileNotFound struct {
 	Path string
 }
@@ -29,7 +24,6 @@ func (e ErrFileNotFound) Error() string {
 	return fmt.Sprintf("tuf: file not found %s", e.Path)
 }
 
-// ErrInsufficientKeys - did not have enough keys to sign when requested
 type ErrInsufficientKeys struct {
 	Name string
 }
@@ -38,8 +32,6 @@ func (e ErrInsufficientKeys) Error() string {
 	return fmt.Sprintf("tuf: insufficient keys to sign %s", e.Name)
 }
 
-// ErrInsufficientSignatures - do not have enough signatures on a piece of
-// metadata
 type ErrInsufficientSignatures struct {
 	Name string
 	Err  error
@@ -49,7 +41,6 @@ func (e ErrInsufficientSignatures) Error() string {
 	return fmt.Sprintf("tuf: insufficient signatures for %s: %s", e.Name, e.Err)
 }
 
-// ErrInvalidRole - role is wrong. Typically we're missing the public keys for it
 type ErrInvalidRole struct {
 	Role string
 }
@@ -58,7 +49,6 @@ func (e ErrInvalidRole) Error() string {
 	return fmt.Sprintf("tuf: invalid role %s", e.Role)
 }
 
-// ErrInvalidExpires - the expiry time for a metadata file is invalid
 type ErrInvalidExpires struct {
 	Expires time.Time
 }
@@ -67,7 +57,6 @@ func (e ErrInvalidExpires) Error() string {
 	return fmt.Sprintf("tuf: invalid expires: %s", e.Expires)
 }
 
-// ErrKeyNotFound - could not find a given key on a role
 type ErrKeyNotFound struct {
 	Role  string
 	KeyID string
@@ -77,7 +66,6 @@ func (e ErrKeyNotFound) Error() string {
 	return fmt.Sprintf(`tuf: no key with id "%s" exists for the %s role`, e.KeyID, e.Role)
 }
 
-// ErrNotEnoughKeys - there are not enough keys to ever meet the signature threshold
 type ErrNotEnoughKeys struct {
 	Role      string
 	Keys      int
@@ -88,7 +76,6 @@ func (e ErrNotEnoughKeys) Error() string {
 	return fmt.Sprintf("tuf: %s role has insufficient keys for threshold (has %d keys, threshold is %d)", e.Role, e.Keys, e.Threshold)
 }
 
-// ErrPassphraseRequired - a passphrase is needed and wasn't provided
 type ErrPassphraseRequired struct {
 	Role string
 }
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/keys/db.go b/Godeps/_workspace/src/github.com/endophage/gotuf/keys/db.go
index f4837afd..9ac5c96e 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/keys/db.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/keys/db.go
@@ -6,7 +6,6 @@ import (
 	"github.com/endophage/gotuf/data"
 )
 
-// Various basic key database errors
 var (
 	ErrWrongType        = errors.New("tuf: invalid key type")
 	ErrExists           = errors.New("tuf: key already in db")
@@ -17,15 +16,11 @@ var (
 	ErrInvalidThreshold = errors.New("tuf: invalid role threshold")
 )
 
-// KeyDB is an in memory database of public keys and role associations.
-// It is populated when parsing TUF files and used during signature
-// verification to look up the keys for a given role
 type KeyDB struct {
 	roles map[string]*data.Role
 	keys  map[string]data.PublicKey
 }
 
-// NewDB initializes an empty KeyDB
 func NewDB() *KeyDB {
 	return &KeyDB{
 		roles: make(map[string]*data.Role),
@@ -33,13 +28,10 @@ func NewDB() *KeyDB {
 	}
 }
 
-// AddKey adds a public key to the database
 func (db *KeyDB) AddKey(k data.PublicKey) {
 	db.keys[k.ID()] = k
 }
 
-// AddRole adds a role to the database. Any keys associated with the
-// role must have already been added.
 func (db *KeyDB) AddRole(r *data.Role) error {
 	if !data.ValidRole(r.Name) {
 		return ErrInvalidRole
@@ -59,12 +51,10 @@ func (db *KeyDB) AddRole(r *data.Role) error {
 	return nil
 }
 
-// GetKey pulls a key out of the database by its ID
 func (db *KeyDB) GetKey(id string) data.PublicKey {
 	return db.keys[id]
 }
 
-// GetRole retrieves a role based on its name
 func (db *KeyDB) GetRole(name string) *data.Role {
 	return db.roles[name]
 }
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/ed25519.go b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/ed25519.go
index 4cfbdc44..ca857486 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/ed25519.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/ed25519.go
@@ -13,8 +13,6 @@ type Ed25519 struct {
 	keys map[string]data.PrivateKey
 }
 
-// NewEd25519 initializes a new empty Ed25519 CryptoService that operates
-// entirely in memory
 func NewEd25519() *Ed25519 {
 	return &Ed25519{
 		make(map[string]data.PrivateKey),
@@ -26,21 +24,19 @@ func (e *Ed25519) addKey(k data.PrivateKey) {
 	e.keys[k.ID()] = k
 }
 
-// RemoveKey deletes a key from the signer
 func (e *Ed25519) RemoveKey(keyID string) error {
 	delete(e.keys, keyID)
 	return nil
 }
 
-// Sign generates an Ed25519 signature over the data
 func (e *Ed25519) Sign(keyIDs []string, toSign []byte) ([]data.Signature, error) {
 	signatures := make([]data.Signature, 0, len(keyIDs))
-	for _, keyID := range keyIDs {
+	for _, kID := range keyIDs {
 		priv := [ed25519.PrivateKeySize]byte{}
-		copy(priv[:], e.keys[keyID].Private())
+		copy(priv[:], e.keys[kID].Private())
 		sig := ed25519.Sign(&priv, toSign)
 		signatures = append(signatures, data.Signature{
-			KeyID:     keyID,
+			KeyID:     kID,
 			Method:    data.EDDSASignature,
 			Signature: sig[:],
 		})
@@ -49,7 +45,6 @@ func (e *Ed25519) Sign(keyIDs []string, toSign []byte) ([]data.Signature, error)
 
 }
 
-// Create generates a new key and returns the public part
 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")
@@ -65,19 +60,16 @@ func (e *Ed25519) Create(role string, algorithm data.KeyAlgorithm) (data.PublicK
 	return public, nil
 }
 
-// PublicKeys returns a map of public keys for the ids provided, when those IDs are found
-// in the store.
 func (e *Ed25519) PublicKeys(keyIDs ...string) (map[string]data.PublicKey, error) {
 	k := make(map[string]data.PublicKey)
-	for _, keyID := range keyIDs {
-		if key, ok := e.keys[keyID]; ok {
-			k[keyID] = data.PublicKeyFromPrivate(key)
+	for _, kID := range keyIDs {
+		if key, ok := e.keys[kID]; ok {
+			k[kID] = data.PublicKeyFromPrivate(key)
 		}
 	}
 	return k, nil
 }
 
-// GetKey returns a single public key based on the ID
 func (e *Ed25519) GetKey(keyID string) data.PublicKey {
 	return data.PublicKeyFromPrivate(e.keys[keyID])
 }
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/errors.go b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/errors.go
index 0c92f346..09ecc9a7 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/errors.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/errors.go
@@ -4,7 +4,6 @@ import (
 	"fmt"
 )
 
-// ErrExpired indicates a piece of metadata has expired
 type ErrExpired struct {
 	Role    string
 	Expired string
@@ -14,8 +13,6 @@ func (e ErrExpired) Error() string {
 	return fmt.Sprintf("%s expired at %v", e.Role, e.Expired)
 }
 
-// ErrLowVersion indicates the piece of metadata has a version number lower than
-// a version number we're already seen for this role
 type ErrLowVersion struct {
 	Actual  int
 	Current int
@@ -25,23 +22,18 @@ func (e ErrLowVersion) Error() string {
 	return fmt.Sprintf("version %d is lower than current version %d", e.Actual, e.Current)
 }
 
-// ErrRoleThreshold indicates we did not validate enough signatures to meet the threshold
 type ErrRoleThreshold struct{}
 
 func (e ErrRoleThreshold) Error() string {
 	return "valid signatures did not meet threshold"
 }
 
-// ErrInvalidKeyType indicates the types for the key and signature it's associated with are
-// mismatched. Probably a sign of malicious behaviour
 type ErrInvalidKeyType struct{}
 
 func (e ErrInvalidKeyType) Error() string {
 	return "key type is not valid for signature"
 }
 
-// ErrInvalidKeyLength indicates that while we may support the cipher, the provided
-// key length is not specifically supported, i.e. we support RSA, but not 1024 bit keys
 type ErrInvalidKeyLength struct {
 	msg string
 }
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 e0a9b3b8..8bab4410 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign.go
@@ -1,84 +1,43 @@
 package signed
 
-// The Sign function is a choke point for all code paths that do signing.
-// We use this fact to do key ID translation. There are 2 types of key ID:
-//   - Scoped: the key ID based purely on the data that appears in the TUF
-//             files. This may be wrapped by a certificate that scopes the
-//             key to be used in a specific context.
-//   - Canonical: the key ID based purely on the public key bytes. This is
-//             used by keystores to easily identify keys that may be reused
-//             in many scoped locations.
-// Currently these types only differ in the context of Root Keys in Notary
-// for which the root key is wrapped using an x509 certificate.
-
 import (
 	"fmt"
-
 	"github.com/Sirupsen/logrus"
 	"github.com/endophage/gotuf/data"
 	"github.com/endophage/gotuf/errors"
-	"github.com/endophage/gotuf/utils"
+	"strings"
 )
 
-type idPair struct {
-	scopedKeyID    string
-	canonicalKeyID string
-}
-
 // Sign takes a data.Signed and a key, calculated and adds the signature
 // to the data.Signed
 func Sign(service CryptoService, s *data.Signed, keys ...data.PublicKey) error {
 	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(
-		[]idPair,
-		0,
-		len(keys),
-	)
+	keyIDs := make([]string, 0, len(keys))
 
 	for _, key := range keys {
-		keyID, err := utils.CanonicalKeyID(key)
-		if err != nil {
-			continue
-		}
 		keyIDMemb[key.ID()] = struct{}{}
-		keyIDs = append(keyIDs, idPair{
-			scopedKeyID:    key.ID(),
-			canonicalKeyID: keyID,
-		})
-	}
-
-	// we need to ask the signer to sign with the canonical key ID
-	// (ID of the TUF key's public key bytes only), but
-	// we need to translate back to the scoped key ID (the hash of the TUF key
-	// with the full PEM bytes) before giving the
-	// signature back to TUF.
-	for _, pair := range keyIDs {
-		newSigs, err := service.Sign([]string{pair.canonicalKeyID}, s.Signed)
-		if err != nil {
-			return err
-		}
-		// we only asked to sign with 1 key ID, so there will either be 1
-		// or zero signatures
-		if len(newSigs) == 1 {
-			newSig := newSigs[0]
-			newSig.KeyID = pair.scopedKeyID
-			signatures = append(signatures, newSig)
-		}
-	}
-	if len(signatures) < 1 {
-		return errors.ErrInsufficientSignatures{
-			Name: fmt.Sprintf("Cryptoservice failed to produce any signatures for keys with IDs: %v", keyIDs),
-			Err:  nil,
-		}
+		keyIDs = append(keyIDs, key.ID())
 	}
+	logrus.Debugf("Generated list of signing IDs: %s", strings.Join(keyIDs, ", "))
 	for _, sig := range s.Signatures {
 		if _, ok := keyIDMemb[sig.KeyID]; ok {
 			continue
 		}
 		signatures = append(signatures, sig)
 	}
-	s.Signatures = signatures
+	newSigs, err := service.Sign(keyIDs, s.Signed)
+	if err != nil {
+		return err
+	}
+	if len(newSigs) < 1 {
+		return errors.ErrInsufficientSignatures{
+			Name: fmt.Sprint("Cryptoservice failed to produce any signatures for keys with IDs: %s", strings.Join(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/verifiers.go b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verifiers.go
index ef518f0b..e11eb4ad 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verifiers.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verifiers.go
@@ -50,10 +50,8 @@ func RegisterVerifier(algorithm data.SigAlgorithm, v Verifier) {
 	Verifiers[algorithm] = v
 }
 
-// Ed25519Verifier used to verify Ed25519 signatures
 type Ed25519Verifier struct{}
 
-// Verify checks that an ed25519 signature is valid
 func (v Ed25519Verifier) Verify(key data.PublicKey, sig []byte, msg []byte) error {
 	if key.Algorithm() != data.ED25519Key {
 		return ErrInvalidKeyType{}
@@ -158,10 +156,9 @@ func (v RSAPSSVerifier) Verify(key data.PublicKey, sig []byte, msg []byte) error
 	return verifyPSS(pubKey, digest[:], sig)
 }
 
-// RSAPKCS1v15Verifier checks RSA PKCS1v15 signatures
+// RSAPKCS1v15SVerifier checks RSA PKCS1v15 signatures
 type RSAPKCS1v15Verifier struct{}
 
-// Verify does the actual verification
 func (v RSAPKCS1v15Verifier) Verify(key data.PublicKey, sig []byte, msg []byte) error {
 	// will return err if keytype is not a recognized RSA type
 	pubKey, err := getRSAPubKey(key)
@@ -193,7 +190,7 @@ func (v RSAPKCS1v15Verifier) Verify(key data.PublicKey, sig []byte, msg []byte)
 	return nil
 }
 
-// RSAPyCryptoVerifier checks RSASSA-PSS signatures
+// RSAPSSVerifier checks RSASSA-PSS signatures
 type RSAPyCryptoVerifier struct{}
 
 // Verify does the actual check.
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 b0acf816..b1ef6a3a 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verify.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verify.go
@@ -11,7 +11,6 @@ import (
 	"github.com/jfrazelle/go/canonical/json"
 )
 
-// Various basic signing errors
 var (
 	ErrMissingKey   = errors.New("tuf: missing key")
 	ErrNoSignatures = errors.New("tuf: data has no signatures")
@@ -62,8 +61,6 @@ func VerifyRoot(s *data.Signed, minVersion int, keys map[string]data.PublicKey)
 	return ErrRoleThreshold{}
 }
 
-// Verify checks the signatures and metadata (expiry, version) for the signed role
-// data
 func Verify(s *data.Signed, role string, minVersion int, db *keys.KeyDB) error {
 	if err := VerifySignatures(s, role, db); err != nil {
 		return err
@@ -90,12 +87,10 @@ func verifyMeta(s *data.Signed, role string, minVersion int) error {
 	return nil
 }
 
-// IsExpired checks if the given time passed before the present time
-func IsExpired(t time.Time) bool {
+var IsExpired = func(t time.Time) bool {
 	return t.Before(time.Now())
 }
 
-// VerifySignatures checks the we have sufficient valid signatures for the given role
 func VerifySignatures(s *data.Signed, role string, db *keys.KeyDB) error {
 	if len(s.Signatures) == 0 {
 		return ErrNoSignatures
@@ -154,7 +149,6 @@ func VerifySignatures(s *data.Signed, role string, db *keys.KeyDB) error {
 	return nil
 }
 
-// Unmarshal unmarshals and verifys the raw bytes for a given role's metadata
 func Unmarshal(b []byte, v interface{}, role string, minVersion int, db *keys.KeyDB) error {
 	s := &data.Signed{}
 	if err := json.Unmarshal(b, s); err != nil {
@@ -166,8 +160,6 @@ func Unmarshal(b []byte, v interface{}, role string, minVersion int, db *keys.Ke
 	return json.Unmarshal(s.Signed, v)
 }
 
-// UnmarshalTrusted unmarshals and verifies signatures only, not metadata, for a
-// given role's metadata
 func UnmarshalTrusted(b []byte, v interface{}, role string, db *keys.KeyDB) error {
 	s := &data.Signed{}
 	if err := json.Unmarshal(b, s); err != nil {
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/store/dbstore.go b/Godeps/_workspace/src/github.com/endophage/gotuf/store/dbstore.go
new file mode 100644
index 00000000..8d65d0db
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/store/dbstore.go
@@ -0,0 +1,252 @@
+package store
+
+import (
+	"database/sql"
+	"encoding/hex"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"path"
+
+	logrus "github.com/Sirupsen/logrus"
+	"github.com/endophage/gotuf/data"
+	"github.com/endophage/gotuf/utils"
+	"github.com/jfrazelle/go/canonical/json"
+)
+
+const (
+	tufLoc         string = "/tmp/tuf"
+	metadataSubDir string = "metadata"
+)
+
+// implements LocalStore
+type dbStore struct {
+	db        sql.DB
+	imageName string
+}
+
+// DBStore takes a database connection and the QDN of the image
+func DBStore(db *sql.DB, imageName string) *dbStore {
+	store := dbStore{
+		db:        *db,
+		imageName: imageName,
+	}
+
+	return &store
+}
+
+// GetMeta loads existing TUF metadata files
+func (dbs *dbStore) GetMeta(name string) ([]byte, error) {
+	data, err := dbs.readFile(name)
+	if err != nil {
+		return nil, err
+	}
+	return data, err
+}
+
+// SetMeta writes individual TUF metadata files
+func (dbs *dbStore) SetMeta(name string, meta []byte) error {
+	return dbs.writeFile(name, meta)
+}
+
+// WalkStagedTargets walks all targets in scope
+func (dbs *dbStore) WalkStagedTargets(paths []string, targetsFn targetsWalkFunc) error {
+	if len(paths) == 0 {
+		files := dbs.loadTargets("")
+		for path, meta := range files {
+			if err := targetsFn(path, meta); err != nil {
+				return err
+			}
+		}
+		return nil
+	}
+
+	for _, path := range paths {
+		files := dbs.loadTargets(path)
+		meta, ok := files[path]
+		if !ok {
+			return fmt.Errorf("File Not Found")
+		}
+		if err := targetsFn(path, meta); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// Commit writes a set of consistent (possibly) TUF metadata files
+func (dbs *dbStore) Commit(metafiles map[string][]byte, consistent bool, hashes map[string]data.Hashes) error {
+	// TODO (endophage): write meta files to cache
+	return nil
+
+}
+
+// GetKeys returns private keys
+func (dbs *dbStore) GetKeys(role string) ([]data.PrivateKey, error) {
+	keys := []data.PrivateKey{}
+	var r *sql.Rows
+	var err error
+	sql := "SELECT `key` FROM `keys` WHERE `role` = ? AND `namespace` = ?;"
+	tx, err := dbs.db.Begin()
+	defer tx.Rollback()
+	r, err = tx.Query(sql, role, dbs.imageName)
+	if err != nil {
+		return nil, err
+	}
+	defer r.Close()
+	for r.Next() {
+		var jsonStr string
+		key := new(data.TUFKey)
+		r.Scan(&jsonStr)
+		err := json.Unmarshal([]byte(jsonStr), key)
+		if err != nil {
+			return nil, err
+		}
+		keys = append(keys, key)
+	}
+	return keys, nil
+}
+
+// SaveKey saves a new private key
+func (dbs *dbStore) SaveKey(role string, key data.PrivateKey) error {
+	jsonBytes, err := json.Marshal(key)
+	if err != nil {
+		return fmt.Errorf("Could not JSON Marshal Key")
+	}
+	tx, err := dbs.db.Begin()
+	if err != nil {
+		logrus.Error(err)
+		return err
+	}
+	_, err = tx.Exec("INSERT INTO `keys` (`namespace`, `role`, `key`) VALUES (?,?,?);", dbs.imageName, role, string(jsonBytes))
+	tx.Commit()
+	return err
+}
+
+// Clean removes staged targets
+func (dbs *dbStore) Clean() error {
+	// TODO (endophage): purge stale items from db? May just/also need a remove method
+	return nil
+}
+
+// AddBlob adds an object to the store
+func (dbs *dbStore) AddBlob(path string, meta data.FileMeta) {
+	path = utils.NormalizeTarget(path)
+	jsonbytes := []byte{}
+	if meta.Custom != nil {
+		jsonbytes, _ = meta.Custom.MarshalJSON()
+	}
+
+	tx, err := dbs.db.Begin()
+	if err != nil {
+		logrus.Error(err)
+		return
+	}
+	_, err = tx.Exec("INSERT OR REPLACE INTO `filemeta` VALUES (?,?,?,?);", dbs.imageName, path, meta.Length, jsonbytes)
+	if err != nil {
+		logrus.Error(err)
+	}
+	tx.Commit()
+	dbs.addBlobHashes(path, meta.Hashes)
+}
+
+func (dbs *dbStore) addBlobHashes(path string, hashes data.Hashes) {
+	tx, err := dbs.db.Begin()
+	if err != nil {
+		logrus.Error(err)
+	}
+	for alg, hash := range hashes {
+		_, err := tx.Exec("INSERT OR REPLACE INTO `filehashes` VALUES (?,?,?,?);", dbs.imageName, path, alg, hex.EncodeToString(hash))
+		if err != nil {
+			logrus.Error(err)
+		}
+	}
+	tx.Commit()
+}
+
+// RemoveBlob removes an object from the store
+func (dbs *dbStore) RemoveBlob(path string) error {
+	tx, err := dbs.db.Begin()
+	if err != nil {
+		logrus.Error(err)
+		return err
+	}
+	_, err = tx.Exec("DELETE FROM `filemeta` WHERE `path`=? AND `namespace`=?", path, dbs.imageName)
+	if err == nil {
+		tx.Commit()
+	} else {
+		tx.Rollback()
+	}
+	return err
+}
+
+func (dbs *dbStore) loadTargets(path string) map[string]data.FileMeta {
+	var err error
+	var r *sql.Rows
+	tx, err := dbs.db.Begin()
+	defer tx.Rollback()
+	files := make(map[string]data.FileMeta)
+	sql := "SELECT `filemeta`.`path`, `size`, `alg`, `hash`, `custom` FROM `filemeta` JOIN `filehashes` ON `filemeta`.`path` = `filehashes`.`path` AND `filemeta`.`namespace` = `filehashes`.`namespace` WHERE `filemeta`.`namespace`=?"
+	if path != "" {
+		sql = fmt.Sprintf("%s %s", sql, "AND `filemeta`.`path`=?")
+		r, err = tx.Query(sql, dbs.imageName, path)
+	} else {
+		r, err = tx.Query(sql, dbs.imageName)
+	}
+	if err != nil {
+		return files
+	}
+	defer r.Close()
+	for r.Next() {
+		var absPath, alg, hash string
+		var size int64
+		var custom []byte
+		r.Scan(&absPath, &size, &alg, &hash, &custom)
+		hashBytes, err := hex.DecodeString(hash)
+		if err != nil {
+			// We're going to skip items with unparseable hashes as they
+			// won't be valid in the targets
+			logrus.Debug("Hash was not stored in hex as expected")
+			continue
+		}
+		if file, ok := files[absPath]; ok {
+			file.Hashes[alg] = hashBytes
+		} else {
+			file = data.FileMeta{
+				Length: size,
+				Hashes: data.Hashes{
+					alg: hashBytes,
+				},
+			}
+			if custom != nil {
+				file.Custom = json.RawMessage(custom)
+			}
+			files[absPath] = file
+		}
+	}
+	return files
+}
+
+func (dbs *dbStore) writeFile(name string, content []byte) error {
+	jsonName := fmt.Sprintf("%s.json", name)
+	fullPath := path.Join(tufLoc, metadataSubDir, dbs.imageName, jsonName)
+	dirPath := path.Dir(fullPath)
+	err := os.MkdirAll(dirPath, 0744)
+	if err != nil {
+		logrus.Error("error creating directory path to TUF cache")
+		return err
+	}
+
+	err = ioutil.WriteFile(fullPath, content, 0744)
+	if err != nil {
+		logrus.Error("Error writing file")
+	}
+	return err
+}
+
+func (dbs *dbStore) readFile(name string) ([]byte, error) {
+	jsonName := fmt.Sprintf("%s.json", name)
+	fullPath := path.Join(tufLoc, metadataSubDir, dbs.imageName, jsonName)
+	content, err := ioutil.ReadFile(fullPath)
+	return content, err
+}
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/store/errors.go b/Godeps/_workspace/src/github.com/endophage/gotuf/store/errors.go
index b944c2d7..0bc8272f 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/store/errors.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/store/errors.go
@@ -1,7 +1,5 @@
 package store
 
-// ErrMetaNotFound indicates we did not find a particular piece
-// of metadata in the store
 type ErrMetaNotFound struct{}
 
 func (err ErrMetaNotFound) Error() string {
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/store/filestore.go b/Godeps/_workspace/src/github.com/endophage/gotuf/store/filestore.go
index ff3f785f..2ebd9b5b 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/store/filestore.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/store/filestore.go
@@ -8,8 +8,7 @@ import (
 	"path/filepath"
 )
 
-// NewFilesystemStore creates a new store in a directory tree
-func NewFilesystemStore(baseDir, metaSubDir, metaExtension, targetsSubDir string) (*FilesystemStore, error) {
+func NewFilesystemStore(baseDir, metaSubDir, metaExtension, targetsSubDir string) (*filesystemStore, error) {
 	metaDir := path.Join(baseDir, metaSubDir)
 	targetsDir := path.Join(baseDir, targetsSubDir)
 
@@ -23,7 +22,7 @@ func NewFilesystemStore(baseDir, metaSubDir, metaExtension, targetsSubDir string
 		return nil, err
 	}
 
-	return &FilesystemStore{
+	return &filesystemStore{
 		baseDir:       baseDir,
 		metaDir:       metaDir,
 		metaExtension: metaExtension,
@@ -31,16 +30,14 @@ func NewFilesystemStore(baseDir, metaSubDir, metaExtension, targetsSubDir string
 	}, nil
 }
 
-// FilesystemStore is a store in a locally accessible directory
-type FilesystemStore struct {
+type filesystemStore struct {
 	baseDir       string
 	metaDir       string
 	metaExtension string
 	targetsDir    string
 }
 
-// GetMeta returns the meta for the given name (a role)
-func (f *FilesystemStore) GetMeta(name string, size int64) ([]byte, error) {
+func (f *filesystemStore) GetMeta(name string, size int64) ([]byte, error) {
 	fileName := fmt.Sprintf("%s.%s", name, f.metaExtension)
 	path := filepath.Join(f.metaDir, fileName)
 	meta, err := ioutil.ReadFile(path)
@@ -50,8 +47,7 @@ func (f *FilesystemStore) GetMeta(name string, size int64) ([]byte, error) {
 	return meta, nil
 }
 
-// SetMultiMeta sets the metadata for multiple roles in one operation
-func (f *FilesystemStore) SetMultiMeta(metas map[string][]byte) error {
+func (f *filesystemStore) SetMultiMeta(metas map[string][]byte) error {
 	for role, blob := range metas {
 		err := f.SetMeta(role, blob)
 		if err != nil {
@@ -61,8 +57,7 @@ func (f *FilesystemStore) SetMultiMeta(metas map[string][]byte) error {
 	return nil
 }
 
-// SetMeta sets the meta for a single role
-func (f *FilesystemStore) SetMeta(name string, meta []byte) error {
+func (f *filesystemStore) SetMeta(name string, meta []byte) error {
 	fileName := fmt.Sprintf("%s.%s", name, f.metaExtension)
 	path := filepath.Join(f.metaDir, fileName)
 	if err := ioutil.WriteFile(path, meta, 0600); err != nil {
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/store/httpstore.go b/Godeps/_workspace/src/github.com/endophage/gotuf/store/httpstore.go
index 5e667432..73043826 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/store/httpstore.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/store/httpstore.go
@@ -14,8 +14,6 @@ import (
 	"github.com/Sirupsen/logrus"
 )
 
-// ErrServerUnavailable indicates an error from the server. code allows us to
-// populate the http error we received
 type ErrServerUnavailable struct {
 	code int
 }
@@ -24,9 +22,12 @@ func (err ErrServerUnavailable) Error() string {
 	return fmt.Sprintf("Unable to reach trust server at this time: %d.", err.code)
 }
 
-// ErrMaliciousServer indicates the server returned a response that is highly suspected
-// of being malicious. i.e. it attempted to send us more data than the known size of a
-// particular role metadata.
+type ErrShortRead struct{}
+
+func (err ErrShortRead) Error() string {
+	return "Trust server returned incompelete response."
+}
+
 type ErrMaliciousServer struct{}
 
 func (err ErrMaliciousServer) Error() string {
@@ -51,8 +52,7 @@ type HTTPStore struct {
 	roundTrip     http.RoundTripper
 }
 
-// NewHTTPStore initializes a new store against a URL and a number of configuration options
-func NewHTTPStore(baseURL, metaPrefix, metaExtension, targetsPrefix, keyExtension string, roundTrip http.RoundTripper) (RemoteStore, error) {
+func NewHTTPStore(baseURL, metaPrefix, metaExtension, targetsPrefix, keyExtension string, roundTrip http.RoundTripper) (*HTTPStore, error) {
 	base, err := url.Parse(baseURL)
 	if err != nil {
 		return nil, err
@@ -99,13 +99,16 @@ func (s HTTPStore) GetMeta(name string, size int64) ([]byte, error) {
 	logrus.Debugf("%d when retrieving metadata for %s", resp.StatusCode, name)
 	b := io.LimitReader(resp.Body, size)
 	body, err := ioutil.ReadAll(b)
+	if resp.ContentLength > 0 && int64(len(body)) < resp.ContentLength {
+		return nil, ErrShortRead{}
+	}
+
 	if err != nil {
 		return nil, err
 	}
 	return body, nil
 }
 
-// SetMeta uploads a piece of TUF metadata to the server
 func (s HTTPStore) SetMeta(name string, blob []byte) error {
 	url, err := s.buildMetaURL("")
 	if err != nil {
@@ -128,9 +131,6 @@ func (s HTTPStore) SetMeta(name string, blob []byte) error {
 	return nil
 }
 
-// SetMultiMeta does a single batch upload of multiple pieces of TUF metadata.
-// This should be preferred for updating a remote server as it enable the server
-// to remain consistent, either accepting or rejecting the complete update.
 func (s HTTPStore) SetMultiMeta(metas map[string][]byte) error {
 	url, err := s.buildMetaURL("")
 	if err != nil {
@@ -220,7 +220,6 @@ func (s HTTPStore) GetTarget(path string) (io.ReadCloser, error) {
 	return resp.Body, nil
 }
 
-// GetKey retrieves a public key from the remote server
 func (s HTTPStore) GetKey(role string) ([]byte, error) {
 	url, err := s.buildKeyURL(role)
 	if err != nil {
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/store/interfaces.go b/Godeps/_workspace/src/github.com/endophage/gotuf/store/interfaces.go
index 0be5f60d..093f3851 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/store/interfaces.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/store/interfaces.go
@@ -8,34 +8,26 @@ import (
 
 type targetsWalkFunc func(path string, meta data.FileMeta) error
 
-// MetadataStore must be implemented by anything that intends to interact
-// with a store of TUF files
 type MetadataStore interface {
 	GetMeta(name string, size int64) ([]byte, error)
 	SetMeta(name string, blob []byte) error
 	SetMultiMeta(map[string][]byte) error
 }
 
-// PublicKeyStore must be implemented by a key service
 type PublicKeyStore interface {
 	GetKey(role string) ([]byte, error)
 }
 
-// TargetStore represents a collection of targets that can be walked similarly
-// to walking a directory, passing a callback that receives the path and meta
-// for each target
+// [endophage] I'm of the opinion this should go away.
 type TargetStore interface {
 	WalkStagedTargets(paths []string, targetsFn targetsWalkFunc) error
 }
 
-// LocalStore represents a local TUF sture
 type LocalStore interface {
 	MetadataStore
 	TargetStore
 }
 
-// RemoteStore is similar to LocalStore with the added expectation that it should
-// provide a way to download targets once located
 type RemoteStore interface {
 	MetadataStore
 	PublicKeyStore
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/store/memorystore.go b/Godeps/_workspace/src/github.com/endophage/gotuf/store/memorystore.go
index 8adddebe..d32c9a4f 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/store/memorystore.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/store/memorystore.go
@@ -10,9 +10,7 @@ import (
 	"github.com/endophage/gotuf/utils"
 )
 
-// NewMemoryStore returns a MetadataStore that operates entirely in memory.
-// Very useful for testing
-func NewMemoryStore(meta map[string][]byte, files map[string][]byte) RemoteStore {
+func NewMemoryStore(meta map[string][]byte, files map[string][]byte) *memoryStore {
 	if meta == nil {
 		meta = make(map[string][]byte)
 	}
@@ -33,14 +31,7 @@ type memoryStore struct {
 }
 
 func (m *memoryStore) GetMeta(name string, size int64) ([]byte, error) {
-	d, ok := m.meta[name]
-	if ok {
-		if int64(len(d)) < size {
-			return d, nil
-		}
-		return d[:size], nil
-	}
-	return nil, ErrMetaNotFound{}
+	return m.meta[name], nil
 }
 
 func (m *memoryStore) SetMeta(name string, meta []byte) error {
@@ -76,7 +67,7 @@ func (m *memoryStore) WalkStagedTargets(paths []string, targetsFn targetsWalkFun
 	for _, path := range paths {
 		dat, ok := m.files[path]
 		if !ok {
-			return errors.ErrFileNotFound{Path: path}
+			return errors.ErrFileNotFound{path}
 		}
 		meta, err := data.NewFileMeta(bytes.NewReader(dat), "sha256")
 		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 a797e8b5..39af5401 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/tuf.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/tuf.go
@@ -1,4 +1,4 @@
-// Package tuf defines the core TUF logic around manipulating a repo.
+// tuf defines the core TUF logic around manipulating a repo.
 package tuf
 
 import (
@@ -19,29 +19,24 @@ import (
 	"github.com/endophage/gotuf/utils"
 )
 
-// ErrSigVerifyFail - signature verification failed
 type ErrSigVerifyFail struct{}
 
 func (e ErrSigVerifyFail) Error() string {
 	return "Error: Signature verification failed"
 }
 
-// ErrMetaExpired - metadata file has expired
 type ErrMetaExpired struct{}
 
 func (e ErrMetaExpired) Error() string {
 	return "Error: Metadata has expired"
 }
 
-// ErrLocalRootExpired - the local root file is out of date
 type ErrLocalRootExpired struct{}
 
 func (e ErrLocalRootExpired) Error() string {
 	return "Error: Local Root Has Expired"
 }
 
-// ErrNotLoaded - attempted to access data that has not been loaded into
-// the repo
 type ErrNotLoaded struct {
 	role string
 }
@@ -50,12 +45,12 @@ func (err ErrNotLoaded) Error() string {
 	return fmt.Sprintf("%s role has not been loaded", err.role)
 }
 
-// Repo is an in memory representation of the TUF Repo.
+// TufRepo is an in memory representation of the TUF Repo.
 // It operates at the data.Signed level, accepting and producing
-// data.Signed objects. Users of a Repo are responsible for
+// data.Signed objects. Users of a TufRepo are responsible for
 // fetching raw JSON and using the Set* functions to populate
-// the Repo instance.
-type Repo struct {
+// the TufRepo instance.
+type TufRepo struct {
 	Root          *data.SignedRoot
 	Targets       map[string]*data.SignedTargets
 	Snapshot      *data.SignedSnapshot
@@ -64,10 +59,10 @@ type Repo struct {
 	cryptoService signed.CryptoService
 }
 
-// NewRepo initializes a Repo instance with a keysDB and a signer.
-// If the Repo will only be used for reading, the signer should be nil.
-func NewRepo(keysDB *keys.KeyDB, cryptoService signed.CryptoService) *Repo {
-	repo := &Repo{
+// NewTufRepo initializes a TufRepo instance with a keysDB and a signer.
+// If the TufRepo will only be used for reading, the signer should be nil.
+func NewTufRepo(keysDB *keys.KeyDB, cryptoService signed.CryptoService) *TufRepo {
+	repo := &TufRepo{
 		Targets:       make(map[string]*data.SignedTargets),
 		keysDB:        keysDB,
 		cryptoService: cryptoService,
@@ -76,7 +71,7 @@ func NewRepo(keysDB *keys.KeyDB, cryptoService signed.CryptoService) *Repo {
 }
 
 // AddBaseKeys is used to add keys to the role in root.json
-func (tr *Repo) AddBaseKeys(role string, keys ...data.PublicKey) error {
+func (tr *TufRepo) AddBaseKeys(role string, keys ...data.PublicKey) error {
 	if tr.Root == nil {
 		return ErrNotLoaded{role: "root"}
 	}
@@ -106,7 +101,7 @@ func (tr *Repo) AddBaseKeys(role string, keys ...data.PublicKey) error {
 }
 
 // ReplaceBaseKeys is used to replace all keys for the given role with the new keys
-func (tr *Repo) ReplaceBaseKeys(role string, keys ...data.PublicKey) error {
+func (tr *TufRepo) ReplaceBaseKeys(role string, keys ...data.PublicKey) error {
 	r := tr.keysDB.GetRole(role)
 	err := tr.RemoveBaseKeys(role, r.KeyIDs...)
 	if err != nil {
@@ -116,11 +111,11 @@ func (tr *Repo) ReplaceBaseKeys(role string, keys ...data.PublicKey) error {
 }
 
 // RemoveBaseKeys is used to remove keys from the roles in root.json
-func (tr *Repo) RemoveBaseKeys(role string, keyIDs ...string) error {
+func (tr *TufRepo) RemoveBaseKeys(role string, keyIDs ...string) error {
 	if tr.Root == nil {
 		return ErrNotLoaded{role: "root"}
 	}
-	var keep []string
+	keep := make([]string, 0)
 	toDelete := make(map[string]struct{})
 	// remove keys from specified role
 	for _, k := range keyIDs {
@@ -162,7 +157,7 @@ func (tr *Repo) RemoveBaseKeys(role string, keyIDs ...string) error {
 // 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 *Repo) UpdateDelegations(role *data.Role, keys []data.Key, before string) error {
+func (tr *TufRepo) UpdateDelegations(role *data.Role, keys []data.Key, before string) error {
 	if !role.IsDelegation() || !role.IsValid() {
 		return errors.ErrInvalidRole{}
 	}
@@ -206,7 +201,7 @@ func (tr *Repo) UpdateDelegations(role *data.Role, keys []data.Key, before strin
 // 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 *Repo) InitRepo(consistent bool) error {
+func (tr *TufRepo) InitRepo(consistent bool) error {
 	if err := tr.InitRoot(consistent); err != nil {
 		return err
 	}
@@ -219,9 +214,7 @@ func (tr *Repo) InitRepo(consistent bool) error {
 	return tr.InitTimestamp()
 }
 
-// InitRoot initializes an empty root file with the 4 core roles based
-// on the current content of th ekey db
-func (tr *Repo) InitRoot(consistent bool) error {
+func (tr *TufRepo) InitRoot(consistent bool) error {
 	rootRoles := make(map[string]*data.RootRole)
 	rootKeys := make(map[string]data.PublicKey)
 	for _, r := range data.ValidRoles {
@@ -247,15 +240,13 @@ func (tr *Repo) InitRoot(consistent bool) error {
 	return nil
 }
 
-// InitTargets initializes an empty targets
-func (tr *Repo) InitTargets() error {
+func (tr *TufRepo) InitTargets() error {
 	targets := data.NewTargets()
 	tr.Targets[data.ValidRoles["targets"]] = targets
 	return nil
 }
 
-// InitSnapshot initializes a snapshot based on the current root and targets
-func (tr *Repo) InitSnapshot() error {
+func (tr *TufRepo) InitSnapshot() error {
 	root, err := tr.Root.ToSigned()
 	if err != nil {
 		return err
@@ -272,8 +263,7 @@ func (tr *Repo) InitSnapshot() error {
 	return nil
 }
 
-// InitTimestamp initializes a timestamp based on the current snapshot
-func (tr *Repo) InitTimestamp() error {
+func (tr *TufRepo) InitTimestamp() error {
 	snap, err := tr.Snapshot.ToSigned()
 	if err != nil {
 		return err
@@ -288,9 +278,9 @@ func (tr *Repo) InitTimestamp() error {
 }
 
 // SetRoot parses the Signed object into a SignedRoot object, sets
-// the keys and roles in the KeyDB, and sets the Repo.Root field
+// the keys and roles in the KeyDB, and sets the TufRepo.Root field
 // to the SignedRoot object.
-func (tr *Repo) SetRoot(s *data.SignedRoot) error {
+func (tr *TufRepo) SetRoot(s *data.SignedRoot) error {
 	for _, key := range s.Signed.Keys {
 		logrus.Debug("Adding key ", key.ID())
 		tr.keysDB.AddKey(key)
@@ -317,23 +307,23 @@ func (tr *Repo) SetRoot(s *data.SignedRoot) error {
 }
 
 // SetTimestamp parses the Signed object into a SignedTimestamp object
-// and sets the Repo.Timestamp field.
-func (tr *Repo) SetTimestamp(s *data.SignedTimestamp) error {
+// and sets the TufRepo.Timestamp field.
+func (tr *TufRepo) SetTimestamp(s *data.SignedTimestamp) error {
 	tr.Timestamp = s
 	return nil
 }
 
 // SetSnapshot parses the Signed object into a SignedSnapshots object
-// and sets the Repo.Snapshot field.
-func (tr *Repo) SetSnapshot(s *data.SignedSnapshot) error {
+// and sets the TufRepo.Snapshot field.
+func (tr *TufRepo) SetSnapshot(s *data.SignedSnapshot) error {
 	tr.Snapshot = s
 	return nil
 }
 
 // SetTargets parses the Signed object into a SignedTargets object,
 // reads the delegated roles and keys into the KeyDB, and sets the
-// SignedTargets object agaist the role in the Repo.Targets map.
-func (tr *Repo) SetTargets(role string, s *data.SignedTargets) error {
+// SignedTargets object agaist the role in the TufRepo.Targets map.
+func (tr *TufRepo) SetTargets(role string, s *data.SignedTargets) error {
 	for _, k := range s.Signed.Delegations.Keys {
 		tr.keysDB.AddKey(k)
 	}
@@ -347,7 +337,7 @@ func (tr *Repo) SetTargets(role string, s *data.SignedTargets) error {
 // TargetMeta returns the FileMeta entry for the given path in the
 // targets file associated with the given role. This may be nil if
 // the target isn't found in the targets file.
-func (tr Repo) TargetMeta(role, path string) *data.FileMeta {
+func (tr TufRepo) TargetMeta(role, path string) *data.FileMeta {
 	if t, ok := tr.Targets[role]; ok {
 		if m, ok := t.Signed.Targets[path]; ok {
 			return &m
@@ -358,12 +348,12 @@ func (tr Repo) TargetMeta(role, path string) *data.FileMeta {
 
 // TargetDelegations returns a slice of Roles that are valid publishers
 // for the target path provided.
-func (tr Repo) TargetDelegations(role, path, pathHex string) []*data.Role {
+func (tr TufRepo) TargetDelegations(role, path, pathHex string) []*data.Role {
 	if pathHex == "" {
 		pathDigest := sha256.Sum256([]byte(path))
 		pathHex = hex.EncodeToString(pathDigest[:])
 	}
-	var roles []*data.Role
+	roles := make([]*data.Role, 0)
 	if t, ok := tr.Targets[role]; ok {
 		for _, r := range t.Signed.Delegations.Roles {
 			if r.CheckPrefixes(pathHex) || r.CheckPaths(path) {
@@ -380,7 +370,7 @@ func (tr Repo) TargetDelegations(role, path, pathHex string) []*data.Role {
 // runs out of locations to search.
 // N.B. Multiple entries may exist in different delegated roles
 //      for the same target. Only the first one encountered is returned.
-func (tr Repo) FindTarget(path string) *data.FileMeta {
+func (tr TufRepo) FindTarget(path string) *data.FileMeta {
 	pathDigest := sha256.Sum256([]byte(path))
 	pathHex := hex.EncodeToString(pathDigest[:])
 
@@ -405,10 +395,10 @@ func (tr Repo) FindTarget(path string) *data.FileMeta {
 // AddTargets will attempt to add the given targets specifically to
 // the directed role. If the user does not have the signing keys for the role
 // the function will return an error and the full slice of targets.
-func (tr *Repo) AddTargets(role string, targets data.Files) (data.Files, error) {
+func (tr *TufRepo) AddTargets(role string, targets data.Files) (data.Files, error) {
 	t, ok := tr.Targets[role]
 	if !ok {
-		return targets, errors.ErrInvalidRole{Role: role}
+		return targets, errors.ErrInvalidRole{role}
 	}
 	invalid := make(data.Files)
 	for path, target := range targets {
@@ -428,11 +418,10 @@ func (tr *Repo) AddTargets(role string, targets data.Files) (data.Files, error)
 	return nil, nil
 }
 
-// RemoveTargets removes the given target (paths) from the given target role (delegation)
-func (tr *Repo) RemoveTargets(role string, targets ...string) error {
+func (tr *TufRepo) RemoveTargets(role string, targets ...string) error {
 	t, ok := tr.Targets[role]
 	if !ok {
-		return errors.ErrInvalidRole{Role: role}
+		return errors.ErrInvalidRole{role}
 	}
 
 	for _, path := range targets {
@@ -442,8 +431,7 @@ func (tr *Repo) RemoveTargets(role string, targets ...string) error {
 	return nil
 }
 
-// UpdateSnapshot updates the FileMeta for the given role based on the Signed object
-func (tr *Repo) UpdateSnapshot(role string, s *data.Signed) error {
+func (tr *TufRepo) UpdateSnapshot(role string, s *data.Signed) error {
 	jsonData, err := json.Marshal(s)
 	if err != nil {
 		return err
@@ -457,8 +445,7 @@ func (tr *Repo) UpdateSnapshot(role string, s *data.Signed) error {
 	return nil
 }
 
-// UpdateTimestamp updates the snapshot meta in the timestamp based on the Signed object
-func (tr *Repo) UpdateTimestamp(s *data.Signed) error {
+func (tr *TufRepo) UpdateTimestamp(s *data.Signed) error {
 	jsonData, err := json.Marshal(s)
 	if err != nil {
 		return err
@@ -472,8 +459,7 @@ func (tr *Repo) UpdateTimestamp(s *data.Signed) error {
 	return nil
 }
 
-// SignRoot signs the root
-func (tr *Repo) SignRoot(expires time.Time, cryptoService signed.CryptoService) (*data.Signed, error) {
+func (tr *TufRepo) SignRoot(expires time.Time, cryptoService signed.CryptoService) (*data.Signed, error) {
 	logrus.Debug("signing root...")
 	tr.Root.Signed.Expires = expires
 	tr.Root.Signed.Version++
@@ -490,8 +476,7 @@ func (tr *Repo) SignRoot(expires time.Time, cryptoService signed.CryptoService)
 	return signed, nil
 }
 
-// SignTargets signs the targets file for the given top level or delegated targets role
-func (tr *Repo) SignTargets(role string, expires time.Time, cryptoService signed.CryptoService) (*data.Signed, error) {
+func (tr *TufRepo) SignTargets(role string, expires time.Time, cryptoService signed.CryptoService) (*data.Signed, error) {
 	logrus.Debugf("sign targets called for role %s", role)
 	tr.Targets[role].Signed.Expires = expires
 	tr.Targets[role].Signed.Version++
@@ -510,8 +495,7 @@ func (tr *Repo) SignTargets(role string, expires time.Time, cryptoService signed
 	return signed, nil
 }
 
-// SignSnapshot updates the snapshot based on the current targets and root then signs it
-func (tr *Repo) SignSnapshot(expires time.Time, cryptoService signed.CryptoService) (*data.Signed, error) {
+func (tr *TufRepo) SignSnapshot(expires time.Time, cryptoService signed.CryptoService) (*data.Signed, error) {
 	logrus.Debug("signing snapshot...")
 	signedRoot, err := tr.Root.ToSigned()
 	if err != nil {
@@ -547,8 +531,7 @@ func (tr *Repo) SignSnapshot(expires time.Time, cryptoService signed.CryptoServi
 	return signed, nil
 }
 
-// SignTimestamp updates the timestamp based on the current snapshot then signs it
-func (tr *Repo) SignTimestamp(expires time.Time, cryptoService signed.CryptoService) (*data.Signed, error) {
+func (tr *TufRepo) SignTimestamp(expires time.Time, cryptoService signed.CryptoService) (*data.Signed, error) {
 	logrus.Debug("SignTimestamp")
 	signedSnapshot, err := tr.Snapshot.ToSigned()
 	if err != nil {
@@ -574,7 +557,7 @@ func (tr *Repo) SignTimestamp(expires time.Time, cryptoService signed.CryptoServ
 	return signed, nil
 }
 
-func (tr Repo) sign(signedData *data.Signed, role data.Role, cryptoService signed.CryptoService) (*data.Signed, error) {
+func (tr TufRepo) sign(signedData *data.Signed, role data.Role, cryptoService signed.CryptoService) (*data.Signed, error) {
 	ks := make([]data.PublicKey, 0, len(role.KeyIDs))
 	for _, kid := range role.KeyIDs {
 		k := tr.keysDB.GetKey(kid)
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/utils/util.go b/Godeps/_workspace/src/github.com/endophage/gotuf/utils/util.go
index 1282fb72..5184f799 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/utils/util.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/utils/util.go
@@ -8,33 +8,26 @@ import (
 	gopath "path"
 	"path/filepath"
 
-	"github.com/docker/notary/trustmanager"
 	"github.com/endophage/gotuf/data"
 )
 
-// ErrWrongLength indicates the length was different to that expected
 var ErrWrongLength = errors.New("wrong length")
 
-// ErrWrongHash indicates the hash was different to that expected
 type ErrWrongHash struct {
 	Type     string
 	Expected []byte
 	Actual   []byte
 }
 
-// Error implements error interface
 func (e ErrWrongHash) Error() string {
 	return fmt.Sprintf("wrong %s hash, expected %#x got %#x", e.Type, e.Expected, e.Actual)
 }
 
-// ErrNoCommonHash indicates the metadata did not provide any hashes this
-// client recognizes
 type ErrNoCommonHash struct {
 	Expected data.Hashes
 	Actual   data.Hashes
 }
 
-// Error implements error interface
 func (e ErrNoCommonHash) Error() string {
 	types := func(a data.Hashes) []string {
 		t := make([]string, 0, len(a))
@@ -46,21 +39,16 @@ func (e ErrNoCommonHash) Error() string {
 	return fmt.Sprintf("no common hash function, expected one of %s, got %s", types(e.Expected), types(e.Actual))
 }
 
-// ErrUnknownHashAlgorithm - client was ashed to use a hash algorithm
-// it is not familiar with
 type ErrUnknownHashAlgorithm struct {
 	Name string
 }
 
-// Error implements error interface
 func (e ErrUnknownHashAlgorithm) Error() string {
 	return fmt.Sprintf("unknown hash algorithm: %s", e.Name)
 }
 
-// PassphraseFunc type for func that request a passphrase
 type PassphraseFunc func(role string, confirm bool) ([]byte, error)
 
-// FileMetaEqual checks whether 2 FileMeta objects are consistent with eachother
 func FileMetaEqual(actual data.FileMeta, expected data.FileMeta) error {
 	if actual.Length != expected.Length {
 		return ErrWrongLength
@@ -80,13 +68,10 @@ func FileMetaEqual(actual data.FileMeta, expected data.FileMeta) error {
 	return nil
 }
 
-// NormalizeTarget adds a slash, if required, to the front of a target path
 func NormalizeTarget(path string) string {
 	return gopath.Join("/", path)
 }
 
-// HashedPaths prefixes the filename with the known hashes for the file,
-// returning a list of possible consistent paths.
 func HashedPaths(path string, hashes data.Hashes) []string {
 	paths := make([]string, 0, len(hashes))
 	for _, hash := range hashes {
@@ -95,15 +80,3 @@ func HashedPaths(path string, hashes data.Hashes) []string {
 	}
 	return paths
 }
-
-// CanonicalKeyID returns the ID of the public bytes version of a TUF key.
-// On regular RSA/ECDSA TUF keys, this is just the key ID.  On X509 RSA/ECDSA
-// TUF keys, this is the key ID of the public key part of the key.
-func CanonicalKeyID(k data.PublicKey) (string, error) {
-	switch k.Algorithm() {
-	case data.ECDSAx509Key, data.RSAx509Key:
-		return trustmanager.X509PublicKeyID(k)
-	default:
-		return k.ID(), nil
-	}
-}
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/utils/utils.go b/Godeps/_workspace/src/github.com/endophage/gotuf/utils/utils.go
index 4e9b28f8..ca164a1a 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/utils/utils.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/utils/utils.go
@@ -15,7 +15,6 @@ import (
 	"github.com/endophage/gotuf/data"
 )
 
-// Download does a simple download from a URL
 func Download(url url.URL) (*http.Response, error) {
 	tr := &http.Transport{
 		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
@@ -24,7 +23,6 @@ func Download(url url.URL) (*http.Response, error) {
 	return client.Get(url.String())
 }
 
-// Upload does a simple JSON upload to a URL
 func Upload(url string, body io.Reader) (*http.Response, error) {
 	tr := &http.Transport{
 		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
@@ -33,8 +31,6 @@ func Upload(url string, body io.Reader) (*http.Response, error) {
 	return client.Post(url, "application/json", body)
 }
 
-// ValidateTarget ensures that the data read from reader matches
-// the known metadata
 func ValidateTarget(r io.Reader, m *data.FileMeta) error {
 	h := sha256.New()
 	length, err := io.Copy(h, r)
@@ -42,7 +38,7 @@ func ValidateTarget(r io.Reader, m *data.FileMeta) error {
 		return err
 	}
 	if length != m.Length {
-		return fmt.Errorf("Size of downloaded target did not match targets entry.\nExpected: %d\nReceived: %d\n", m.Length, length)
+		return fmt.Errorf("Size of downloaded target did not match targets entry.\nExpected: %s\nReceived: %s\n", m.Length, length)
 	}
 	hashDigest := h.Sum(nil)
 	if bytes.Compare(m.Hashes["sha256"], hashDigest[:]) != 0 {
@@ -51,7 +47,6 @@ func ValidateTarget(r io.Reader, m *data.FileMeta) error {
 	return nil
 }
 
-// StrSliceContains checks if the given string appears in the slice
 func StrSliceContains(ss []string, s string) bool {
 	for _, v := range ss {
 		if v == s {
@@ -61,8 +56,6 @@ func StrSliceContains(ss []string, s string) bool {
 	return false
 }
 
-// StrSliceContainsI checks if the given string appears in the slice
-// in a case insensitive manner
 func StrSliceContainsI(ss []string, s string) bool {
 	s = strings.ToLower(s)
 	for _, v := range ss {
@@ -74,26 +67,19 @@ func StrSliceContainsI(ss []string, s string) bool {
 	return false
 }
 
-// FileExists returns true if a file (or dir) exists at the given path,
-// false otherwise
 func FileExists(path string) bool {
 	_, err := os.Stat(path)
 	return os.IsNotExist(err)
 }
 
-// NoopCloser is a simple Reader wrapper that does nothing when Close is
-// called
 type NoopCloser struct {
 	io.Reader
 }
 
-// Close does nothing for a NoopCloser
 func (nc *NoopCloser) Close() error {
 	return nil
 }
 
-// DoHash returns the digest of d using the hashing algorithm named
-// in alg
 func DoHash(alg string, d []byte) []byte {
 	switch alg {
 	case "sha256":
diff --git a/client/client.go b/client/client.go
index a1541809..ca57a89f 100644
--- a/client/client.go
+++ b/client/client.go
@@ -69,7 +69,7 @@ type NotaryRepository struct {
 	tufRepoPath     string
 	fileStore       store.MetadataStore
 	cryptoService   signed.CryptoService
-	tufRepo         *tuf.Repo
+	tufRepo         *tuf.TufRepo
 	roundTrip       http.RoundTripper
 	KeyStoreManager *keystoremanager.KeyStoreManager
 }
@@ -214,7 +214,7 @@ func (r *NotaryRepository) Initialize(uCryptoService *cryptoservice.UnlockedCryp
 		return err
 	}
 
-	r.tufRepo = tuf.NewRepo(kdb, r.cryptoService)
+	r.tufRepo = tuf.NewTufRepo(kdb, r.cryptoService)
 
 	err = r.tufRepo.InitRoot(false)
 	if err != nil {
@@ -461,7 +461,7 @@ func (r *NotaryRepository) Publish() error {
 
 func (r *NotaryRepository) bootstrapRepo() error {
 	kdb := keys.NewDB()
-	tufRepo := tuf.NewRepo(kdb, r.cryptoService)
+	tufRepo := tuf.NewTufRepo(kdb, r.cryptoService)
 
 	logrus.Debugf("Loading trusted collection.")
 	rootJSON, err := r.fileStore.GetMeta("root", 0)
@@ -587,7 +587,7 @@ func (r *NotaryRepository) bootstrapClient() (*tufclient.Client, error) {
 	}
 
 	kdb := keys.NewDB()
-	r.tufRepo = tuf.NewRepo(kdb, r.cryptoService)
+	r.tufRepo = tuf.NewTufRepo(kdb, r.cryptoService)
 
 	signedRoot, err := data.RootFromSigned(root)
 	if err != nil {
diff --git a/client/helpers.go b/client/helpers.go
index 8bfd8c63..50be86c6 100644
--- a/client/helpers.go
+++ b/client/helpers.go
@@ -25,7 +25,7 @@ func getRemoteStore(baseURL, gun string, rt http.RoundTripper) (store.RemoteStor
 	)
 }
 
-func applyChangelist(repo *tuf.Repo, cl changelist.Changelist) error {
+func applyChangelist(repo *tuf.TufRepo, cl changelist.Changelist) error {
 	it, err := cl.NewIterator()
 	if err != nil {
 		return err
@@ -53,7 +53,7 @@ func applyChangelist(repo *tuf.Repo, cl changelist.Changelist) error {
 	return nil
 }
 
-func applyTargetsChange(repo *tuf.Repo, c changelist.Change) error {
+func applyTargetsChange(repo *tuf.TufRepo, c changelist.Change) error {
 	var err error
 	switch c.Action() {
 	case changelist.ActionCreate:
@@ -77,7 +77,7 @@ func applyTargetsChange(repo *tuf.Repo, c changelist.Change) error {
 	return nil
 }
 
-func applyRootChange(repo *tuf.Repo, c changelist.Change) error {
+func applyRootChange(repo *tuf.TufRepo, c changelist.Change) error {
 	var err error
 	switch c.Type() {
 	case changelist.TypeRootRole:
@@ -88,7 +88,7 @@ func applyRootChange(repo *tuf.Repo, c changelist.Change) error {
 	return err // might be nil
 }
 
-func applyRootRoleChange(repo *tuf.Repo, c changelist.Change) error {
+func applyRootRoleChange(repo *tuf.TufRepo, c changelist.Change) error {
 	switch c.Action() {
 	case changelist.ActionCreate:
 		// replaces all keys for a role
diff --git a/cmd/notary-signer/main.go b/cmd/notary-signer/main.go
index 83dc413c..4a86dde9 100644
--- a/cmd/notary-signer/main.go
+++ b/cmd/notary-signer/main.go
@@ -1,8 +1,6 @@
 package main
 
 import (
-	"crypto/rand"
-	"crypto/tls"
 	"database/sql"
 	"errors"
 	_ "expvar"
@@ -22,6 +20,7 @@ import (
 	"github.com/docker/notary/cryptoservice"
 	"github.com/docker/notary/signer"
 	"github.com/docker/notary/signer/api"
+	"github.com/docker/notary/utils"
 	"github.com/docker/notary/version"
 	"github.com/endophage/gotuf/data"
 	_ "github.com/go-sql-driver/mysql"
@@ -103,20 +102,13 @@ func main() {
 		log.Fatalf("Certificate and key are mandatory")
 	}
 
-	tlsConfig := &tls.Config{
-		MinVersion:               tls.VersionTLS12,
-		PreferServerCipherSuites: true,
-		CipherSuites: []uint16{
-			tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-			tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
-			tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-			tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
-			tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
-			tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
-			tls.TLS_RSA_WITH_AES_128_CBC_SHA,
-			tls.TLS_RSA_WITH_AES_256_CBC_SHA},
+	tlsConfig, err := utils.ConfigureServerTLS(&utils.ServerTLSOpts{
+		ServerCertFile: certFile,
+		ServerKeyFile:  keyFile,
+	})
+	if err != nil {
+		logrus.Fatalf("Unable to set up TLS: %s", err.Error())
 	}
-	tlsConfig.Rand = rand.Reader
 
 	cryptoServices := make(signer.CryptoServiceIndex)
 
diff --git a/cmd/notary/tuf.go b/cmd/notary/tuf.go
index 40f5191c..b3cd58e3 100644
--- a/cmd/notary/tuf.go
+++ b/cmd/notary/tuf.go
@@ -3,8 +3,6 @@ package main
 import (
 	"bufio"
 	"crypto/sha256"
-	"crypto/tls"
-	"crypto/x509"
 	"fmt"
 	"io/ioutil"
 	"net"
@@ -22,7 +20,7 @@ import (
 	"github.com/docker/distribution/registry/client/transport"
 	"github.com/docker/docker/pkg/term"
 	notaryclient "github.com/docker/notary/client"
-	"github.com/docker/notary/trustmanager"
+	"github.com/docker/notary/utils"
 	"github.com/spf13/cobra"
 )
 
@@ -360,7 +358,6 @@ func (ps passwordStore) Basic(u *url.URL) (string, string) {
 
 func getTransport(gun string, readOnly bool) http.RoundTripper {
 	// Attempt to get a root CA from the config file. Nil is the host defaults.
-	rootPool := x509.NewCertPool()
 	rootCAFile := mainViper.GetString("remote_server.root_ca")
 	if rootCAFile != "" {
 		// If we haven't been given an Absolute path, we assume it's relative
@@ -368,19 +365,18 @@ func getTransport(gun string, readOnly bool) http.RoundTripper {
 		if !filepath.IsAbs(rootCAFile) {
 			rootCAFile = filepath.Join(configPath, rootCAFile)
 		}
-		rootCert, err := trustmanager.LoadCertFromFile(rootCAFile)
-		if err != nil {
-			fatalf("could not load root ca file. %s", err.Error())
-		}
-		rootPool.AddCert(rootCert)
 	}
 
-	// skipTLSVerify is false by default so verification will
-	// be performed.
-	tlsConfig := &tls.Config{
-		InsecureSkipVerify: mainViper.GetBool("remote_server.skipTLSVerify"),
-		MinVersion:         tls.VersionTLS10,
-		RootCAs:            rootPool,
+	insecureSkipVerify := false
+	if mainViper.IsSet("remote_server.skipTLSVerify") {
+		insecureSkipVerify = mainViper.GetBool("remote_server.skipTLSVerify")
+	}
+	tlsConfig, err := utils.ConfigureClientTLS(&utils.ClientTLSOpts{
+		RootCAFile:         rootCAFile,
+		InsecureSkipVerify: insecureSkipVerify,
+	})
+	if err != nil {
+		logrus.Fatal("Unable to configure TLS: ", err.Error())
 	}
 
 	base := &http.Transport{
diff --git a/server/handlers/validation.go b/server/handlers/validation.go
index 13d355c5..c3c7344e 100644
--- a/server/handlers/validation.go
+++ b/server/handlers/validation.go
@@ -67,7 +67,7 @@ func (err ErrBadSnapshot) Error() string {
 // are semantically correct and the signatures are correct
 func validateUpdate(gun string, updates []storage.MetaUpdate, store storage.MetaStore) error {
 	kdb := keys.NewDB()
-	repo := tuf.NewRepo(kdb, nil)
+	repo := tuf.NewTufRepo(kdb, nil)
 	rootRole := data.RoleName(data.CanonicalRootRole)
 	targetsRole := data.RoleName(data.CanonicalTargetsRole)
 	snapshotRole := data.RoleName(data.CanonicalSnapshotRole)
diff --git a/server/server.go b/server/server.go
index bee1b701..cc8e29de 100644
--- a/server/server.go
+++ b/server/server.go
@@ -1,7 +1,6 @@
 package server
 
 import (
-	"crypto/rand"
 	"crypto/tls"
 	"fmt"
 	"net"
@@ -42,27 +41,13 @@ func Run(ctx context.Context, addr, tlsCertFile, tlsKeyFile string, trust signed
 	}
 
 	if tlsCertFile != "" && tlsKeyFile != "" {
-		keypair, err := tls.LoadX509KeyPair(tlsCertFile, tlsKeyFile)
+		tlsConfig, err := utils.ConfigureServerTLS(&utils.ServerTLSOpts{
+			ServerCertFile: tlsCertFile,
+			ServerKeyFile:  tlsKeyFile,
+		})
 		if err != nil {
 			return err
 		}
-		tlsConfig := &tls.Config{
-			MinVersion:               tls.VersionTLS12,
-			PreferServerCipherSuites: true,
-			CipherSuites: []uint16{
-				tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-				tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
-				tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-				tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
-				tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
-				tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
-				tls.TLS_RSA_WITH_AES_128_CBC_SHA,
-				tls.TLS_RSA_WITH_AES_256_CBC_SHA,
-			},
-			Certificates: []tls.Certificate{keypair},
-			Rand:         rand.Reader,
-		}
-
 		logrus.Info("Enabling TLS")
 		lsnr = tls.NewListener(lsnr, tlsConfig)
 	} else if tlsCertFile != "" || tlsKeyFile != "" {
diff --git a/signer/signer_trust.go b/signer/signer_trust.go
index 07ad56ec..448a1767 100644
--- a/signer/signer_trust.go
+++ b/signer/signer_trust.go
@@ -7,6 +7,7 @@ import (
 
 	"github.com/Sirupsen/logrus"
 	pb "github.com/docker/notary/proto"
+	"github.com/docker/notary/utils"
 	"github.com/endophage/gotuf/data"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc"
@@ -30,10 +31,14 @@ type NotarySigner struct {
 func NewNotarySigner(hostname string, port string, tlscafile string) *NotarySigner {
 	var opts []grpc.DialOption
 	netAddr := net.JoinHostPort(hostname, port)
-	creds, err := credentials.NewClientTLSFromFile(tlscafile, hostname)
+	tlsConfig, err := utils.ConfigureClientTLS(&utils.ClientTLSOpts{
+		RootCAFile: tlscafile,
+		ServerName: hostname,
+	})
 	if err != nil {
-		logrus.Fatal("fail to read: ", err)
+		logrus.Fatal("Unable to set up TLS: ", err)
 	}
+	creds := credentials.NewTLS(tlsConfig)
 	opts = append(opts, grpc.WithTransportCredentials(creds))
 	conn, err := grpc.Dial(netAddr, opts...)
 
diff --git a/trustmanager/x509filestore.go b/trustmanager/x509filestore.go
index 1df62331..84178055 100644
--- a/trustmanager/x509filestore.go
+++ b/trustmanager/x509filestore.go
@@ -260,6 +260,12 @@ func (s *X509FileStore) GetVerifyOptions(dnsName string) (x509.VerifyOptions, er
 	return opts, nil
 }
 
+// Empty returns true if there are no certificates in the X509FileStore, false
+// otherwise.
+func (s *X509FileStore) Empty() bool {
+	return len(s.fingerprintMap) == 0
+}
+
 func fileName(cert *x509.Certificate) (string, CertID, error) {
 	certID, err := fingerprintCert(cert)
 	if err != nil {
diff --git a/trustmanager/x509utils.go b/trustmanager/x509utils.go
index eac624f7..2661c767 100644
--- a/trustmanager/x509utils.go
+++ b/trustmanager/x509utils.go
@@ -370,7 +370,7 @@ func GenerateED25519Key(random io.Reader) (data.PrivateKey, error) {
 	return tufPrivKey, nil
 }
 
-// ECDSAToPrivateKey converts an ecdsa.Private key to a TUF data.PrivateKey type
+// ECDSAToPrivateKey converts an rsa.Private key to a TUF data.PrivateKey type
 func ECDSAToPrivateKey(ecdsaPrivKey *ecdsa.PrivateKey) (data.PrivateKey, error) {
 	// Get a DER-encoded representation of the PublicKey
 	ecdsaPubBytes, err := x509.MarshalPKIXPublicKey(&ecdsaPrivKey.PublicKey)
@@ -443,33 +443,29 @@ func EncryptPrivateKey(key data.PrivateKey, passphrase string) ([]byte, error) {
 	return pem.EncodeToMemory(encryptedPEMBlock), nil
 }
 
-// CertToKey transforms a single input certificate into its corresponding
-// PublicKey
-func CertToKey(cert *x509.Certificate) data.PublicKey {
-	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")
-	}
-
-	return data.NewPublicKey(keyType, pemdata)
-}
-
 // 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 {
-		newKey := CertToKey(cert)
+		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
 }
 
@@ -499,26 +495,3 @@ func NewCertificate(gun string) (*x509.Certificate, error) {
 		BasicConstraintsValid: true,
 	}, nil
 }
-
-// X509PublicKeyID returns a public key ID as a string, given a
-// data.PublicKey that contains an X509 Certificate
-func X509PublicKeyID(certPubKey data.PublicKey) (string, error) {
-	cert, err := LoadCertFromPEM(certPubKey.Public())
-	if err != nil {
-		return "", err
-	}
-	var finalAlgorithm data.KeyAlgorithm
-
-	switch certPubKey.Algorithm() {
-	case data.ECDSAx509Key:
-		finalAlgorithm = data.ECDSAKey
-	case data.RSAx509Key:
-		finalAlgorithm = data.RSAKey
-	}
-
-	pubKeyBytes, err := x509.MarshalPKIXPublicKey(cert.PublicKey)
-	if err != nil {
-		return "", err
-	}
-	return data.NewPublicKey(finalAlgorithm, pubKeyBytes).ID(), nil
-}
diff --git a/utils/tls_config.go b/utils/tls_config.go
new file mode 100644
index 00000000..15050f84
--- /dev/null
+++ b/utils/tls_config.go
@@ -0,0 +1,133 @@
+package utils
+
+import (
+	"crypto/rand"
+	"crypto/tls"
+	"crypto/x509"
+	"fmt"
+	"io/ioutil"
+)
+
+// Client TLS cipher suites (dropping CBC ciphers for client preferred suite set)
+var clientCipherSuites = []uint16{
+	tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+}
+
+// Server TLS cipher suites
+var serverCipherSuites = append(clientCipherSuites, []uint16{
+	tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+	tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+	tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+	tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+	tls.TLS_RSA_WITH_AES_256_CBC_SHA,
+	tls.TLS_RSA_WITH_AES_128_CBC_SHA,
+}...)
+
+func poolFromFile(filename string) (*x509.CertPool, error) {
+	pemBytes, err := ioutil.ReadFile(filename)
+	if err != nil {
+		return nil, err
+	}
+	pool := x509.NewCertPool()
+	if ok := pool.AppendCertsFromPEM(pemBytes); !ok {
+		return nil, fmt.Errorf(
+			"Unable to parse certificates from %s", filename)
+	}
+	if len(pool.Subjects()) == 0 {
+		return nil, fmt.Errorf(
+			"No certificates parsed from %s", filename)
+	}
+	return pool, nil
+}
+
+// ServerTLSOpts generates a tls configuration for servers using the
+// provided parameters.
+type ServerTLSOpts struct {
+	ServerCertFile    string
+	ServerKeyFile     string
+	RequireClientAuth bool
+	ClientCAFile      string
+}
+
+// ConfigureServerTLS specifies a set of ciphersuites, the server cert and key,
+// and optionally client authentication.  Note that a tls configuration is
+// constructed that either requires and verifies client authentication or
+// doesn't deal with client certs at all. Nothing in the middle.
+//
+// Also note that if the client CA file contains invalid data, behavior is not
+// guaranteed.  Currently (as of Go 1.5.1) only the valid certificates up to
+// the bad data will be parsed and added the client CA pool.
+func ConfigureServerTLS(opts *ServerTLSOpts) (*tls.Config, error) {
+	keypair, err := tls.LoadX509KeyPair(
+		opts.ServerCertFile, opts.ServerKeyFile)
+	if err != nil {
+		return nil, err
+	}
+
+	tlsConfig := &tls.Config{
+		MinVersion:               tls.VersionTLS12,
+		PreferServerCipherSuites: true,
+		CipherSuites:             serverCipherSuites,
+		Certificates:             []tls.Certificate{keypair},
+		Rand:                     rand.Reader,
+	}
+
+	if opts.RequireClientAuth {
+		tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
+	}
+
+	if opts.ClientCAFile != "" {
+		pool, err := poolFromFile(opts.ClientCAFile)
+		if err != nil {
+			return nil, err
+		}
+		tlsConfig.ClientCAs = pool
+	}
+
+	return tlsConfig, nil
+}
+
+// ClientTLSOpts is a struct that contains options to pass to
+// ConfigureClientTLS
+type ClientTLSOpts struct {
+	RootCAFile         string
+	ServerName         string
+	InsecureSkipVerify bool
+	ClientCertFile     string
+	ClientKeyFile      string
+}
+
+// ConfigureClientTLS generates a tls configuration for clients using the
+// provided parameters.
+///
+// Note that if the root CA file contains invalid data, behavior is not
+// guaranteed.  Currently (as of Go 1.5.1) only the valid certificates up to
+// the bad data will be parsed and added the root CA pool.
+func ConfigureClientTLS(opts *ClientTLSOpts) (*tls.Config, error) {
+	tlsConfig := &tls.Config{
+		InsecureSkipVerify: opts.InsecureSkipVerify,
+		MinVersion:         tls.VersionTLS12,
+		CipherSuites:       clientCipherSuites,
+		ServerName:         opts.ServerName,
+	}
+
+	if opts.RootCAFile != "" {
+		pool, err := poolFromFile(opts.RootCAFile)
+		if err != nil {
+			return nil, err
+		}
+		tlsConfig.RootCAs = pool
+	}
+
+	if opts.ClientCertFile != "" || opts.ClientKeyFile != "" {
+		keypair, err := tls.LoadX509KeyPair(
+			opts.ClientCertFile, opts.ClientKeyFile)
+		if err != nil {
+			return nil, err
+		}
+		tlsConfig.Certificates = []tls.Certificate{keypair}
+	}
+
+	return tlsConfig, nil
+}


Test patch:
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/testutils/repo.go b/Godeps/_workspace/src/github.com/endophage/gotuf/testutils/repo.go
index 45171419..3fa9c1f6 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/testutils/repo.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/testutils/repo.go
@@ -16,10 +16,10 @@ import (
 
 // EmptyRepo creates an in memory key database, crypto service
 // and initializes a repo with no targets or delegations.
-func EmptyRepo() (*keys.KeyDB, *tuf.Repo, signed.CryptoService) {
+func EmptyRepo() (*keys.KeyDB, *tuf.TufRepo, signed.CryptoService) {
 	c := signed.NewEd25519()
 	kdb := keys.NewDB()
-	r := tuf.NewRepo(kdb, c)
+	r := tuf.NewTufRepo(kdb, c)
 
 	for _, role := range []string{"root", "targets", "snapshot", "timestamp"} {
 		key, _ := c.Create(role, data.ED25519Key)
@@ -32,8 +32,7 @@ func EmptyRepo() (*keys.KeyDB, *tuf.Repo, signed.CryptoService) {
 	return kdb, r, c
 }
 
-// AddTarget generates a fake target and adds it to a repo.
-func AddTarget(role string, r *tuf.Repo) (name string, meta data.FileMeta, content []byte, err error) {
+func AddTarget(role string, r *tuf.TufRepo) (name string, meta data.FileMeta, content []byte, err error) {
 	randness := fuzz.Continue{}
 	content = RandomByteSlice(1024)
 	name = randness.RandString()
@@ -49,7 +48,6 @@ func AddTarget(role string, r *tuf.Repo) (name string, meta data.FileMeta, conte
 	return
 }
 
-// RandomByteSlice generates some random data to be used for testing only
 func RandomByteSlice(maxSize int) []byte {
 	r := rand.New(rand.NewSource(time.Now().UnixNano()))
 	contentSize := r.Intn(maxSize)
@@ -60,8 +58,7 @@ func RandomByteSlice(maxSize int) []byte {
 	return content
 }
 
-// Sign signs all top level roles in a repo in the appropriate order
-func Sign(repo *tuf.Repo) (root, targets, snapshot, timestamp *data.Signed, err error) {
+func Sign(repo *tuf.TufRepo) (root, targets, snapshot, timestamp *data.Signed, err error) {
 	root, err = repo.SignRoot(data.DefaultExpires("root"), nil)
 	if err != nil {
 		return nil, nil, nil, nil, err
@@ -81,7 +78,6 @@ func Sign(repo *tuf.Repo) (root, targets, snapshot, timestamp *data.Signed, err
 	return
 }
 
-// Serialize takes the Signed objects for the 4 top level roles and serializes them all to JSON
 func Serialize(sRoot, sTargets, sSnapshot, sTimestamp *data.Signed) (root, targets, snapshot, timestamp []byte, err error) {
 	root, err = json.Marshal(sRoot)
 	if err != nil {
diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/testutils/utils.go b/Godeps/_workspace/src/github.com/endophage/gotuf/testutils/utils.go
index 2dec7ce4..59e0bdbd 100644
--- a/Godeps/_workspace/src/github.com/endophage/gotuf/testutils/utils.go
+++ b/Godeps/_workspace/src/github.com/endophage/gotuf/testutils/utils.go
@@ -6,13 +6,11 @@ import (
 	"os"
 
 	"github.com/endophage/gotuf/data"
-	// need to initialize sqlite for tests
 	_ "github.com/mattn/go-sqlite3"
 )
 
-var counter = 1
+var counter int = 1
 
-// SampleMeta returns a static, fake (and invalid) FileMeta object
 func SampleMeta() data.FileMeta {
 	meta := data.FileMeta{
 		Length: 1,
@@ -24,7 +22,6 @@ func SampleMeta() data.FileMeta {
 	return meta
 }
 
-// GetSqliteDB creates and initializes a sqlite db
 func GetSqliteDB() *sql.DB {
 	os.Mkdir("/tmp/sqlite", 0755)
 	conn, err := sql.Open("sqlite3", fmt.Sprintf("/tmp/sqlite/file%d.db", counter))
@@ -43,7 +40,6 @@ func GetSqliteDB() *sql.DB {
 	return conn
 }
 
-// FlushDB deletes a sqliteDB
 func FlushDB(db *sql.DB) {
 	tx, _ := db.Begin()
 	tx.Exec("DELETE FROM `filemeta`")
diff --git a/client/helpers_test.go b/client/helpers_test.go
index 6f50d283..eb911e4f 100644
--- a/client/helpers_test.go
+++ b/client/helpers_test.go
@@ -18,7 +18,7 @@ func TestApplyTargetsChange(t *testing.T) {
 	assert.NoError(t, err)
 	kdb.AddRole(role)
 
-	repo := tuf.NewRepo(kdb, nil)
+	repo := tuf.NewTufRepo(kdb, nil)
 	err = repo.InitTargets()
 	assert.NoError(t, err)
 	hash := sha256.Sum256([]byte{})
@@ -61,7 +61,7 @@ func TestApplyChangelist(t *testing.T) {
 	assert.NoError(t, err)
 	kdb.AddRole(role)
 
-	repo := tuf.NewRepo(kdb, nil)
+	repo := tuf.NewTufRepo(kdb, nil)
 	err = repo.InitTargets()
 	assert.NoError(t, err)
 	hash := sha256.Sum256([]byte{})
@@ -109,7 +109,7 @@ func TestApplyChangelistMulti(t *testing.T) {
 	assert.NoError(t, err)
 	kdb.AddRole(role)
 
-	repo := tuf.NewRepo(kdb, nil)
+	repo := tuf.NewTufRepo(kdb, nil)
 	err = repo.InitTargets()
 	assert.NoError(t, err)
 	hash := sha256.Sum256([]byte{})
diff --git a/signer/signer_trust_test.go b/signer/signer_trust_test.go
index bcbba05b..4b5ccef4 100644
--- a/signer/signer_trust_test.go
+++ b/signer/signer_trust_test.go
@@ -40,7 +40,7 @@ func stubHealthFunction(t *testing.T, status map[string]string, err error) rpcHe
 		_, withDeadline := ctx.Deadline()
 		assert.True(t, withDeadline)
 
-		return &pb.HealthStatus{status}, err
+		return &pb.HealthStatus{Status: status}, err
 	}
 }
 
diff --git a/trustmanager/x509filestore_test.go b/trustmanager/x509filestore_test.go
index 21b1a0b3..58decfc7 100644
--- a/trustmanager/x509filestore_test.go
+++ b/trustmanager/x509filestore_test.go
@@ -5,6 +5,7 @@ import (
 	"encoding/pem"
 	"io/ioutil"
 	"os"
+	"path/filepath"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
@@ -22,6 +23,44 @@ func TestNewX509FileStore(t *testing.T) {
 	}
 }
 
+// NewX509FileStore loads any existing certs from the directory, and does
+// not overwrite any of the.
+func TestNewX509FileStoreLoadsExistingCerts(t *testing.T) {
+	tempDir, err := ioutil.TempDir("", "cert-test")
+	assert.NoError(t, err)
+	defer os.RemoveAll(tempDir)
+
+	certBytes, err := ioutil.ReadFile("../fixtures/root-ca.crt")
+	assert.NoError(t, err)
+	out, err := os.Create(filepath.Join(tempDir, "root-ca.crt"))
+	assert.NoError(t, err)
+
+	// to distinguish it from the canonical format
+	distinguishingBytes := []byte{'\n', '\n', '\n', '\n', '\n', '\n'}
+	nBytes, err := out.Write(distinguishingBytes)
+	assert.NoError(t, err)
+	assert.Len(t, distinguishingBytes, nBytes)
+
+	nBytes, err = out.Write(certBytes)
+	assert.NoError(t, err)
+	assert.Len(t, certBytes, nBytes)
+
+	err = out.Close()
+	assert.NoError(t, err)
+
+	store, err := NewX509FileStore(tempDir)
+	assert.NoError(t, err)
+
+	expectedCert, err := LoadCertFromFile("../fixtures/root-ca.crt")
+	assert.NoError(t, err)
+	assert.Equal(t, []*x509.Certificate{expectedCert}, store.GetCertificates())
+
+	outBytes, err := ioutil.ReadFile(filepath.Join(tempDir, "root-ca.crt"))
+	assert.NoError(t, err)
+	assert.Equal(t, distinguishingBytes, outBytes[:6], "original file overwritten")
+	assert.Equal(t, certBytes, outBytes[6:], "original file overwritten")
+}
+
 func TestAddCertX509FileStore(t *testing.T) {
 	// Read certificate from file
 	b, err := ioutil.ReadFile("../fixtures/root-ca.crt")
@@ -82,6 +121,21 @@ func TestAddCertFromFileX509FileStore(t *testing.T) {
 	}
 }
 
+// TestNewX509FileStoreEmpty verifies the behavior of the Empty function
+func TestNewX509FileStoreEmpty(t *testing.T) {
+	tempDir, err := ioutil.TempDir("", "cert-test")
+	assert.NoError(t, err)
+	defer os.RemoveAll(tempDir)
+
+	store, err := NewX509FileStore(tempDir)
+	assert.NoError(t, err)
+	assert.True(t, store.Empty())
+
+	err = store.AddCertFromFile("../fixtures/root-ca.crt")
+	assert.NoError(t, err)
+	assert.False(t, store.Empty())
+}
+
 func TestAddCertFromPEMX509FileStore(t *testing.T) {
 	b, err := ioutil.ReadFile("../fixtures/root-ca.crt")
 	if err != nil {
diff --git a/trustmanager/x509utils_test.go b/trustmanager/x509utils_test.go
index db7ef3ac..78830089 100644
--- a/trustmanager/x509utils_test.go
+++ b/trustmanager/x509utils_test.go
@@ -1,16 +1,12 @@
 package trustmanager
 
 import (
-	"crypto/ecdsa"
-	"crypto/elliptic"
 	"crypto/rand"
 	"crypto/x509"
-	"io/ioutil"
 	"strings"
 	"testing"
 	"time"
 
-	"github.com/endophage/gotuf/data"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -148,56 +144,3 @@ func TestKeyOperations(t *testing.T) {
 	assert.Equal(t, rsaKey.Private(), decryptedRSAKey.Private())
 
 }
-
-// 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)
-}
-
-// X509PublickeyID returns the public key ID of an ECDSA X509 key rather than
-// the cert ID
-func TestECDSAX509PublickeyID(t *testing.T) {
-	template, err := NewCertificate("something")
-	assert.NoError(t, err)
-	template.SignatureAlgorithm = x509.ECDSAWithSHA256
-	template.PublicKeyAlgorithm = x509.ECDSA
-
-	privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
-	assert.NoError(t, err)
-
-	tufPrivKey, err := ECDSAToPrivateKey(privKey)
-	assert.NoError(t, err)
-
-	derBytes, err := x509.CreateCertificate(
-		rand.Reader, template, template, &privKey.PublicKey, privKey)
-	assert.NoError(t, err)
-
-	cert, err := x509.ParseCertificate(derBytes)
-	assert.NoError(t, err)
-
-	tufKey := CertToKey(cert)
-	tufID, err := X509PublicKeyID(tufKey)
-	assert.NoError(t, err)
-
-	assert.Equal(t, tufPrivKey.ID(), tufID)
-}
diff --git a/utils/tls_config_test.go b/utils/tls_config_test.go
new file mode 100644
index 00000000..75c53e88
--- /dev/null
+++ b/utils/tls_config_test.go
@@ -0,0 +1,253 @@
+package utils
+
+import (
+	"crypto"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/tls"
+	"crypto/x509"
+	"io/ioutil"
+	"os"
+	"testing"
+
+	"github.com/docker/notary/trustmanager"
+	"github.com/stretchr/testify/assert"
+)
+
+const (
+	ServerCert = "../fixtures/notary-server.crt"
+	ServerKey  = "../fixtures/notary-server.key"
+	RootCA     = "../fixtures/root-ca.crt"
+)
+
+// generates a multiple-certificate file with both RSA and ECDSA certs and
+// returns the filename so that cleanup can be deferred.
+func generateMultiCert(t *testing.T) string {
+	tempFile, err := ioutil.TempFile("/tmp", "cert-test")
+	defer tempFile.Close()
+	assert.NoError(t, err)
+
+	rsaKey, err := rsa.GenerateKey(rand.Reader, 2048)
+	assert.NoError(t, err)
+	ecKey, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
+	assert.NoError(t, err)
+	template, err := trustmanager.NewCertificate("gun")
+	assert.NoError(t, err)
+
+	for _, key := range []crypto.Signer{rsaKey, ecKey} {
+		derBytes, err := x509.CreateCertificate(
+			rand.Reader, template, template, key.Public(), key)
+		assert.NoError(t, err)
+
+		cert, err := x509.ParseCertificate(derBytes)
+		assert.NoError(t, err)
+
+		pemBytes := trustmanager.CertToPEM(cert)
+		nBytes, err := tempFile.Write(pemBytes)
+		assert.NoError(t, err)
+		assert.Equal(t, nBytes, len(pemBytes))
+	}
+	return tempFile.Name()
+}
+
+// If the cert files and directory are provided but are invalid, an error is
+// returned.
+func TestConfigServerTLSFailsIfUnableToLoadCerts(t *testing.T) {
+	for i := 0; i < 3; i++ {
+		files := []string{ServerCert, ServerKey, RootCA}
+		files[i] = "not-real-file"
+
+		result, err := ConfigureServerTLS(&ServerTLSOpts{
+			ServerCertFile:    files[0],
+			ServerKeyFile:     files[1],
+			RequireClientAuth: true,
+			ClientCAFile:      files[2],
+		})
+		assert.Nil(t, result)
+		assert.Error(t, err)
+	}
+}
+
+// If server cert and key are provided, and client auth is disabled, then
+// a valid tls.Config is returned with ClientAuth set to NoClientCert
+func TestConfigServerTLSServerCertsOnly(t *testing.T) {
+	keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
+	assert.NoError(t, err)
+
+	tlsConfig, err := ConfigureServerTLS(&ServerTLSOpts{
+		ServerCertFile: ServerCert,
+		ServerKeyFile:  ServerKey,
+	})
+	assert.NoError(t, err)
+	assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
+	assert.True(t, tlsConfig.PreferServerCipherSuites)
+	assert.Equal(t, tls.NoClientCert, tlsConfig.ClientAuth)
+	assert.Nil(t, tlsConfig.ClientCAs)
+}
+
+// If a valid client cert file is provided, but it contains no client
+// certs, an error is returned.
+func TestConfigServerTLSWithEmptyCACertFile(t *testing.T) {
+	tempFile, err := ioutil.TempFile("/tmp", "cert-test")
+	assert.NoError(t, err)
+	defer os.RemoveAll(tempFile.Name())
+	tempFile.Close()
+
+	tlsConfig, err := ConfigureServerTLS(&ServerTLSOpts{
+		ServerCertFile: ServerCert,
+		ServerKeyFile:  ServerKey,
+		ClientCAFile:   tempFile.Name(),
+	})
+	assert.Nil(t, tlsConfig)
+	assert.Error(t, err)
+}
+
+// If server cert and key are provided, and client cert file is provided with
+// one cert, a valid tls.Config is returned with the clientCAs set to that
+// cert.
+func TestConfigServerTLSWithOneCACert(t *testing.T) {
+	keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
+	assert.NoError(t, err)
+
+	tlsConfig, err := ConfigureServerTLS(&ServerTLSOpts{
+		ServerCertFile: ServerCert,
+		ServerKeyFile:  ServerKey,
+		ClientCAFile:   RootCA,
+	})
+	assert.NoError(t, err)
+	assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
+	assert.True(t, tlsConfig.PreferServerCipherSuites)
+	assert.Equal(t, tls.NoClientCert, tlsConfig.ClientAuth)
+	assert.Len(t, tlsConfig.ClientCAs.Subjects(), 1)
+}
+
+// If server cert and key are provided, and client cert file is provided with
+// multiple certs, a valid tls.Config is returned with the clientCAs set to
+// the valid cert.
+func TestConfigServerTLSWithMultipleCACerts(t *testing.T) {
+	tempFilename := generateMultiCert(t)
+	defer os.RemoveAll(tempFilename)
+
+	keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
+	assert.NoError(t, err)
+
+	tlsConfig, err := ConfigureServerTLS(&ServerTLSOpts{
+		ServerCertFile: ServerCert,
+		ServerKeyFile:  ServerKey,
+		ClientCAFile:   tempFilename,
+	})
+	assert.NoError(t, err)
+	assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
+	assert.True(t, tlsConfig.PreferServerCipherSuites)
+	assert.Equal(t, tls.NoClientCert, tlsConfig.ClientAuth)
+	assert.Len(t, tlsConfig.ClientCAs.Subjects(), 2)
+}
+
+// If server cert and key are provided, and client auth is disabled, then
+// a valid tls.Config is returned with ClientAuth set to
+// RequireAndVerifyClientCert
+func TestConfigServerTLSClientAuthEnabled(t *testing.T) {
+	keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
+	assert.NoError(t, err)
+
+	tlsConfig, err := ConfigureServerTLS(&ServerTLSOpts{
+		ServerCertFile:    ServerCert,
+		ServerKeyFile:     ServerKey,
+		RequireClientAuth: true,
+	})
+	assert.NoError(t, err)
+	assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
+	assert.True(t, tlsConfig.PreferServerCipherSuites)
+	assert.Equal(t, tls.RequireAndVerifyClientCert, tlsConfig.ClientAuth)
+	assert.Nil(t, tlsConfig.ClientCAs)
+}
+
+// The skipVerify boolean gets set on the tls.Config's InsecureSkipBoolean
+func TestConfigClientTLSNoVerify(t *testing.T) {
+	for _, skip := range []bool{true, false} {
+		tlsConfig, err := ConfigureClientTLS(
+			&ClientTLSOpts{InsecureSkipVerify: skip})
+		assert.NoError(t, err)
+		assert.Nil(t, tlsConfig.Certificates)
+		assert.Equal(t, skip, tlsConfig.InsecureSkipVerify)
+		assert.Equal(t, "", tlsConfig.ServerName)
+		assert.Nil(t, tlsConfig.RootCAs)
+	}
+}
+
+// The skipVerify boolean gets set on the tls.Config's InsecureSkipBoolean
+func TestConfigClientServerName(t *testing.T) {
+	for _, name := range []string{"", "myname"} {
+		tlsConfig, err := ConfigureClientTLS(&ClientTLSOpts{ServerName: name})
+		assert.NoError(t, err)
+		assert.Nil(t, tlsConfig.Certificates)
+		assert.Equal(t, false, tlsConfig.InsecureSkipVerify)
+		assert.Equal(t, name, tlsConfig.ServerName)
+		assert.Nil(t, tlsConfig.RootCAs)
+	}
+}
+
+// The RootCA is set if the file provided has a single CA cert.
+func TestConfigClientTLSRootCAFileWithOneCert(t *testing.T) {
+	tlsConfig, err := ConfigureClientTLS(&ClientTLSOpts{RootCAFile: RootCA})
+	assert.NoError(t, err)
+	assert.Nil(t, tlsConfig.Certificates)
+	assert.Equal(t, false, tlsConfig.InsecureSkipVerify)
+	assert.Equal(t, "", tlsConfig.ServerName)
+	assert.Len(t, tlsConfig.RootCAs.Subjects(), 1)
+}
+
+// If the root CA file provided has multiple CA certs, only the valid certs
+// are read.
+func TestConfigClientTLSRootCAFileMultipleCerts(t *testing.T) {
+	tempFilename := generateMultiCert(t)
+	defer os.RemoveAll(tempFilename)
+
+	tlsConfig, err := ConfigureClientTLS(
+		&ClientTLSOpts{RootCAFile: tempFilename})
+	assert.NoError(t, err)
+	assert.Nil(t, tlsConfig.Certificates)
+	assert.Equal(t, false, tlsConfig.InsecureSkipVerify)
+	assert.Equal(t, "", tlsConfig.ServerName)
+	assert.Len(t, tlsConfig.RootCAs.Subjects(), 2)
+}
+
+// An error is returned if a root CA is provided but the file doesn't exist.
+func TestConfigClientTLSNonexistentRootCAFile(t *testing.T) {
+	tlsConfig, err := ConfigureClientTLS(
+		&ClientTLSOpts{RootCAFile: "not-a-file"})
+	assert.Error(t, err)
+	assert.Nil(t, tlsConfig)
+}
+
+// An error is returned if either the client cert or the key are provided
+// but invalid or blank.
+func TestConfigClientTLSClientCertOrKeyInvalid(t *testing.T) {
+	for i := 0; i < 2; i++ {
+		for _, invalid := range []string{"not-a-file", ""} {
+			files := []string{ServerCert, ServerKey}
+			files[i] = invalid
+			tlsConfig, err := ConfigureClientTLS(&ClientTLSOpts{
+				ClientCertFile: files[0], ClientKeyFile: files[1]})
+			assert.Error(t, err)
+			assert.Nil(t, tlsConfig)
+		}
+	}
+}
+
+// The certificate is set if the client cert and client key are provided and
+// valid.
+func TestConfigClientTLSValidClientCertAndKey(t *testing.T) {
+	keypair, err := tls.LoadX509KeyPair(ServerCert, ServerKey)
+	assert.NoError(t, err)
+
+	tlsConfig, err := ConfigureClientTLS(&ClientTLSOpts{
+		ClientCertFile: ServerCert, ClientKeyFile: ServerKey})
+	assert.NoError(t, err)
+	assert.Equal(t, []tls.Certificate{keypair}, tlsConfig.Certificates)
+	assert.Equal(t, false, tlsConfig.InsecureSkipVerify)
+	assert.Equal(t, "", tlsConfig.ServerName)
+	assert.Nil(t, tlsConfig.RootCAs)
+}