creating concrete types for the various key ciphers

Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
David Lawrence 2015-10-28 16:02:55 -07:00
parent daa36b43b7
commit f73560d839
37 changed files with 550 additions and 332 deletions

View File

@ -38,8 +38,8 @@ type TufChange struct {
// TufRootData represents a modification of the keys associated
// with a role that appears in the root.json
type TufRootData struct {
Keys []data.TUFKey `json:"keys"`
RoleName string `json:"role"`
Keys data.KeyList `json:"keys"`
RoleName string `json:"role"`
}
// NewTufChange initializes a tufChange object

View File

@ -149,20 +149,16 @@ func (r *NotaryRepository) Initialize(uCryptoService *cryptoservice.UnlockedCryp
// If the key is RSA, we store it as type RSAx509, if it is ECDSA we store it
// as ECDSAx509 to allow the gotuf verifiers to correctly decode the
// key on verification of signatures.
var algorithmType data.KeyAlgorithm
algorithm := uCryptoService.PrivKey.Algorithm()
switch algorithm {
var rootKey data.PublicKey
switch uCryptoService.PrivKey.Algorithm() {
case data.RSAKey:
algorithmType = data.RSAx509Key
rootKey = data.NewRSAx509PublicKey(trustmanager.CertToPEM(rootCert))
case data.ECDSAKey:
algorithmType = data.ECDSAx509Key
rootKey = data.NewECDSAx509PublicKey(trustmanager.CertToPEM(rootCert))
default:
return fmt.Errorf("invalid format for root key: %s", algorithm)
return fmt.Errorf("invalid format for root key: %s", uCryptoService.PrivKey.Algorithm())
}
// Generate a x509Key using the rootCert as the public key
rootKey := data.NewPublicKey(algorithmType, trustmanager.CertToPEM(rootCert))
// All the timestamp keys are generated by the remote server.
remote, err := getRemoteStore(r.baseURL, r.gun, r.roundTrip)
if err != nil {
@ -173,15 +169,12 @@ func (r *NotaryRepository) Initialize(uCryptoService *cryptoservice.UnlockedCryp
return err
}
parsedKey := &data.TUFKey{}
err = json.Unmarshal(rawTSKey, parsedKey)
timestampKey, err := data.UnmarshalPublicKey(rawTSKey)
if err != nil {
return err
}
// Turn the JSON timestamp key from the remote server into a TUFKey
timestampKey := data.NewPublicKey(parsedKey.Algorithm(), parsedKey.Public())
logrus.Debugf("got remote %s timestamp key with keyID: %s", parsedKey.Algorithm(), timestampKey.ID())
logrus.Debugf("got remote %s timestamp key with keyID: %s", timestampKey.Algorithm(), timestampKey.ID())
// This is currently hardcoding the targets and snapshots keys to ECDSA
// Targets and snapshot keys are always generated locally.
@ -631,14 +624,9 @@ func (r *NotaryRepository) rootFileKeyChange(role, action string, key data.Publi
}
defer cl.Close()
k, ok := key.(*data.TUFKey)
if !ok {
return errors.New("Invalid key type found during rotation.")
}
meta := changelist.TufRootData{
RoleName: role,
Keys: []data.TUFKey{*k},
Keys: data.KeyList{key},
}
metaJSON, err := json.Marshal(meta)
if err != nil {

View File

@ -28,7 +28,7 @@ func TestValidateRoot(t *testing.T) {
}
}
func validateRootSuccessfully(t *testing.T, rootType data.KeyAlgorithm) {
func validateRootSuccessfully(t *testing.T, rootType string) {
// Temporary directory where test files will be created
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
defer os.RemoveAll(tempBaseDir)
@ -43,7 +43,7 @@ func validateRootSuccessfully(t *testing.T, rootType data.KeyAlgorithm) {
repo, err := NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, passphraseRetriever)
assert.NoError(t, err, "error creating repository: %s", err)
rootKeyID, err := repo.KeyStoreManager.GenRootKey(rootType.String())
rootKeyID, err := repo.KeyStoreManager.GenRootKey(rootType)
assert.NoError(t, err, "error generating root key: %s", err)
rootCryptoService, err := repo.KeyStoreManager.GetRootCryptoService(rootKeyID)
@ -63,10 +63,10 @@ func validateRootSuccessfully(t *testing.T, rootType data.KeyAlgorithm) {
// Now test ListTargets. In preparation, we need to expose some signed
// metadata files on the internal HTTP server.
var tempKey data.TUFKey
json.Unmarshal([]byte(timestampECDSAKeyJSON), &tempKey)
tempKey, err := data.UnmarshalPrivateKey([]byte(timestampECDSAKeyJSON))
assert.NoError(t, err)
repo.KeyStoreManager.KeyStore.AddKey(filepath.Join(filepath.FromSlash(gun), tempKey.ID()), "root", &tempKey)
repo.KeyStoreManager.KeyStore.AddKey(filepath.Join(filepath.FromSlash(gun), tempKey.ID()), "root", tempKey)
// Because ListTargets will clear this
savedTUFRepo := repo.tufRepo

View File

@ -53,7 +53,7 @@ func TestInitRepo(t *testing.T) {
}
}
func testInitRepo(t *testing.T, rootType data.KeyAlgorithm) {
func testInitRepo(t *testing.T, rootType string) {
gun := "docker.com/notary"
// Temporary directory where test files will be created
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
@ -67,7 +67,7 @@ func testInitRepo(t *testing.T, rootType data.KeyAlgorithm) {
repo, err := NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, passphraseRetriever)
assert.NoError(t, err, "error creating repo: %s", err)
rootKeyID, err := repo.KeyStoreManager.GenRootKey(rootType.String())
rootKeyID, err := repo.KeyStoreManager.GenRootKey(rootType)
assert.NoError(t, err, "error generating root key: %s", err)
rootCryptoService, err := repo.KeyStoreManager.GetRootCryptoService(rootKeyID)
@ -180,7 +180,7 @@ func TestAddListTarget(t *testing.T) {
}
}
func testAddListTarget(t *testing.T, rootType data.KeyAlgorithm) {
func testAddListTarget(t *testing.T, rootType string) {
// Temporary directory where test files will be created
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
defer os.RemoveAll(tempBaseDir)
@ -195,7 +195,7 @@ func testAddListTarget(t *testing.T, rootType data.KeyAlgorithm) {
repo, err := NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, passphraseRetriever)
assert.NoError(t, err, "error creating repository: %s", err)
rootKeyID, err := repo.KeyStoreManager.GenRootKey(rootType.String())
rootKeyID, err := repo.KeyStoreManager.GenRootKey(rootType)
assert.NoError(t, err, "error generating root key: %s", err)
rootCryptoService, err := repo.KeyStoreManager.GetRootCryptoService(rootKeyID)
@ -298,10 +298,10 @@ func testAddListTarget(t *testing.T, rootType data.KeyAlgorithm) {
err = applyChangelist(repo.tufRepo, cl)
assert.NoError(t, err, "could not apply changelist")
var tempKey data.TUFKey
json.Unmarshal([]byte(timestampECDSAKeyJSON), &tempKey)
tempKey, err := data.UnmarshalPrivateKey([]byte(timestampECDSAKeyJSON))
assert.NoError(t, err)
repo.KeyStoreManager.KeyStore.AddKey(filepath.Join(filepath.FromSlash(gun), tempKey.ID()), "nonroot", &tempKey)
repo.KeyStoreManager.KeyStore.AddKey(filepath.Join(filepath.FromSlash(gun), tempKey.ID()), "nonroot", tempKey)
// Because ListTargets will clear this
savedTUFRepo := repo.tufRepo
@ -373,7 +373,7 @@ func TestValidateRootKey(t *testing.T) {
}
}
func testValidateRootKey(t *testing.T, rootType data.KeyAlgorithm) {
func testValidateRootKey(t *testing.T, rootType string) {
// Temporary directory where test files will be created
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
defer os.RemoveAll(tempBaseDir)
@ -388,7 +388,7 @@ func testValidateRootKey(t *testing.T, rootType data.KeyAlgorithm) {
repo, err := NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, passphraseRetriever)
assert.NoError(t, err, "error creating repository: %s", err)
rootKeyID, err := repo.KeyStoreManager.GenRootKey(rootType.String())
rootKeyID, err := repo.KeyStoreManager.GenRootKey(rootType)
assert.NoError(t, err, "error generating root key: %s", err)
rootCryptoService, err := repo.KeyStoreManager.GetRootCryptoService(rootKeyID)
@ -438,7 +438,7 @@ func TestPublish(t *testing.T) {
}
}
func testPublish(t *testing.T, rootType data.KeyAlgorithm) {
func testPublish(t *testing.T, rootType string) {
// Temporary directory where test files will be created
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
defer os.RemoveAll(tempBaseDir)
@ -471,7 +471,7 @@ func testPublish(t *testing.T, rootType data.KeyAlgorithm) {
repo, err := NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, passphraseRetriever)
assert.NoError(t, err, "error creating repository: %s", err)
rootKeyID, err := repo.KeyStoreManager.GenRootKey(rootType.String())
rootKeyID, err := repo.KeyStoreManager.GenRootKey(rootType)
assert.NoError(t, err, "error generating root key: %s", err)
rootCryptoService, err := repo.KeyStoreManager.GetRootCryptoService(rootKeyID)
@ -660,7 +660,7 @@ func TestRotate(t *testing.T) {
repo, err := NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, passphraseRetriever)
assert.NoError(t, err, "error creating repository: %s", err)
rootKeyID, err := repo.KeyStoreManager.GenRootKey(data.ECDSAKey.String())
rootKeyID, err := repo.KeyStoreManager.GenRootKey(data.ECDSAKey)
assert.NoError(t, err, "error generating root key: %s", err)
rootCryptoService, err := repo.KeyStoreManager.GetRootCryptoService(rootKeyID)

View File

@ -97,11 +97,7 @@ func applyRootRoleChange(repo *tuf.Repo, c changelist.Change) error {
if err != nil {
return err
}
k := []data.PublicKey{}
for _, key := range d.Keys {
k = append(k, data.NewPublicKey(key.Algorithm(), key.Public()))
}
err = repo.ReplaceBaseKeys(d.RoleName, k...)
err = repo.ReplaceBaseKeys(d.RoleName, d.Keys...)
if err != nil {
return err
}

View File

@ -33,7 +33,7 @@ func NewCryptoService(gun string, keyStore trustmanager.KeyStore) *CryptoService
}
// Create is used to generate keys for targets, snapshots and timestamps
func (ccs *CryptoService) Create(role string, algorithm data.KeyAlgorithm) (data.PublicKey, error) {
func (ccs *CryptoService) Create(role string, algorithm string) (data.PublicKey, error) {
var privKey data.PrivateKey
var err error

View File

@ -19,7 +19,7 @@ func TestCryptoService(t *testing.T) {
var passphraseRetriever = func(string, string, bool, int) (string, bool, error) { return "", false, nil }
func testCryptoService(t *testing.T, keyAlgo data.KeyAlgorithm, verifier signed.Verifier) {
func testCryptoService(t *testing.T, keyAlgo string, verifier signed.Verifier) {
content := []byte("this is a secret")
keyStore := trustmanager.NewKeyMemoryStore(passphraseRetriever)

View File

@ -57,7 +57,7 @@ func TestImportExportZip(t *testing.T) {
repo, err := client.NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, oldPassphraseRetriever)
assert.NoError(t, err, "error creating repo: %s", err)
rootKeyID, err := repo.KeyStoreManager.GenRootKey(data.ECDSAKey.String())
rootKeyID, err := repo.KeyStoreManager.GenRootKey(data.ECDSAKey)
assert.NoError(t, err, "error generating root key: %s", err)
rootCryptoService, err := repo.KeyStoreManager.GetRootCryptoService(rootKeyID)
@ -138,7 +138,7 @@ func TestImportExportZip(t *testing.T) {
repo2, err := client.NewNotaryRepository(tempBaseDir2, gun, ts.URL, http.DefaultTransport, newPassphraseRetriever)
assert.NoError(t, err, "error creating repo: %s", err)
rootKeyID2, err := repo2.KeyStoreManager.GenRootKey(data.ECDSAKey.String())
rootKeyID2, err := repo2.KeyStoreManager.GenRootKey(data.ECDSAKey)
assert.NoError(t, err, "error generating root key: %s", err)
rootCryptoService2, err := repo2.KeyStoreManager.GetRootCryptoService(rootKeyID2)
@ -194,7 +194,7 @@ func TestImportExportGUN(t *testing.T) {
repo, err := client.NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, oldPassphraseRetriever)
assert.NoError(t, err, "error creating repo: %s", err)
rootKeyID, err := repo.KeyStoreManager.GenRootKey(data.ECDSAKey.String())
rootKeyID, err := repo.KeyStoreManager.GenRootKey(data.ECDSAKey)
assert.NoError(t, err, "error generating root key: %s", err)
rootCryptoService, err := repo.KeyStoreManager.GetRootCryptoService(rootKeyID)
@ -278,7 +278,7 @@ func TestImportExportGUN(t *testing.T) {
repo2, err := client.NewNotaryRepository(tempBaseDir2, gun, ts.URL, http.DefaultTransport, oldPassphraseRetriever)
assert.NoError(t, err, "error creating repo: %s", err)
rootKeyID2, err := repo2.KeyStoreManager.GenRootKey(data.ECDSAKey.String())
rootKeyID2, err := repo2.KeyStoreManager.GenRootKey(data.ECDSAKey)
assert.NoError(t, err, "error generating root key: %s", err)
rootCryptoService2, err := repo2.KeyStoreManager.GetRootCryptoService(rootKeyID2)
@ -327,7 +327,7 @@ func TestImportExportRootKey(t *testing.T) {
repo, err := client.NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, oldPassphraseRetriever)
assert.NoError(t, err, "error creating repo: %s", err)
rootKeyID, err := repo.KeyStoreManager.GenRootKey(data.ECDSAKey.String())
rootKeyID, err := repo.KeyStoreManager.GenRootKey(data.ECDSAKey)
assert.NoError(t, err, "error generating root key: %s", err)
rootCryptoService, err := repo.KeyStoreManager.GetRootCryptoService(rootKeyID)
@ -353,7 +353,7 @@ func TestImportExportRootKey(t *testing.T) {
repo2, err := client.NewNotaryRepository(tempBaseDir2, gun, ts.URL, http.DefaultTransport, oldPassphraseRetriever)
assert.NoError(t, err, "error creating repo: %s", err)
rootKeyID2, err := repo2.KeyStoreManager.GenRootKey(data.ECDSAKey.String())
rootKeyID2, err := repo2.KeyStoreManager.GenRootKey(data.ECDSAKey)
assert.NoError(t, err, "error generating root key: %s", err)
rootCryptoService2, err := repo2.KeyStoreManager.GetRootCryptoService(rootKeyID2)
@ -414,7 +414,7 @@ func TestImportExportRootKeyReencrypt(t *testing.T) {
repo, err := client.NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, oldPassphraseRetriever)
assert.NoError(t, err, "error creating repo: %s", err)
rootKeyID, err := repo.KeyStoreManager.GenRootKey(data.ECDSAKey.String())
rootKeyID, err := repo.KeyStoreManager.GenRootKey(data.ECDSAKey)
assert.NoError(t, err, "error generating root key: %s", err)
rootCryptoService, err := repo.KeyStoreManager.GetRootCryptoService(rootKeyID)
@ -440,7 +440,7 @@ func TestImportExportRootKeyReencrypt(t *testing.T) {
repo2, err := client.NewNotaryRepository(tempBaseDir2, gun, ts.URL, http.DefaultTransport, newPassphraseRetriever)
assert.NoError(t, err, "error creating repo: %s", err)
rootKeyID2, err := repo2.KeyStoreManager.GenRootKey(data.ECDSAKey.String())
rootKeyID2, err := repo2.KeyStoreManager.GenRootKey(data.ECDSAKey)
assert.NoError(t, err, "error generating root key: %s", err)
rootCryptoService2, err := repo2.KeyStoreManager.GetRootCryptoService(rootKeyID2)

View File

@ -127,7 +127,7 @@ func (km *KeyStoreManager) GenRootKey(algorithm string) (string, error) {
// We don't want external API callers to rely on internal TUF data types, so
// the API here should continue to receive a string algorithm, and ensure
// that it is downcased
switch data.KeyAlgorithm(strings.ToLower(algorithm)) {
switch strings.ToLower(algorithm) {
case data.RSAKey:
privKey, err = trustmanager.GenerateRSAKey(rand.Reader, rsaRootKeySize)
case data.ECDSAKey:

View File

@ -220,7 +220,7 @@ func TestValidateSuccessfulRootRotation(t *testing.T) {
}
}
func testValidateSuccessfulRootRotation(t *testing.T, keyAlg data.KeyAlgorithm, rootKeyType data.KeyAlgorithm) {
func testValidateSuccessfulRootRotation(t *testing.T, keyAlg string, rootKeyType string) {
// Temporary directory where test files will be created
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
defer os.RemoveAll(tempBaseDir)
@ -233,10 +233,10 @@ func testValidateSuccessfulRootRotation(t *testing.T, keyAlg data.KeyAlgorithm,
keyStoreManager, err := NewKeyStoreManager(tempBaseDir, passphraseRetriever)
assert.NoError(t, err)
origRootKeyID, err := keyStoreManager.GenRootKey(keyAlg.String())
origRootKeyID, err := keyStoreManager.GenRootKey(keyAlg)
assert.NoError(t, err)
replRootKeyID, err := keyStoreManager.GenRootKey(keyAlg.String())
replRootKeyID, err := keyStoreManager.GenRootKey(keyAlg)
assert.NoError(t, err)
origUnlockedCryptoService, err := keyStoreManager.GetRootCryptoService(origRootKeyID)
@ -306,7 +306,7 @@ func TestValidateRootRotationMissingOrigSig(t *testing.T) {
}
}
func testValidateRootRotationMissingOrigSig(t *testing.T, keyAlg data.KeyAlgorithm, rootKeyType data.KeyAlgorithm) {
func testValidateRootRotationMissingOrigSig(t *testing.T, keyAlg string, rootKeyType string) {
// Temporary directory where test files will be created
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
defer os.RemoveAll(tempBaseDir)
@ -319,10 +319,10 @@ func testValidateRootRotationMissingOrigSig(t *testing.T, keyAlg data.KeyAlgorit
keyStoreManager, err := NewKeyStoreManager(tempBaseDir, passphraseRetriever)
assert.NoError(t, err)
origRootKeyID, err := keyStoreManager.GenRootKey(keyAlg.String())
origRootKeyID, err := keyStoreManager.GenRootKey(keyAlg)
assert.NoError(t, err)
replRootKeyID, err := keyStoreManager.GenRootKey(keyAlg.String())
replRootKeyID, err := keyStoreManager.GenRootKey(keyAlg)
assert.NoError(t, err)
origUnlockedCryptoService, err := keyStoreManager.GetRootCryptoService(origRootKeyID)
@ -389,7 +389,7 @@ func TestValidateRootRotationMissingNewSig(t *testing.T) {
}
}
func testValidateRootRotationMissingNewSig(t *testing.T, keyAlg data.KeyAlgorithm, rootKeyType data.KeyAlgorithm) {
func testValidateRootRotationMissingNewSig(t *testing.T, keyAlg string, rootKeyType string) {
// Temporary directory where test files will be created
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
defer os.RemoveAll(tempBaseDir)
@ -402,10 +402,10 @@ func testValidateRootRotationMissingNewSig(t *testing.T, keyAlg data.KeyAlgorith
keyStoreManager, err := NewKeyStoreManager(tempBaseDir, passphraseRetriever)
assert.NoError(t, err)
origRootKeyID, err := keyStoreManager.GenRootKey(keyAlg.String())
origRootKeyID, err := keyStoreManager.GenRootKey(keyAlg)
assert.NoError(t, err)
replRootKeyID, err := keyStoreManager.GenRootKey(keyAlg.String())
replRootKeyID, err := keyStoreManager.GenRootKey(keyAlg)
assert.NoError(t, err)
origUnlockedCryptoService, err := keyStoreManager.GetRootCryptoService(origRootKeyID)

View File

@ -192,7 +192,7 @@ func GetTimestampKeyHandler(ctx context.Context, w http.ResponseWriter, r *http.
logger.Error("500 GET key algorithm not configured")
return errors.ErrNoKeyAlgorithm.WithDetail(nil)
}
keyAlgorithm := data.KeyAlgorithm(keyAlgo)
keyAlgorithm := keyAlgo
key, err := timestamp.GetOrCreateTimestampKey(gun, store, crypto, keyAlgorithm)
if err != nil {

View File

@ -239,7 +239,7 @@ func TestValidateRootRotation(t *testing.T) {
delete(repo.Root.Signed.Keys, oldRootRole.KeyIDs[0])
repo.Root.Signed.Roles["root"] = &rootRole.RootRole
repo.Root.Signed.Keys[rootKey.ID()] = data.NewPrivateKey(rootKey.Algorithm(), rootKey.Public(), nil)
repo.Root.Signed.Keys[rootKey.ID()] = rootKey
r, err = repo.SignRoot(data.DefaultExpires(data.CanonicalRootRole), nil)
assert.NoError(t, err)

View File

@ -4,7 +4,6 @@ import (
"fmt"
"github.com/Sirupsen/logrus"
"github.com/docker/notary/tuf/data"
"github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
"github.com/mattn/go-sqlite3"
@ -138,7 +137,7 @@ func (db *SQLStorage) Delete(gun string) error {
}
// GetTimestampKey returns the timestamps Public Key data
func (db *SQLStorage) GetTimestampKey(gun string) (algorithm data.KeyAlgorithm, public []byte, err error) {
func (db *SQLStorage) GetTimestampKey(gun string) (algorithm string, public []byte, err error) {
logrus.Debug("retrieving timestamp key for ", gun)
var row TimestampKey
@ -150,11 +149,11 @@ func (db *SQLStorage) GetTimestampKey(gun string) (algorithm data.KeyAlgorithm,
return "", nil, query.Error
}
return data.KeyAlgorithm(row.Cipher), row.Public, nil
return row.Cipher, row.Public, nil
}
// SetTimestampKey attempts to write a TimeStamp key and returns an error if it already exists
func (db *SQLStorage) SetTimestampKey(gun string, algorithm data.KeyAlgorithm, public []byte) error {
func (db *SQLStorage) SetTimestampKey(gun string, algorithm string, public []byte) error {
entry := TimestampKey{
Gun: gun,

View File

@ -5,7 +5,6 @@ import (
"os"
"testing"
"github.com/docker/notary/tuf/data"
"github.com/jinzhu/gorm"
_ "github.com/mattn/go-sqlite3"
"github.com/stretchr/testify/assert"
@ -264,7 +263,7 @@ func TestSQLGetTimestampKeyNoKey(t *testing.T) {
defer os.RemoveAll(tempBaseDir)
cipher, public, err := dbStore.GetTimestampKey("testGUN")
assert.Equal(t, data.KeyAlgorithm(""), cipher)
assert.Equal(t, "", cipher)
assert.Nil(t, public)
assert.IsType(t, &ErrNoKey{}, err,
"Expected ErrNoKey from GetTimestampKey")
@ -278,7 +277,7 @@ func TestSQLGetTimestampKeyNoKey(t *testing.T) {
t, query.Error, "Inserting timestamp into empty DB should succeed")
cipher, public, err = dbStore.GetTimestampKey("testGUN")
assert.Equal(t, data.KeyAlgorithm("testCipher"), cipher,
assert.Equal(t, "testCipher", cipher,
"Returned cipher was incorrect")
assert.Equal(t, []byte("1"), public, "Returned pubkey was incorrect")
}

View File

@ -1,7 +1,5 @@
package storage
import "github.com/docker/notary/tuf/data"
// MetaStore holds the methods that are used for a Metadata Store
type MetaStore interface {
// UpdateCurrent adds new metadata version for the given GUN if and only
@ -26,9 +24,9 @@ type MetaStore interface {
// GetTimestampKey returns the algorithm and public key for the given GUN.
// If the GUN doesn't exist, returns an error.
GetTimestampKey(gun string) (algorithm data.KeyAlgorithm, public []byte, err error)
GetTimestampKey(gun string) (algorithm string, public []byte, err error)
// SetTimeStampKey sets the algorithm and public key for the given GUN if
// it doesn't already exist. Otherwise an error is returned.
SetTimestampKey(gun string, algorithm data.KeyAlgorithm, public []byte) error
SetTimestampKey(gun string, algorithm string, public []byte) error
}

View File

@ -4,12 +4,10 @@ import (
"fmt"
"strings"
"sync"
"github.com/docker/notary/tuf/data"
)
type key struct {
algorithm data.KeyAlgorithm
algorithm string
public []byte
}
@ -83,7 +81,7 @@ func (st *MemStorage) Delete(gun string) error {
}
// GetTimestampKey returns the public key material of the timestamp key of a given gun
func (st *MemStorage) GetTimestampKey(gun string) (algorithm data.KeyAlgorithm, public []byte, err error) {
func (st *MemStorage) GetTimestampKey(gun string) (algorithm string, public []byte, err error) {
// no need for lock. It's ok to return nil if an update
// wasn't observed
k, ok := st.tsKeys[gun]
@ -95,7 +93,7 @@ func (st *MemStorage) GetTimestampKey(gun string) (algorithm data.KeyAlgorithm,
}
// SetTimestampKey sets a Timestamp key under a gun
func (st *MemStorage) SetTimestampKey(gun string, algorithm data.KeyAlgorithm, public []byte) error {
func (st *MemStorage) SetTimestampKey(gun string, algorithm string, public []byte) error {
k := &key{algorithm: algorithm, public: public}
st.lock.Lock()
defer st.lock.Unlock()

View File

@ -16,7 +16,7 @@ import (
// found. It attempts to handle the race condition that may occur if 2 servers try to
// create the key at the same time by simply querying the store a second time if it
// receives a conflict when writing.
func GetOrCreateTimestampKey(gun string, store storage.MetaStore, crypto signed.CryptoService, fallBackAlgorithm data.KeyAlgorithm) (data.PublicKey, error) {
func GetOrCreateTimestampKey(gun string, store storage.MetaStore, crypto signed.CryptoService, fallBackAlgorithm string) (data.PublicKey, error) {
keyAlgorithm, public, err := store.GetTimestampKey(gun)
if err == nil {
return data.NewPublicKey(keyAlgorithm, public), nil

View File

@ -6,7 +6,6 @@ import (
"github.com/docker/notary/signer"
"github.com/docker/notary/signer/keys"
"github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/signed"
"github.com/gorilla/mux"
@ -34,7 +33,7 @@ func getCryptoService(w http.ResponseWriter, algorithm string, cryptoServices si
return nil
}
service := cryptoServices[data.KeyAlgorithm(algorithm)]
service := cryptoServices[algorithm]
if service == nil {
http.Error(w, "algorithm "+algorithm+" not supported", http.StatusBadRequest)
@ -67,7 +66,7 @@ func KeyInfo(cryptoServices signer.CryptoServiceIndex) http.Handler {
key := &pb.PublicKey{
KeyInfo: &pb.KeyInfo{
KeyID: &pb.KeyID{ID: tufKey.ID()},
Algorithm: &pb.Algorithm{Algorithm: tufKey.Algorithm().String()},
Algorithm: &pb.Algorithm{Algorithm: tufKey.Algorithm()},
},
PublicKey: tufKey.Public(),
}
@ -86,7 +85,7 @@ func CreateKey(cryptoServices signer.CryptoServiceIndex) http.Handler {
return
}
tufKey, err := cryptoService.Create("", data.KeyAlgorithm(vars["Algorithm"]))
tufKey, err := cryptoService.Create("", vars["Algorithm"])
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
@ -95,7 +94,7 @@ func CreateKey(cryptoServices signer.CryptoServiceIndex) http.Handler {
key := &pb.PublicKey{
KeyInfo: &pb.KeyInfo{
KeyID: &pb.KeyID{ID: tufKey.ID()},
Algorithm: &pb.Algorithm{Algorithm: tufKey.Algorithm().String()},
Algorithm: &pb.Algorithm{Algorithm: tufKey.Algorithm()},
},
PublicKey: tufKey.Public(),
}
@ -188,7 +187,7 @@ func Sign(cryptoServices signer.CryptoServiceIndex) http.Handler {
signature := &pb.Signature{
KeyInfo: &pb.KeyInfo{
KeyID: &pb.KeyID{ID: tufKey.ID()},
Algorithm: &pb.Algorithm{Algorithm: tufKey.Algorithm().String()},
Algorithm: &pb.Algorithm{Algorithm: tufKey.Algorithm()},
},
Content: signatures[0].Signature,
}

View File

@ -14,7 +14,7 @@ import (
// or ErrInvalidKeyID if the key is not found in any of the signing services.
// It also returns the CryptoService associated with the key, so the caller
// can perform operations with the key (such as signing).
func FindKeyByID(cryptoServices signer.CryptoServiceIndex, keyID *pb.KeyID) (data.Key, signed.CryptoService, error) {
func FindKeyByID(cryptoServices signer.CryptoServiceIndex, keyID *pb.KeyID) (data.PublicKey, signed.CryptoService, error) {
for _, service := range cryptoServices {
key := service.GetKey(keyID.ID)
if key != nil {

View File

@ -6,7 +6,6 @@ import (
ctxu "github.com/docker/distribution/context"
"github.com/docker/notary/signer"
"github.com/docker/notary/signer/keys"
"github.com/docker/notary/tuf/data"
"golang.org/x/net/context"
"google.golang.org/grpc"
@ -29,7 +28,7 @@ type SignerServer struct {
//CreateKey returns a PublicKey created using KeyManagementServer's SigningService
func (s *KeyManagementServer) CreateKey(ctx context.Context, algorithm *pb.Algorithm) (*pb.PublicKey, error) {
keyAlgo := data.KeyAlgorithm(algorithm.Algorithm)
keyAlgo := algorithm.Algorithm
service := s.CryptoServices[keyAlgo]
@ -49,7 +48,7 @@ func (s *KeyManagementServer) CreateKey(ctx context.Context, algorithm *pb.Algor
return &pb.PublicKey{
KeyInfo: &pb.KeyInfo{
KeyID: &pb.KeyID{ID: tufKey.ID()},
Algorithm: &pb.Algorithm{Algorithm: tufKey.Algorithm().String()},
Algorithm: &pb.Algorithm{Algorithm: tufKey.Algorithm()},
},
PublicKey: tufKey.Public(),
}, nil
@ -102,7 +101,7 @@ func (s *KeyManagementServer) GetKeyInfo(ctx context.Context, keyID *pb.KeyID) (
return &pb.PublicKey{
KeyInfo: &pb.KeyInfo{
KeyID: &pb.KeyID{ID: tufKey.ID()},
Algorithm: &pb.Algorithm{Algorithm: tufKey.Algorithm().String()},
Algorithm: &pb.Algorithm{Algorithm: tufKey.Algorithm()},
},
PublicKey: tufKey.Public(),
}, nil
@ -137,7 +136,7 @@ func (s *SignerServer) Sign(ctx context.Context, sr *pb.SignatureRequest) (*pb.S
signature := &pb.Signature{
KeyInfo: &pb.KeyInfo{
KeyID: &pb.KeyID{ID: tufKey.ID()},
Algorithm: &pb.Algorithm{Algorithm: tufKey.Algorithm().String()},
Algorithm: &pb.Algorithm{Algorithm: tufKey.Algorithm()},
},
Algorithm: &pb.Algorithm{Algorithm: signatures[0].Method.String()},
Content: signatures[0].Signature,

View File

@ -79,7 +79,7 @@ func TestDeleteKeyHandlerReturnsNotFoundWithNonexistentKey(t *testing.T) {
}
func TestCreateKeyHandlerCreatesKey(t *testing.T) {
publicKey, err := kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: data.ED25519Key.String()})
publicKey, err := kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: data.ED25519Key})
assert.NotNil(t, publicKey)
assert.NotEmpty(t, publicKey.PublicKey)
assert.NotEmpty(t, publicKey.KeyInfo)
@ -88,14 +88,14 @@ func TestCreateKeyHandlerCreatesKey(t *testing.T) {
}
func TestDeleteKeyHandlerDeletesCreatedKey(t *testing.T) {
publicKey, err := kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: data.ED25519Key.String()})
publicKey, err := kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: data.ED25519Key})
ret, err := kmClient.DeleteKey(context.Background(), publicKey.KeyInfo.KeyID)
assert.Nil(t, err)
assert.Equal(t, ret, void)
}
func TestKeyInfoReturnsCreatedKeys(t *testing.T) {
publicKey, err := kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: data.ED25519Key.String()})
publicKey, err := kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: data.ED25519Key})
fmt.Println("Pubkey ID: " + publicKey.GetKeyInfo().KeyID.ID)
returnedPublicKey, err := kmClient.GetKeyInfo(context.Background(), publicKey.KeyInfo.KeyID)
fmt.Println("returnedPublicKey ID: " + returnedPublicKey.GetKeyInfo().KeyID.ID)
@ -106,9 +106,9 @@ func TestKeyInfoReturnsCreatedKeys(t *testing.T) {
}
func TestCreateKeyCreatesNewKeys(t *testing.T) {
publicKey1, err := kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: data.ED25519Key.String()})
publicKey1, err := kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: data.ED25519Key})
assert.Nil(t, err)
publicKey2, err := kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: data.ED25519Key.String()})
publicKey2, err := kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: data.ED25519Key})
assert.Nil(t, err)
assert.NotEqual(t, publicKey1, publicKey2)
assert.NotEqual(t, publicKey1.KeyInfo, publicKey2.KeyInfo)
@ -128,7 +128,7 @@ func TestGetKeyInfoReturnsNotFoundOnNonexistKeys(t *testing.T) {
func TestCreatedKeysCanBeUsedToSign(t *testing.T) {
message := []byte{0, 0, 0, 0}
publicKey, err := kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: data.ED25519Key.String()})
publicKey, err := kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: data.ED25519Key})
assert.Nil(t, err)
assert.NotNil(t, publicKey)

View File

@ -23,7 +23,7 @@ type RSAHardwareCryptoService struct {
}
// Create creates a key and returns its public components
func (s *RSAHardwareCryptoService) Create(role string, algo data.KeyAlgorithm) (data.PublicKey, error) {
func (s *RSAHardwareCryptoService) Create(role string, algo string) (data.PublicKey, error) {
// For now generate random labels for keys
// (diogo): add link between keyID and label in database so we can support multiple keys
randomLabel := make([]byte, 32)

View File

@ -77,7 +77,7 @@ func (s *KeyDBStore) AddKey(name, alias string, privKey data.PrivateKey) error {
EncryptionAlg: EncryptionAlg,
KeywrapAlg: KeywrapAlg,
PassphraseAlias: s.defaultPassAlias,
Algorithm: privKey.Algorithm().String(),
Algorithm: privKey.Algorithm(),
Public: string(privKey.Public()),
Private: encryptedKey}
@ -124,8 +124,9 @@ func (s *KeyDBStore) GetKey(name string) (data.PrivateKey, string, error) {
return nil, "", err
}
pubKey := data.NewPublicKey(dbPrivateKey.Algorithm, []byte(dbPrivateKey.Public))
// Create a new PrivateKey with unencrypted bytes
privKey := data.NewPrivateKey(data.KeyAlgorithm(dbPrivateKey.Algorithm), []byte(dbPrivateKey.Public), []byte(decryptedPrivKey))
privKey := data.NewPrivateKey(pubKey, []byte(decryptedPrivKey))
// Add the key to cache
s.cachedKeys[privKey.ID()] = privKey

View File

@ -32,7 +32,7 @@ func NewHSMRSAKey(public []byte, private pkcs11.ObjectHandle) *HSMRSAKey {
}
// Algorithm implements a method of the data.Key interface
func (rsa *HSMRSAKey) Algorithm() data.KeyAlgorithm {
func (rsa *HSMRSAKey) Algorithm() string {
return data.RSAKey
}

View File

@ -2,7 +2,6 @@ package signer
import (
pb "github.com/docker/notary/proto"
"github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/signed"
)
@ -16,7 +15,7 @@ type SigningService interface {
// CryptoServiceIndex represents a mapping between a service algorithm string
// and a CryptoService
type CryptoServiceIndex map[data.KeyAlgorithm]signed.CryptoService
type CryptoServiceIndex map[string]signed.CryptoService
// KeyManager is the interface to implement key management (possibly a key database)
type KeyManager interface {

View File

@ -77,12 +77,12 @@ func (trust *NotarySigner) Sign(keyIDs []string, toSign []byte) ([]data.Signatur
}
// Create creates a remote key and returns the PublicKey associated with the remote private key
func (trust *NotarySigner) Create(role string, algorithm data.KeyAlgorithm) (data.PublicKey, error) {
publicKey, err := trust.kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: algorithm.String()})
func (trust *NotarySigner) Create(role string, algorithm string) (data.PublicKey, error) {
publicKey, err := trust.kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: algorithm})
if err != nil {
return nil, err
}
public := data.NewPublicKey(data.KeyAlgorithm(publicKey.KeyInfo.Algorithm.Algorithm), publicKey.PublicKey)
public := data.NewPublicKey(publicKey.KeyInfo.Algorithm.Algorithm, publicKey.PublicKey)
return public, nil
}
@ -98,7 +98,7 @@ func (trust *NotarySigner) GetKey(keyid string) data.PublicKey {
if err != nil {
return nil
}
return data.NewPublicKey(data.KeyAlgorithm(publicKey.KeyInfo.Algorithm.Algorithm), publicKey.PublicKey)
return data.NewPublicKey(publicKey.KeyInfo.Algorithm.Algorithm, publicKey.PublicKey)
}
// CheckHealth checks the health of one of the clients, since both clients run

View File

@ -9,7 +9,7 @@ import (
"testing"
"github.com/docker/notary/pkg/passphrase"
"github.com/endophage/gotuf/data"
"github.com/docker/notary/tuf/data"
"github.com/stretchr/testify/assert"
)

View File

@ -102,19 +102,16 @@ func fingerprintCert(cert *x509.Certificate) (CertID, error) {
block := pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}
pemdata := pem.EncodeToMemory(&block)
var keyType data.KeyAlgorithm
var tufKey data.PublicKey
switch cert.PublicKeyAlgorithm {
case x509.RSA:
keyType = data.RSAx509Key
tufKey = data.NewRSAx509PublicKey(pemdata)
case x509.ECDSA:
keyType = data.ECDSAx509Key
tufKey = data.NewECDSAx509PublicKey(pemdata)
default:
return "", fmt.Errorf("got Unknown key type while fingerprinting certificate")
}
// Create new TUF Key so we can compute the TUF-compliant CertID
tufKey := data.NewPublicKey(keyType, pemdata)
return CertID(tufKey.ID()), nil
}
@ -327,7 +324,8 @@ func RSAToPrivateKey(rsaPrivKey *rsa.PrivateKey) (data.PrivateKey, error) {
// Get a DER-encoded representation of the PrivateKey
rsaPrivBytes := x509.MarshalPKCS1PrivateKey(rsaPrivKey)
return data.NewPrivateKey(data.RSAKey, rsaPubBytes, rsaPrivBytes), nil
pubKey := data.NewRSAPublicKey(rsaPubBytes)
return data.NewRSAPrivateKey(*pubKey, rsaPrivBytes), nil
}
// GenerateECDSAKey generates an ECDSA Private key and returns a TUF PrivateKey
@ -384,7 +382,8 @@ func ECDSAToPrivateKey(ecdsaPrivKey *ecdsa.PrivateKey) (data.PrivateKey, error)
return nil, fmt.Errorf("failed to marshal private key: %v", err)
}
return data.NewPrivateKey(data.ECDSAKey, ecdsaPubBytes, ecdsaPrivKeyBytes), nil
pubKey := data.NewECDSAPublicKey(ecdsaPubBytes)
return data.NewECDSAPrivateKey(*pubKey, ecdsaPrivKeyBytes), nil
}
// ED25519ToPrivateKey converts a serialized ED25519 key to a TUF
@ -394,36 +393,37 @@ func ED25519ToPrivateKey(privKeyBytes []byte) (data.PrivateKey, error) {
return nil, errors.New("malformed ed25519 private key")
}
return data.NewPrivateKey(data.ED25519Key, privKeyBytes[:ed25519.PublicKeySize], privKeyBytes), nil
pubKey := data.NewED25519PublicKey(privKeyBytes[:ed25519.PublicKeySize])
return data.NewED25519PrivateKey(*pubKey, privKeyBytes), nil
}
func blockType(algorithm data.KeyAlgorithm) (string, error) {
switch algorithm {
case data.RSAKey:
func blockType(k data.PrivateKey) (string, error) {
switch k.(type) {
case *data.RSAPrivateKey:
return "RSA PRIVATE KEY", nil
case data.ECDSAKey:
case *data.ECDSAPrivateKey:
return "EC PRIVATE KEY", nil
case data.ED25519Key:
case *data.ED25519PrivateKey:
return "ED25519 PRIVATE KEY", nil
default:
return "", fmt.Errorf("algorithm %s not supported", algorithm)
return "", fmt.Errorf("algorithm %s not supported", k.Algorithm())
}
}
// KeyToPEM returns a PEM encoded key from a Private Key
func KeyToPEM(privKey data.PrivateKey) ([]byte, error) {
blockType, err := blockType(privKey.Algorithm())
bt, err := blockType(privKey)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(&pem.Block{Type: blockType, Bytes: privKey.Private()}), nil
return pem.EncodeToMemory(&pem.Block{Type: bt, Bytes: privKey.Private()}), nil
}
// EncryptPrivateKey returns an encrypted PEM key given a Privatekey
// and a passphrase
func EncryptPrivateKey(key data.PrivateKey, passphrase string) ([]byte, error) {
blockType, err := blockType(key.Algorithm())
bt, err := blockType(key)
if err != nil {
return nil, err
}
@ -432,7 +432,7 @@ func EncryptPrivateKey(key data.PrivateKey, passphrase string) ([]byte, error) {
cipherType := x509.PEMCipherAES256
encryptedPEMBlock, err := x509.EncryptPEMBlock(rand.Reader,
blockType,
bt,
key.Private(),
password,
cipherType)
@ -449,17 +449,15 @@ 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
return data.NewRSAx509PublicKey(pemdata)
case x509.ECDSA:
keyType = data.ECDSAx509Key
return data.NewECDSAx509PublicKey(pemdata)
default:
logrus.Debugf("unknown certificate type found, ignoring")
logrus.Debugf("Unknown key type parsed from certificate: %v", cert.PublicKeyAlgorithm)
return nil
}
return data.NewPublicKey(keyType, pemdata)
}
// CertsToKeys transforms each of the input certificates into it's corresponding
@ -507,18 +505,18 @@ func X509PublicKeyID(certPubKey data.PublicKey) (string, error) {
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
var key data.PublicKey
switch certPubKey.Algorithm() {
case data.ECDSAx509Key:
key = data.NewECDSAPublicKey(pubKeyBytes)
case data.RSAx509Key:
key = data.NewRSAPublicKey(pubKeyBytes)
}
return key.ID(), nil
}

View File

@ -8,22 +8,16 @@ 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
ID() string
Algorithm() string
Public() []byte
}
// PrivateKey adds the ability to access the private key
type PrivateKey interface {
Key
PublicKey
Private() []byte
}
@ -34,38 +28,165 @@ type KeyPair struct {
Private []byte `json:"private"`
}
// TUFKey is the structure used for both public and private keys in TUF.
type Keys map[string]PublicKey
func (ks *Keys) UnmarshalJSON(data []byte) error {
parsed := make(map[string]tufKey)
err := json.Unmarshal(data, &parsed)
if err != nil {
return err
}
final := make(map[string]PublicKey)
for k, tk := range parsed {
final[k] = typedPublicKey(tk)
}
*ks = final
return nil
}
type KeyList []PublicKey
func (ks *KeyList) UnmarshalJSON(data []byte) error {
parsed := make([]tufKey, 0, 1)
err := json.Unmarshal(data, &parsed)
if err != nil {
return err
}
final := make([]PublicKey, 0, len(parsed))
for _, tk := range parsed {
final = append(final, typedPublicKey(tk))
}
*ks = final
return nil
}
func typedPublicKey(tk tufKey) PublicKey {
switch tk.Algorithm() {
case ECDSAKey:
return &ECDSAPublicKey{tufKey: tk}
case ECDSAx509Key:
return &ECDSAx509PublicKey{tufKey: tk}
case RSAKey:
return &RSAPublicKey{tufKey: tk}
case RSAx509Key:
return &RSAx509PublicKey{tufKey: tk}
case ED25519Key:
return &ED25519PublicKey{tufKey: tk}
}
return &UnknownPublicKey{tufKey: tk}
}
func typedPrivateKey(tk tufKey) PrivateKey {
private := tk.Value.Private
tk.Value.Private = nil
switch tk.Algorithm() {
case ECDSAKey:
return &ECDSAPrivateKey{
ECDSAPublicKey: ECDSAPublicKey{
tufKey: tk,
},
private: private,
}
case ECDSAx509Key:
return &ECDSAx509PrivateKey{
ECDSAx509PublicKey: ECDSAx509PublicKey{
tufKey: tk,
},
private: private,
}
case RSAKey:
return &RSAPrivateKey{
RSAPublicKey: RSAPublicKey{
tufKey: tk,
},
private: private,
}
case RSAx509Key:
return &RSAx509PrivateKey{
RSAx509PublicKey: RSAx509PublicKey{
tufKey: tk,
},
private: private,
}
case ED25519Key:
return &ED25519PrivateKey{
ED25519PublicKey: ED25519PublicKey{
tufKey: tk,
},
private: private,
}
}
return &UnknownPrivateKey{
tufKey: tk,
private: private,
}
}
func NewPublicKey(alg string, public []byte) PublicKey {
tk := tufKey{
Type: alg,
Value: KeyPair{
Public: public,
},
}
return typedPublicKey(tk)
}
func NewPrivateKey(pubKey PublicKey, private []byte) PrivateKey {
tk := tufKey{
Type: pubKey.Algorithm(),
Value: KeyPair{
Public: pubKey.Public(),
Private: private, // typedPrivateKey moves this value
},
}
return typedPrivateKey(tk)
}
func UnmarshalPublicKey(data []byte) (PublicKey, error) {
var parsed tufKey
err := json.Unmarshal(data, &parsed)
if err != nil {
return nil, err
}
return typedPublicKey(parsed), nil
}
func UnmarshalPrivateKey(data []byte) (PrivateKey, error) {
var parsed tufKey
err := json.Unmarshal(data, &parsed)
if err != nil {
return nil, err
}
return typedPrivateKey(parsed), nil
}
// tufKey is the structure used for both public and private keys in TUF.
// Normally it would make sense to use a different structures for public and
// private keys, but that would change the key ID algorithm (since the canonical
// JSON would be different). This structure should normally be accessed through
// the PublicKey or PrivateKey interfaces.
type TUFKey struct {
type tufKey struct {
id string
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,
Value: KeyPair{
Public: public,
Private: private,
},
}
Type string `json:"keytype"`
Value KeyPair `json:"keyval"`
}
// Algorithm returns the algorithm of the key
func (k TUFKey) Algorithm() KeyAlgorithm {
func (k tufKey) Algorithm() string {
return k.Type
}
// ID efficiently generates if necessary, and caches the ID of the key
func (k *TUFKey) ID() string {
func (k *tufKey) ID() string {
if k.id == "" {
pubK := NewPublicKey(k.Algorithm(), k.Public())
pubK := tufKey{
Type: k.Algorithm(),
Value: KeyPair{
Public: k.Public(),
Private: nil,
},
}
data, err := json.MarshalCanonical(&pubK)
if err != nil {
logrus.Error("Error generating key ID:", err)
@ -77,35 +198,198 @@ func (k *TUFKey) ID() string {
}
// Public returns the public bytes
func (k TUFKey) Public() []byte {
func (k tufKey) Public() []byte {
return k.Value.Public
}
// Private returns the private bytes
func (k TUFKey) Private() []byte {
return k.Value.Private
// Public key types
type ECDSAPublicKey struct {
tufKey
}
// 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,
Value: KeyPair{
Public: public,
Private: nil,
type ECDSAx509PublicKey struct {
tufKey
}
type RSAPublicKey struct {
tufKey
}
type RSAx509PublicKey struct {
tufKey
}
type ED25519PublicKey struct {
tufKey
}
type UnknownPublicKey struct {
tufKey
}
func NewECDSAPublicKey(public []byte) *ECDSAPublicKey {
return &ECDSAPublicKey{
tufKey: tufKey{
Type: ECDSAKey,
Value: KeyPair{
Public: public,
Private: nil,
},
},
}
}
// PublicKeyFromPrivate returns a new TUFKey based on a private key, with
func NewECDSAx509PublicKey(public []byte) *ECDSAx509PublicKey {
return &ECDSAx509PublicKey{
tufKey: tufKey{
Type: ECDSAx509Key,
Value: KeyPair{
Public: public,
Private: nil,
},
},
}
}
func NewRSAPublicKey(public []byte) *RSAPublicKey {
return &RSAPublicKey{
tufKey: tufKey{
Type: RSAKey,
Value: KeyPair{
Public: public,
Private: nil,
},
},
}
}
func NewRSAx509PublicKey(public []byte) *RSAx509PublicKey {
return &RSAx509PublicKey{
tufKey: tufKey{
Type: RSAx509Key,
Value: KeyPair{
Public: public,
Private: nil,
},
},
}
}
func NewED25519PublicKey(public []byte) *ED25519PublicKey {
return &ED25519PublicKey{
tufKey: tufKey{
Type: ED25519Key,
Value: KeyPair{
Public: public,
Private: nil,
},
},
}
}
// Private key types
// ECDSAPrivateKey
type ECDSAPrivateKey struct {
ECDSAPublicKey
private []byte `json:"-"`
}
type ECDSAx509PrivateKey struct {
ECDSAx509PublicKey
private []byte `json:"-"`
}
type RSAPrivateKey struct {
RSAPublicKey
private []byte `json:"-"`
}
type RSAx509PrivateKey struct {
RSAx509PublicKey
private []byte `json:"-"`
}
type ED25519PrivateKey struct {
ED25519PublicKey
private []byte `json:"-"`
}
type UnknownPrivateKey struct {
tufKey
private []byte `json:"-"`
}
func NewECDSAPrivateKey(public ECDSAPublicKey, private []byte) *ECDSAPrivateKey {
return &ECDSAPrivateKey{
ECDSAPublicKey: public,
private: private,
}
}
func NewECDSAx509PrivateKey(public ECDSAx509PublicKey, private []byte) *ECDSAx509PrivateKey {
return &ECDSAx509PrivateKey{
ECDSAx509PublicKey: public,
private: private,
}
}
func NewRSAPrivateKey(public RSAPublicKey, private []byte) *RSAPrivateKey {
return &RSAPrivateKey{
RSAPublicKey: public,
private: private,
}
}
func NewRSAx509PrivateKey(public RSAx509PublicKey, private []byte) *RSAx509PrivateKey {
return &RSAx509PrivateKey{
RSAx509PublicKey: public,
private: private,
}
}
func NewED25519PrivateKey(public ED25519PublicKey, private []byte) *ED25519PrivateKey {
return &ED25519PrivateKey{
ED25519PublicKey: public,
private: private,
}
}
func (k ECDSAPrivateKey) Private() []byte {
return k.private
}
func (k ECDSAx509PrivateKey) Private() []byte {
return k.private
}
func (k RSAPrivateKey) Private() []byte {
return k.private
}
func (k RSAx509PrivateKey) Private() []byte {
return k.private
}
func (k ED25519PrivateKey) Private() []byte {
return k.private
}
func (k UnknownPrivateKey) Private() []byte {
return k.private
}
// 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{
return typedPublicKey(tufKey{
Type: pk.Algorithm(),
Value: KeyPair{
Public: pk.Public(),
Private: nil,
},
}
})
}
type ed25519PrivateKey []byte

View File

@ -15,12 +15,10 @@ type SignedRoot struct {
// Root is the Signed component of a root.json
type Root struct {
Type string `json:"_type"`
Version int `json:"version"`
Expires time.Time `json:"expires"`
// These keys are public keys. We use TUFKey instead of PublicKey to
// support direct JSON unmarshaling.
Keys map[string]*TUFKey `json:"keys"`
Type string `json:"_type"`
Version int `json:"version"`
Expires time.Time `json:"expires"`
Keys Keys `json:"keys"`
Roles map[string]*RootRole `json:"roles"`
ConsistentSnapshot bool `json:"consistent_snapshot"`
}
@ -33,29 +31,13 @@ func NewRoot(keys map[string]PublicKey, roles map[string]*RootRole, consistent b
Type: TUFTypes["root"],
Version: 0,
Expires: DefaultExpires("root"),
Keys: make(map[string]*TUFKey),
Keys: keys,
Roles: roles,
ConsistentSnapshot: consistent,
},
Dirty: true,
}
// Convert PublicKeys to TUFKey structures
// The Signed.Keys map needs to have *TUFKey values, since this
// structure gets directly unmarshalled from JSON, and it's not
// possible to unmarshal into an interface type. But this function
// takes a map with PublicKey values to avoid exposing this ugliness.
// The loop below converts to the TUFKey type.
for k, v := range keys {
signedRoot.Signed.Keys[k] = &TUFKey{
Type: v.Algorithm(),
Value: KeyPair{
Public: v.Public(),
Private: nil,
},
}
}
return signedRoot, nil
}

View File

@ -14,13 +14,6 @@ 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
@ -41,11 +34,11 @@ const (
// Key types
const (
ED25519Key KeyAlgorithm = "ed25519"
RSAKey KeyAlgorithm = "rsa"
RSAx509Key KeyAlgorithm = "rsa-x509"
ECDSAKey KeyAlgorithm = "ecdsa"
ECDSAx509Key KeyAlgorithm = "ecdsa-x509"
ED25519Key = "ed25519"
RSAKey = "rsa"
RSAx509Key = "rsa-x509"
ECDSAKey = "ecdsa"
ECDSAx509Key = "ecdsa-x509"
)
// TUFTypes is the set of metadata types
@ -167,8 +160,8 @@ func NewFileMeta(r io.Reader, hashAlgorithms ...string) (FileMeta, error) {
// Delegations holds a tier of targets delegations
type Delegations struct {
Keys map[string]PublicKey `json:"keys"`
Roles []*Role `json:"roles"`
Keys Keys `json:"keys"`
Roles []*Role `json:"roles"`
}
// NewDelegations initializes an empty Delegations object

View File

@ -50,7 +50,7 @@ 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) {
func (e *Ed25519) Create(role string, algorithm string) (data.PublicKey, error) {
if algorithm != data.ED25519Key {
return nil, errors.New("only ED25519 supported by this cryptoservice")
}
@ -59,8 +59,8 @@ func (e *Ed25519) Create(role string, algorithm data.KeyAlgorithm) (data.PublicK
if err != nil {
return nil, err
}
public := data.NewPublicKey(data.ED25519Key, pub[:])
private := data.NewPrivateKey(data.ED25519Key, pub[:], priv[:])
public := data.NewED25519PublicKey(pub[:])
private := data.NewED25519PrivateKey(*public, priv[:])
e.addKey(private)
return public, nil
}

View File

@ -20,7 +20,7 @@ type KeyService interface {
// the private key into the appropriate signing service.
// The role isn't currently used for anything, but it's here to support
// future features
Create(role string, algorithm data.KeyAlgorithm) (data.PublicKey, error)
Create(role string, algorithm string) (data.PublicKey, error)
// GetKey retrieves the public key if present, otherwise it returns nil
GetKey(keyID string) data.PublicKey

View File

@ -29,7 +29,7 @@ func (mts *FailingCryptoService) Sign(keyIDs []string, _ []byte) ([]data.Signatu
return sigs, nil
}
func (mts *FailingCryptoService) Create(_ string, _ data.KeyAlgorithm) (data.PublicKey, error) {
func (mts *FailingCryptoService) Create(_ string, _ string) (data.PublicKey, error) {
return mts.testKey, nil
}
@ -56,7 +56,7 @@ func (mts *MockCryptoService) Sign(keyIDs []string, _ []byte) ([]data.Signature,
return sigs, nil
}
func (mts *MockCryptoService) Create(_ string, _ data.KeyAlgorithm) (data.PublicKey, error) {
func (mts *MockCryptoService) Create(_ string, _ string) (data.PublicKey, error) {
return mts.testKey, nil
}

View File

@ -10,7 +10,6 @@ import (
"crypto/sha256"
"crypto/x509"
"encoding/hex"
"encoding/json"
"fmt"
"testing"
"text/template"
@ -20,7 +19,7 @@ import (
)
type KeyTemplate struct {
KeyType data.KeyAlgorithm
KeyType string
}
const baseRSAKey = `{"keytype":"{{.KeyType}}","keyval":{"public":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyyvBtTg2xzYS+MTTIBqSpI4V78tt8Yzqi7Jki/Z6NqjiDvcnbgcTqNR2t6B2W5NjGdp/hSaT2jyHM+kdmEGaPxg/zIuHbL3NIp4e0qwovWiEgACPIaELdn8O/kt5swsSKl1KMvLCH1sM86qMibNMAZ/hXOwd90TcHXCgZ91wHEAmsdjDC3dB0TT+FBgOac8RM01Y196QrZoOaDMTWh0EQfw7YbXAElhFVDFxBzDdYWbcIHSIogXQmq0CP+zaL/1WgcZZIClt2M6WCaxxF1S34wNn45gCvVZiZQ/iKWHerSr/2dGQeGo+7ezMSutRzvJ+01fInD86RS/CEtBCFZ1VyQIDAQAB","private":"MIIEpAIBAAKCAQEAyyvBtTg2xzYS+MTTIBqSpI4V78tt8Yzqi7Jki/Z6NqjiDvcnbgcTqNR2t6B2W5NjGdp/hSaT2jyHM+kdmEGaPxg/zIuHbL3NIp4e0qwovWiEgACPIaELdn8O/kt5swsSKl1KMvLCH1sM86qMibNMAZ/hXOwd90TcHXCgZ91wHEAmsdjDC3dB0TT+FBgOac8RM01Y196QrZoOaDMTWh0EQfw7YbXAElhFVDFxBzDdYWbcIHSIogXQmq0CP+zaL/1WgcZZIClt2M6WCaxxF1S34wNn45gCvVZiZQ/iKWHerSr/2dGQeGo+7ezMSutRzvJ+01fInD86RS/CEtBCFZ1VyQIDAQABAoIBAHar8FFxrE1gAGTeUpOF8fG8LIQMRwO4U6eVY7V9GpWiv6gOJTHXYFxU/aL0Ty3eQRxwy9tyVRo8EJz5pRex+e6ws1M+jLOviYqW4VocxQ8dZYd+zBvQfWmRfah7XXJ/HPUx2I05zrmR7VbGX6Bu4g5w3KnyIO61gfyQNKF2bm2Q3yblfupx3URvX0bl180R/+QN2Aslr4zxULFE6b+qJqBydrztq+AAP3WmskRxGa6irFnKxkspJqUpQN1mFselj6iQrzAcwkRPoCw0RwCCMq1/OOYvQtgxTJcO4zDVlbw54PvnxPZtcCWw7fO8oZ2Fvo2SDo75CDOATOGaT4Y9iqECgYEAzWZSpFbN9ZHmvq1lJQg//jFAyjsXRNn/nSvyLQILXltz6EHatImnXo3v+SivG91tfzBI1GfDvGUGaJpvKHoomB+qmhd8KIQhO5MBdAKZMf9fZqZofOPTD9xRXECCwdi+XqHBmL+l1OWz+O9Bh+Qobs2as/hQVgHaoXhQpE0NkTcCgYEA/Tjf6JBGl1+WxQDoGZDJrXoejzG9OFW19RjMdmPrg3t4fnbDtqTpZtCzXxPTCSeMrvplKbqAqZglWyq227ksKw4p7O6YfyhdtvC58oJmivlLr6sFaTsER7mDcYce8sQpqm+XQ8IPbnOk0Z1l6g56euTwTnew49uy25M6U1xL0P8CgYEAxEXv2Kw+OVhHV5PX4BBHHj6we88FiDyMfwM8cvfOJ0datekf9X7ImZkmZEAVPJpWBMD+B0J0jzU2b4SLjfFVkzBHVOH2Ob0xCH2MWPAWtekin7OKizUlPbW5ZV8b0+Kq30DQ/4a7D3rEhK8UPqeuX1tHZox1MAqrgbq3zJj4yvcCgYEAktYPKPm4pYCdmgFrlZ+bA0iEPf7Wvbsd91F5BtHsOOM5PQQ7e0bnvWIaEXEad/2CG9lBHlBy2WVLjDEZthILpa/h6e11ao8KwNGY0iKBuebT17rxOVMqqTjPGt8CuD2994IcEgOPFTpkAdUmyvG4XlkxbB8F6St17NPUB5DGuhsCgYA//Lfytk0FflXEeRQ16LT1YXgV7pcR2jsha4+4O5pxSFw/kTsOfJaYHg8StmROoyFnyE3sg76dCgLn0LENRCe5BvDhJnp5bMpQldG3XwcAxH8FGFNY4LtV/2ZKnJhxcONkfmzQPOmTyedOzrKQ+bNURsqLukCypP7/by6afBY4dA=="}}`
@ -31,38 +30,40 @@ const baseECDSAx509Key = `{"keytype":"ecdsa-x509","keyval":{"public":"LS0tLS1CRU
func TestRSAPSSVerifier(t *testing.T) {
// Unmarshal our private RSA Key
var testRSAKey data.TUFKey
var testRSAKey data.PrivateKey
var jsonKey bytes.Buffer
// Execute our template
templ, _ := template.New("KeyTemplate").Parse(baseRSAKey)
templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAKey})
json.Unmarshal(jsonKey.Bytes(), &testRSAKey)
testRSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes())
assert.NoError(t, err)
// Sign some data using RSAPSS
message := []byte("test data for signing")
hash := crypto.SHA256
hashed := sha256.Sum256(message)
signedData, err := rsaPSSSign(&testRSAKey, hash, hashed[:])
signedData, err := rsaPSSSign(testRSAKey, hash, hashed[:])
assert.NoError(t, err)
// Create and call Verify on the verifier
rsaVerifier := RSAPSSVerifier{}
err = rsaVerifier.Verify(&testRSAKey, signedData, message)
err = rsaVerifier.Verify(testRSAKey, signedData, message)
assert.NoError(t, err, "expecting success but got error while verifying data using RSA PSS")
}
func TestRSAPSSx509Verifier(t *testing.T) {
// Unmarshal our public RSA Key
var testRSAKey data.TUFKey
var testRSAKey data.PrivateKey
var jsonKey bytes.Buffer
// Execute our template
templ, _ := template.New("KeyTemplate").Parse(baseRSAx509Key)
templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAx509Key})
json.Unmarshal(jsonKey.Bytes(), &testRSAKey)
testRSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes())
assert.NoError(t, err)
// Valid signed message
signedData, _ := hex.DecodeString("3de02fa54cdba45c67860f058b7cff1ba264610dc3c5b466b7df027bc52068bdf2956fe438dba08b0b71daa0780a3037bf8f50a09d91ca81fa872bbdbbbff6ef17e04df8741ad5c2f2c3ea5de97d6ffaf4999c83fdfba4b6cb2443da11c7b7eea84123c2fdaf3319fa6342cbbdbd1aa25d1ac20aeee687e48cbf191cc8f68049230261469eeada33dec0af74287766bd984dd01820a7edfb8b0d030e2fcf00886c578b07eb905a2eebc81fd982a578e717c7ac773cab345950c71e1eaf81b70401e5bf3c67cdcb9068bf4b50ff0456b530b3cec5586827eb39b123f9d666a65f4b418a355438ed1753da8a27577ab9cd791d7b840c7e34ecc1290c46d98aa0dd73c0427f6ef8f63e36af42e9657520b8f56c9231ba7e0172dfc3456c63c54e9eae95d06bafe571e91afa1e42d4010e60dd5c441df112cc8474253eee7f1d6c5350039ffcd1f8b0bb013e4403c16fc5b40d6bd56b742ea1ed82c87880147db194b33b022077cc2e8d31ef3eada3e46683ad437ad8ef7ecbe03c29d7a53a9771e42cc4f9d782813c491186fde2cd1dfa408c4e21dd4c3ca1664e901772ffe1713e37b07c9287572114865a05e17cbe29d8622c6b033dcb43c9721d0943c58098607cc28bd58b3caf3dfc1f66d01ebfaf1aa5c2c5945c23af83fe114e587fa7bcbaea6bdccff3c0ad03ce3328f67af30168e225e5827ad9e94b4702de984e6dd775")
@ -70,19 +71,20 @@ func TestRSAPSSx509Verifier(t *testing.T) {
// Create and call Verify on the verifier
rsaVerifier := RSAPSSVerifier{}
err := rsaVerifier.Verify(&testRSAKey, signedData, message)
err = rsaVerifier.Verify(testRSAKey, signedData, message)
assert.NoError(t, err, "expecting success but got error while verifying data using RSAPSS and an X509 encoded Key")
}
func TestRSAPSSVerifierWithInvalidKeyType(t *testing.T) {
var testRSAKey data.TUFKey
var testRSAKey data.PrivateKey
var jsonKey bytes.Buffer
// Execute our template
templ, _ := template.New("KeyTemplate").Parse(baseRSAKey)
templ.Execute(&jsonKey, KeyTemplate{KeyType: "rsa-invalid"})
json.Unmarshal(jsonKey.Bytes(), &testRSAKey)
testRSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes())
assert.NoError(t, err)
// Valid signed data with invalidRsaKeyJSON
signedData, _ := hex.DecodeString("2741a57a5ef89f841b4e0a6afbcd7940bc982cd919fbd11dfc21b5ccfe13855b9c401e3df22da5480cef2fa585d0f6dfc6c35592ed92a2a18001362c3a17f74da3906684f9d81c5846bf6a09e2ede6c009ae164f504e6184e666adb14eadf5f6e12e07ff9af9ad49bf1ea9bcfa3bebb2e33be7d4c0fabfe39534f98f1e3c4bff44f637cff3dae8288aea54d86476a3f1320adc39008eae24b991c1de20744a7967d2e685ac0bcc0bc725947f01c9192ffd3e9300eba4b7faa826e84478493fdf97c705dd331dd46072050d6c5e317c2d63df21694dbaf909ebf46ce0ff04f3979fe13723ae1a823c65f27e56efa19e88f9e7b8ee56eac34353b944067deded3a")
@ -90,7 +92,7 @@ func TestRSAPSSVerifierWithInvalidKeyType(t *testing.T) {
// Create and call Verify on the verifier
rsaVerifier := RSAPSSVerifier{}
err := rsaVerifier.Verify(&testRSAKey, signedData, message)
err = rsaVerifier.Verify(testRSAKey, signedData, message)
assert.Error(t, err, "invalid key type for RSAPSS verifier: rsa-invalid")
}
@ -104,14 +106,15 @@ func TestRSAPSSVerifierWithInvalidKeyLength(t *testing.T) {
}
func TestRSAPSSVerifierWithInvalidKey(t *testing.T) {
var testRSAKey data.TUFKey
var testRSAKey data.PrivateKey
var jsonKey bytes.Buffer
// Execute our template
templ, _ := template.New("KeyTemplate").Parse(baseECDSAKey)
templ.Execute(&jsonKey, KeyTemplate{KeyType: "ecdsa"})
json.Unmarshal(jsonKey.Bytes(), &testRSAKey)
testRSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes())
assert.NoError(t, err)
// Valid signed data with invalidRsaKeyJSON
signedData, _ := hex.DecodeString("2741a57a5ef89f841b4e0a6afbcd7940bc982cd919fbd11dfc21b5ccfe13855b9c401e3df22da5480cef2fa585d0f6dfc6c35592ed92a2a18001362c3a17f74da3906684f9d81c5846bf6a09e2ede6c009ae164f504e6184e666adb14eadf5f6e12e07ff9af9ad49bf1ea9bcfa3bebb2e33be7d4c0fabfe39534f98f1e3c4bff44f637cff3dae8288aea54d86476a3f1320adc39008eae24b991c1de20744a7967d2e685ac0bcc0bc725947f01c9192ffd3e9300eba4b7faa826e84478493fdf97c705dd331dd46072050d6c5e317c2d63df21694dbaf909ebf46ce0ff04f3979fe13723ae1a823c65f27e56efa19e88f9e7b8ee56eac34353b944067deded3a")
@ -119,25 +122,26 @@ func TestRSAPSSVerifierWithInvalidKey(t *testing.T) {
// Create and call Verify on the verifier
rsaVerifier := RSAPSSVerifier{}
err := rsaVerifier.Verify(&testRSAKey, signedData, message)
err = rsaVerifier.Verify(testRSAKey, signedData, message)
assert.Error(t, err, "invalid key type for RSAPSS verifier: ecdsa")
}
func TestRSAPSSVerifierWithInvalidSignature(t *testing.T) {
var testRSAKey data.TUFKey
var testRSAKey data.PrivateKey
var jsonKey bytes.Buffer
// Execute our template
templ, _ := template.New("KeyTemplate").Parse(baseRSAKey)
templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAKey})
json.Unmarshal(jsonKey.Bytes(), &testRSAKey)
testRSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes())
assert.NoError(t, err)
// Sign some data using RSAPSS
message := []byte("test data for signing")
hash := crypto.SHA256
hashed := sha256.Sum256(message)
signedData, err := rsaPSSSign(&testRSAKey, hash, hashed[:])
signedData, err := rsaPSSSign(testRSAKey, hash, hashed[:])
assert.NoError(t, err)
// Modify the signature
@ -145,44 +149,46 @@ func TestRSAPSSVerifierWithInvalidSignature(t *testing.T) {
// Create and call Verify on the verifier
rsaVerifier := RSAPSSVerifier{}
err = rsaVerifier.Verify(&testRSAKey, signedData, message)
err = rsaVerifier.Verify(testRSAKey, signedData, message)
assert.Error(t, err, "signature verification failed")
}
func TestRSAPKCS1v15Verifier(t *testing.T) {
// Unmarshal our private RSA Key
var testRSAKey data.TUFKey
var testRSAKey data.PrivateKey
var jsonKey bytes.Buffer
// Execute our template
templ, _ := template.New("KeyTemplate").Parse(baseRSAKey)
templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAKey})
json.Unmarshal(jsonKey.Bytes(), &testRSAKey)
testRSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes())
assert.NoError(t, err)
// Sign some data using RSAPKCS1v15
message := []byte("test data for signing")
hash := crypto.SHA256
hashed := sha256.Sum256(message)
signedData, err := rsaPKCS1v15Sign(&testRSAKey, hash, hashed[:])
signedData, err := rsaPKCS1v15Sign(testRSAKey, hash, hashed[:])
assert.NoError(t, err)
// Create and call Verify on the verifier
rsaVerifier := RSAPKCS1v15Verifier{}
err = rsaVerifier.Verify(&testRSAKey, signedData, message)
err = rsaVerifier.Verify(testRSAKey, signedData, message)
assert.NoError(t, err, "expecting success but got error while verifying data using RSAPKCS1v15")
}
func TestRSAPKCS1v15x509Verifier(t *testing.T) {
// Unmarshal our public RSA Key
var testRSAKey data.TUFKey
var testRSAKey data.PrivateKey
var jsonKey bytes.Buffer
// Execute our template
templ, _ := template.New("KeyTemplate").Parse(baseRSAx509Key)
templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAx509Key})
json.Unmarshal(jsonKey.Bytes(), &testRSAKey)
testRSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes())
assert.NoError(t, err)
// Valid signed message
signedData, _ := hex.DecodeString("a19602f609646d57f3d0db930bbe491a997baf33f13191916713734ae778ddb4898ece2078741bb0c24d726514c6b4538c3665c374b0b8ec9ff234b45459633268224c9962756ad3684aca5f13a286657375e798ddcb857ed2707c900f097666b958df56b43b790357430c2e7a5c379ba9972c8b008363c144aac5c7e0fbfad83cf6855cf73baf8e3ad774e910ba6ac8dc4cce58fe19cffb7b0a1feaa73d23ebd2d59de2d7d9e98a809d73a310c5396df64ff7a22d735e661e39d37a6c4a013caa6005e91f597ea35db24e6c750d704d292a180128dcf72a818c53a96b0a83ba0414a3611097905262eb79a6ced1484af27c7da6809aa21ae7c6f05ae6568d5e5d9c170470213a30caf2340c3d52e7bd4056d22074daffee6e29d0a6fd3ca6dbd001831fb1e48573f3663b63e110cde19efaf56e49a835aeda82e4d7286de591376ecd03de36d402ec703f39f79b2f764f991d8950a119f2618f6d4e4618114900597a1e89ced609949410623a17b97095afe08babc4c295ade954f055ca01b7909f5585e98eb99bd916583476aa877d20da8f4fe35c0867e934f41c935d469664b80904a93f9f4d9432cabd9383e08559d6452f8e12b2d861412c450709ff874ad63c25a640605a41c4073f0eb4e16e1965abf8e088e210cbf9d3ca884ec2c13fc8a288cfcef2425d9607fcab01dab45c5c346671a9ae1d0e52c81379fa212c")
@ -190,19 +196,20 @@ func TestRSAPKCS1v15x509Verifier(t *testing.T) {
// Create and call Verify on the verifier
rsaVerifier := RSAPKCS1v15Verifier{}
err := rsaVerifier.Verify(&testRSAKey, signedData, message)
err = rsaVerifier.Verify(testRSAKey, signedData, message)
assert.NoError(t, err, "expecting success but got error while verifying data using RSAPKCS1v15 and an X509 encoded Key")
}
func TestRSAPKCS1v15VerifierWithInvalidKeyType(t *testing.T) {
var testRSAKey data.TUFKey
var testRSAKey data.PrivateKey
var jsonKey bytes.Buffer
// Execute our template
templ, _ := template.New("KeyTemplate").Parse(baseRSAKey)
templ.Execute(&jsonKey, KeyTemplate{KeyType: "rsa-invalid"})
json.Unmarshal(jsonKey.Bytes(), &testRSAKey)
testRSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes())
assert.NoError(t, err)
// Valid signed data with invalidRsaKeyJSON
signedData, _ := hex.DecodeString("2741a57a5ef89f841b4e0a6afbcd7940bc982cd919fbd11dfc21b5ccfe13855b9c401e3df22da5480cef2fa585d0f6dfc6c35592ed92a2a18001362c3a17f74da3906684f9d81c5846bf6a09e2ede6c009ae164f504e6184e666adb14eadf5f6e12e07ff9af9ad49bf1ea9bcfa3bebb2e33be7d4c0fabfe39534f98f1e3c4bff44f637cff3dae8288aea54d86476a3f1320adc39008eae24b991c1de20744a7967d2e685ac0bcc0bc725947f01c9192ffd3e9300eba4b7faa826e84478493fdf97c705dd331dd46072050d6c5e317c2d63df21694dbaf909ebf46ce0ff04f3979fe13723ae1a823c65f27e56efa19e88f9e7b8ee56eac34353b944067deded3a")
@ -210,19 +217,20 @@ func TestRSAPKCS1v15VerifierWithInvalidKeyType(t *testing.T) {
// Create and call Verify on the verifier
rsaVerifier := RSAPKCS1v15Verifier{}
err := rsaVerifier.Verify(&testRSAKey, signedData, message)
err = rsaVerifier.Verify(testRSAKey, signedData, message)
assert.Error(t, err, "invalid key type for RSAPKCS1v15 verifier: rsa-invalid")
}
func TestRSAPKCS1v15VerifierWithInvalidKey(t *testing.T) {
var testRSAKey data.TUFKey
var testRSAKey data.PrivateKey
var jsonKey bytes.Buffer
// Execute our template
templ, _ := template.New("KeyTemplate").Parse(baseECDSAKey)
templ.Execute(&jsonKey, KeyTemplate{KeyType: "ecdsa"})
json.Unmarshal(jsonKey.Bytes(), &testRSAKey)
testRSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes())
assert.NoError(t, err)
// Valid signed data with invalidRsaKeyJSON
signedData, _ := hex.DecodeString("2741a57a5ef89f841b4e0a6afbcd7940bc982cd919fbd11dfc21b5ccfe13855b9c401e3df22da5480cef2fa585d0f6dfc6c35592ed92a2a18001362c3a17f74da3906684f9d81c5846bf6a09e2ede6c009ae164f504e6184e666adb14eadf5f6e12e07ff9af9ad49bf1ea9bcfa3bebb2e33be7d4c0fabfe39534f98f1e3c4bff44f637cff3dae8288aea54d86476a3f1320adc39008eae24b991c1de20744a7967d2e685ac0bcc0bc725947f01c9192ffd3e9300eba4b7faa826e84478493fdf97c705dd331dd46072050d6c5e317c2d63df21694dbaf909ebf46ce0ff04f3979fe13723ae1a823c65f27e56efa19e88f9e7b8ee56eac34353b944067deded3a")
@ -230,25 +238,26 @@ func TestRSAPKCS1v15VerifierWithInvalidKey(t *testing.T) {
// Create and call Verify on the verifier
rsaVerifier := RSAPKCS1v15Verifier{}
err := rsaVerifier.Verify(&testRSAKey, signedData, message)
err = rsaVerifier.Verify(testRSAKey, signedData, message)
assert.Error(t, err, "invalid key type for RSAPKCS1v15 verifier: ecdsa")
}
func TestRSAPKCS1v15VerifierWithInvalidSignature(t *testing.T) {
var testRSAKey data.TUFKey
var testRSAKey data.PrivateKey
var jsonKey bytes.Buffer
// Execute our template
templ, _ := template.New("KeyTemplate").Parse(baseRSAKey)
templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAKey})
json.Unmarshal(jsonKey.Bytes(), &testRSAKey)
testRSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes())
assert.NoError(t, err)
// Sign some data using RSAPKCS1v15
message := []byte("test data for signing")
hash := crypto.SHA256
hashed := sha256.Sum256(message)
signedData, err := rsaPKCS1v15Sign(&testRSAKey, hash, hashed[:])
signedData, err := rsaPKCS1v15Sign(testRSAKey, hash, hashed[:])
assert.NoError(t, err)
// Modify the signature
@ -256,29 +265,30 @@ func TestRSAPKCS1v15VerifierWithInvalidSignature(t *testing.T) {
// Create and call Verify on the verifier
rsaVerifier := RSAPKCS1v15Verifier{}
err = rsaVerifier.Verify(&testRSAKey, signedData, message)
err = rsaVerifier.Verify(testRSAKey, signedData, message)
assert.Error(t, err, "signature verification failed")
}
func TestECDSAVerifier(t *testing.T) {
var testECDSAKey data.TUFKey
var testECDSAKey data.PrivateKey
var jsonKey bytes.Buffer
// Execute our template
templ, _ := template.New("KeyTemplate").Parse(baseECDSAKey)
templ.Execute(&jsonKey, KeyTemplate{KeyType: data.ECDSAKey})
json.Unmarshal(jsonKey.Bytes(), &testECDSAKey)
testECDSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes())
assert.NoError(t, err)
// Sign some data using ECDSA
message := []byte("test data for signing")
hashed := sha256.Sum256(message)
signedData, err := ecdsaSign(&testECDSAKey, hashed[:])
signedData, err := ecdsaSign(testECDSAKey, hashed[:])
assert.NoError(t, err)
// Create and call Verify on the verifier
ecdsaVerifier := ECDSAVerifier{}
err = ecdsaVerifier.Verify(&testECDSAKey, signedData, message)
err = ecdsaVerifier.Verify(testECDSAKey, signedData, message)
assert.NoError(t, err, "expecting success but got error while verifying data using ECDSA")
}
@ -296,7 +306,8 @@ func TestECDSAVerifierOtherCurves(t *testing.T) {
ecdsaPrivKeyBytes, err := x509.MarshalECPrivateKey(ecdsaPrivKey)
assert.NoError(t, err, "failed to marshal private key")
testECDSAKey := data.NewPrivateKey(data.ECDSAKey, ecdsaPubBytes, ecdsaPrivKeyBytes)
testECDSAPubKey := data.NewECDSAPublicKey(ecdsaPubBytes)
testECDSAKey := data.NewECDSAPrivateKey(*testECDSAPubKey, ecdsaPrivKeyBytes)
// Sign some data using ECDSA
message := []byte("test data for signing")
@ -317,14 +328,15 @@ func TestECDSAVerifierOtherCurves(t *testing.T) {
}
func TestECDSAx509Verifier(t *testing.T) {
var testECDSAKey data.TUFKey
var testECDSAKey data.PrivateKey
var jsonKey bytes.Buffer
// Execute our template
templ, _ := template.New("KeyTemplate").Parse(baseECDSAx509Key)
templ.Execute(&jsonKey, KeyTemplate{KeyType: data.ECDSAx509Key})
json.Unmarshal(jsonKey.Bytes(), &testECDSAKey)
testECDSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes())
assert.NoError(t, err)
// Valid signature for message
signedData, _ := hex.DecodeString("b82e0ed5c5dddd74c8d3602bfd900c423511697c3cfe54e1d56b9c1df599695c53aa0caafcdc40df3ef496d78ccf67750ba9413f1ccbd8b0ef137f0da1ee9889")
@ -332,19 +344,20 @@ func TestECDSAx509Verifier(t *testing.T) {
// Create and call Verify on the verifier
ecdsaVerifier := ECDSAVerifier{}
err := ecdsaVerifier.Verify(&testECDSAKey, signedData, message)
err = ecdsaVerifier.Verify(testECDSAKey, signedData, message)
assert.NoError(t, err, "expecting success but got error while verifying data using ECDSA and an x509 encoded key")
}
func TestECDSAVerifierWithInvalidKeyType(t *testing.T) {
var testECDSAKey data.TUFKey
var testECDSAKey data.PrivateKey
var jsonKey bytes.Buffer
// Execute our template
templ, _ := template.New("KeyTemplate").Parse(baseECDSAKey)
templ.Execute(&jsonKey, KeyTemplate{KeyType: "ecdsa-invalid"})
json.Unmarshal(jsonKey.Bytes(), &testECDSAKey)
testECDSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes())
assert.NoError(t, err)
// Valid signature using invalidECDSAx509Key
signedData, _ := hex.DecodeString("7b1c45a4dd488a087db46ee459192d890d4f52352620cb84c2c10e0ce8a67fd6826936463a91ffdffab8e6f962da6fc3d3e5735412f7cd161a9fcf97ba1a7033")
@ -352,19 +365,20 @@ func TestECDSAVerifierWithInvalidKeyType(t *testing.T) {
// Create and call Verify on the verifier
ecdsaVerifier := ECDSAVerifier{}
err := ecdsaVerifier.Verify(&testECDSAKey, signedData, message)
err = ecdsaVerifier.Verify(testECDSAKey, signedData, message)
assert.Error(t, err, "invalid key type for ECDSA verifier: ecdsa-invalid")
}
func TestECDSAVerifierWithInvalidKey(t *testing.T) {
var testECDSAKey data.TUFKey
var testECDSAKey data.PrivateKey
var jsonKey bytes.Buffer
// Execute our template
templ, _ := template.New("KeyTemplate").Parse(baseRSAKey)
templ.Execute(&jsonKey, KeyTemplate{KeyType: "rsa"})
json.Unmarshal(jsonKey.Bytes(), &testECDSAKey)
testECDSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes())
assert.NoError(t, err)
// Valid signature using invalidECDSAx509Key
signedData, _ := hex.DecodeString("7b1c45a4dd488a087db46ee459192d890d4f52352620cb84c2c10e0ce8a67fd6826936463a91ffdffab8e6f962da6fc3d3e5735412f7cd161a9fcf97ba1a7033")
@ -372,24 +386,25 @@ func TestECDSAVerifierWithInvalidKey(t *testing.T) {
// Create and call Verify on the verifier
ecdsaVerifier := ECDSAVerifier{}
err := ecdsaVerifier.Verify(&testECDSAKey, signedData, message)
err = ecdsaVerifier.Verify(testECDSAKey, signedData, message)
assert.Error(t, err, "invalid key type for ECDSA verifier: rsa")
}
func TestECDSAVerifierWithInvalidSignature(t *testing.T) {
var testECDSAKey data.TUFKey
var testECDSAKey data.PrivateKey
var jsonKey bytes.Buffer
// Execute our template
templ, _ := template.New("KeyTemplate").Parse(baseECDSAKey)
templ.Execute(&jsonKey, KeyTemplate{KeyType: data.ECDSAKey})
json.Unmarshal(jsonKey.Bytes(), &testECDSAKey)
testECDSAKey, err := data.UnmarshalPrivateKey(jsonKey.Bytes())
assert.NoError(t, err)
// Sign some data using ECDSA
message := []byte("test data for signing")
hashed := sha256.Sum256(message)
signedData, err := ecdsaSign(&testECDSAKey, hashed[:])
signedData, err := ecdsaSign(testECDSAKey, hashed[:])
assert.NoError(t, err)
// Modify the signature
@ -397,7 +412,7 @@ func TestECDSAVerifierWithInvalidSignature(t *testing.T) {
// Create and call Verify on the verifier
ecdsaVerifier := ECDSAVerifier{}
err = ecdsaVerifier.Verify(&testECDSAKey, signedData, message)
err = ecdsaVerifier.Verify(testECDSAKey, signedData, message)
assert.Error(t, err, "signature verification failed")
}
@ -419,7 +434,7 @@ func TestRSAPyCryptoVerifierInvalidKeyType(t *testing.T) {
}
func rsaPSSSign(privKey data.PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
if privKey.Algorithm() != data.RSAKey {
if privKey, ok := privKey.(*data.RSAPrivateKey); !ok {
return nil, fmt.Errorf("private key type not supported: %s", privKey.Algorithm())
}
@ -439,7 +454,7 @@ func rsaPSSSign(privKey data.PrivateKey, hash crypto.Hash, hashed []byte) ([]byt
}
func rsaPKCS1v15Sign(privKey data.PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
if privKey.Algorithm() != data.RSAKey {
if privKey, ok := privKey.(*data.RSAPrivateKey); !ok {
return nil, fmt.Errorf("private key type not supported: %s", privKey.Algorithm())
}
@ -459,7 +474,7 @@ func rsaPKCS1v15Sign(privKey data.PrivateKey, hash crypto.Hash, hashed []byte) (
}
func ecdsaSign(privKey data.PrivateKey, hashed []byte) ([]byte, error) {
if privKey.Algorithm() != data.ECDSAKey {
if _, ok := privKey.(*data.ECDSAPrivateKey); !ok {
return nil, fmt.Errorf("private key type not supported: %s", privKey.Algorithm())
}
@ -487,29 +502,3 @@ func ecdsaSign(privKey data.PrivateKey, hashed []byte) ([]byte, error) {
return append(rBuf, sBuf...), nil
}
// Use this function to generate the X509 signatures that are hardcoded into
// the test
func signX509() {
// Unmarshal our private RSA Key
var testRSAKey data.TUFKey
var jsonKey bytes.Buffer
// Execute our template
templ, _ := template.New("KeyTemplate").Parse(baseRSAx509Key)
templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAKey})
json.Unmarshal(jsonKey.Bytes(), &testRSAKey)
message := []byte("test data for signing")
hash := crypto.SHA256
hashed := sha256.Sum256(message)
// Use the RSA key to RSAPKCS1v15 sign the data
signedData, _ := rsaPKCS1v15Sign(&testRSAKey, hash, hashed[:])
fmt.Println("signed with pkcs1v15:", hex.EncodeToString(signedData))
// Use the RSA key to RSAPSS sign the data
signedData, _ = rsaPSSSign(&testRSAKey, hash, hashed[:])
fmt.Println("signed with pss:", hex.EncodeToString(signedData))
}

View File

@ -83,11 +83,10 @@ func (tr *Repo) AddBaseKeys(role string, keys ...data.PublicKey) error {
ids := []string{}
for _, k := range keys {
// Store only the public portion
pubKey := data.NewPrivateKey(k.Algorithm(), k.Public(), nil)
tr.Root.Signed.Keys[pubKey.ID()] = pubKey
tr.Root.Signed.Keys[k.ID()] = k
tr.keysDB.AddKey(k)
tr.Root.Signed.Roles[role].KeyIDs = append(tr.Root.Signed.Roles[role].KeyIDs, pubKey.ID())
ids = append(ids, pubKey.ID())
tr.Root.Signed.Roles[role].KeyIDs = append(tr.Root.Signed.Roles[role].KeyIDs, k.ID())
ids = append(ids, k.ID())
}
r, err := data.NewRole(
role,
@ -162,7 +161,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 *Repo) UpdateDelegations(role *data.Role, keys []data.PublicKey, before string) error {
if !role.IsDelegation() || !role.IsValid() {
return errors.ErrInvalidRole{}
}
@ -172,12 +171,11 @@ func (tr *Repo) UpdateDelegations(role *data.Role, keys []data.Key, before strin
return errors.ErrInvalidRole{}
}
for _, k := range keys {
key := data.NewPublicKey(k.Algorithm(), k.Public())
if !utils.StrSliceContains(role.KeyIDs, key.ID()) {
role.KeyIDs = append(role.KeyIDs, key.ID())
if !utils.StrSliceContains(role.KeyIDs, k.ID()) {
role.KeyIDs = append(role.KeyIDs, k.ID())
}
p.Signed.Delegations.Keys[key.ID()] = key
tr.keysDB.AddKey(key)
p.Signed.Delegations.Keys[k.ID()] = k
tr.keysDB.AddKey(k)
}
i := -1
@ -234,9 +232,7 @@ func (tr *Repo) InitRoot(consistent bool) error {
// don't need to check if GetKey returns nil, Key presence was
// checked by KeyDB when role was added.
key := tr.keysDB.GetKey(kid)
// Create new key object to doubly ensure private key is excluded
k := data.NewPublicKey(key.Algorithm(), key.Public())
rootKeys[kid] = k
rootKeys[kid] = key
}
}
root, err := data.NewRoot(rootKeys, rootRoles, consistent)

View File

@ -142,7 +142,7 @@ func TestUpdateDelegations(t *testing.T) {
t.Fatal(err)
}
err = repo.UpdateDelegations(role, []data.Key{testKey}, "")
err = repo.UpdateDelegations(role, data.KeyList{testKey}, "")
if err != nil {
t.Fatal(err)
}
@ -156,7 +156,7 @@ func TestUpdateDelegations(t *testing.T) {
t.Fatal(err)
}
err = repo.UpdateDelegations(roleDeep, []data.Key{testDeepKey}, "")
err = repo.UpdateDelegations(roleDeep, data.KeyList{testDeepKey}, "")
if err != nil {
t.Fatal(err)
}