Skip to content

Commit

Permalink
use ecdsa for keytype. But when signing, support both formats (#1130)
Browse files Browse the repository at this point in the history
* use ecdsa for keytype. But when signing, support both formats

Signed-off-by: Fredrik Skogman <kommendorkapten@github.com>

* Fixed linter issue and added old fmt to sign script

Signed-off-by: Fredrik Skogman <kommendorkapten@github.com>

---------

Signed-off-by: Fredrik Skogman <kommendorkapten@github.com>
  • Loading branch information
kommendorkapten committed Feb 28, 2024
1 parent 9f2561e commit 1506910
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 58 deletions.
4 changes: 3 additions & 1 deletion cmd/tuf/app/add-delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ func DelegationCmd(ctx context.Context, opts *DelegationOptions) error {
if err != nil {
return err
}
tufKey, err := pkeys.ConstructTufKeyFromPublic(ctx, publicKey)
// When adding the delegation we don't need to carry over the
// older deprecated format.
tufKey, err := pkeys.ConstructTufKeyFromPublic(ctx, publicKey, false)
if err != nil {
return err
}
Expand Down
6 changes: 4 additions & 2 deletions cmd/tuf/app/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ func InitCmd(ctx context.Context, directory string,
}

// Construct TUF key.
tufKey, err := pkeys.ConstructTufKey(ctx, signer)
// Only create keys using the current key type
tufKey, err := pkeys.ConstructTufKey(ctx, signer, false)
if err != nil {
return err
}
Expand Down Expand Up @@ -341,7 +342,8 @@ func getKeysFromDir(dir string) ([]*data.PublicKey, error) {
if err != nil {
return nil, err
}
tufKey, err := pkeys.EcdsaTufKey(key.PublicKey)
// Only add keys with the new format
tufKey, err := pkeys.EcdsaTufKey(key.PublicKey, false)
if err != nil {
return nil, err
}
Expand Down
26 changes: 19 additions & 7 deletions cmd/tuf/app/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func Sign() *ffcli.Command {
sk = flagset.Bool("sk", false, "indicates use of a hardware key for signing")
key = flagset.String("key", "", "reference to a signer for signing")
bumpVersion = flagset.Bool("bump-version", false, "bumps the version; useful for re-signing without changes")
addOldType = flagset.Bool("add-old-type", false, "Add a signature using the old key type")
)
flagset.Var(&roles, "roles", "role(s) to sign")
return &ffcli.Command{
Expand All @@ -80,7 +81,7 @@ func Sign() *ffcli.Command {
if err != nil {
return err
}
return SignCmd(ctx, *repository, roles, signer, *bumpVersion)
return SignCmd(ctx, *repository, roles, signer, *bumpVersion, *addOldType)
},
}
}
Expand Down Expand Up @@ -121,8 +122,8 @@ func checkMetaForRole(store tuf.LocalStore, role []string) error {
return nil
}

func SignCmd(ctx context.Context, directory string, roles []string, signer signature.Signer,
bumpVersion bool) error {
func SignCmd(ctx context.Context, directory string, roles []string,
signer signature.Signer, bumpVersion, addOldType bool) error {
store := tuf.FileSystemStore(directory, nil)

if err := checkMetaForRole(store, roles); err != nil {
Expand All @@ -135,7 +136,7 @@ func SignCmd(ctx context.Context, directory string, roles []string, signer signa
return err
}
}
if err := SignMeta(ctx, store, name+".json", signer); err != nil {
if err := SignMeta(ctx, store, name+".json", signer, addOldType); err != nil {
return err
}
}
Expand All @@ -148,7 +149,8 @@ func SignCmd(ctx context.Context, directory string, roles []string, signer signa
// Note that if you were using old format exclusively (for testing), then this will
// have no impact on repository validity: extraneous key IDs for the role that are
// not attested to in the trusted root or parent delegation will be ignored.
func SignMeta(ctx context.Context, store tuf.LocalStore, name string, signer signature.Signer) error {
func SignMeta(ctx context.Context, store tuf.LocalStore, name string,
signer signature.Signer, addOldType bool) error {
fmt.Printf("Signing metadata for %s... \n", name)
s, err := repo.GetSignedMeta(store, name)
if err != nil {
Expand Down Expand Up @@ -176,10 +178,20 @@ func SignMeta(ctx context.Context, store tuf.LocalStore, name string, signer sig
}

// Get TUF public IDs associated to the signer.
pubKey, err := keys.ConstructTufKey(ctx, signer)
pubKey, err := keys.ConstructTufKey(ctx, signer, false)
var candidateKeyIDs []string
if err != nil {
return err
}
candidateKeyIDs = append(candidateKeyIDs, pubKey.IDs()...)

if addOldType {
oldKey, err := keys.ConstructTufKey(ctx, signer, true)
if err != nil {
return err
}
candidateKeyIDs = append(candidateKeyIDs, oldKey.IDs()...)
}

role := strings.TrimSuffix(name, ".json")
roleSigningKeys, err := repo.GetSigningKeyIDsForRole(role, store)
Expand All @@ -189,7 +201,7 @@ func SignMeta(ctx context.Context, store tuf.LocalStore, name string, signer sig

// Filter key IDs with the role signing key map.
var keyIDs []string
for _, id := range pubKey.IDs() {
for _, id := range candidateKeyIDs {
// We check to make sure that the key ID is associated with the role's keys.
if _, ok := roleSigningKeys[id]; !ok {
continue
Expand Down
21 changes: 13 additions & 8 deletions cmd/verify/app/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,23 @@ func verifySigningKeys(dirname string, rootCA *x509.Certificate) (*KeyMap, error
log.Printf("error verifying key %d: %s", key.SerialNumber, err)
return nil, err
}
tufKey, err := keys.EcdsaTufKey(key.PublicKey)
if err != nil {
return nil, err
}
if len(tufKey.IDs()) == 0 {
return nil, errors.New("error getting key ID")

for _, bv := range []bool{true, false} {
tufKey, err := keys.EcdsaTufKey(key.PublicKey, bv)
if err != nil {
return nil, err
}
if len(tufKey.IDs()) == 0 {
return nil, errors.New("error getting key ID")
}
keyMap[tufKey.IDs()[0]] = key
}
keyMap[tufKey.IDs()[0]] = key

log.Printf("\nVERIFIED KEY WITH SERIAL NUMBER %d\n", key.SerialNumber)
log.Printf("TUF key ids: \n")
log.Printf("\t%s ", tufKey.IDs()[0])
for kid := range keyMap {
log.Printf("\t%s ", kid)
}
}
}
// Note we use relative path here to simplify things.
Expand Down
20 changes: 14 additions & 6 deletions pkg/keys/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,23 @@ func ToSigningKey(serialNumber int, pubKey []byte, deviceCert []byte, keyCert []
}

// EcdsaTufKey returns a PEM-encoded TUF public key for an ecdsa key.
func EcdsaTufKey(pub *ecdsa.PublicKey) (*data.PublicKey, error) {
func EcdsaTufKey(pub *ecdsa.PublicKey, deprecatedType bool) (*data.PublicKey, error) {
keyValBytes, err := json.Marshal(keys.EcdsaVerifier{
PublicKey: &keys.PKIXPublicKey{PublicKey: pub}})
if err != nil {
return nil, err
}

var keyType data.KeyType
if deprecatedType {
keyType = data.KeyTypeECDSA_SHA2_P256_OLD_FMT
} else {
keyType = data.KeyTypeECDSA_SHA2_P256
}

return &data.PublicKey{
// TODO: Update to new format for next key signing
Type: data.KeyTypeECDSA_SHA2_P256_OLD_FMT,
Type: keyType,
Scheme: data.KeySchemeECDSA_SHA2_P256,
Algorithms: data.HashAlgorithms,
Value: keyValBytes,
Expand Down Expand Up @@ -198,19 +206,19 @@ func (key SigningKey) Verify(root *x509.Certificate) error {
}

// ConstructTufKey constructs a TUF public key from a given signer.
func ConstructTufKey(ctx context.Context, signer signature.Signer) (*data.PublicKey, error) {
func ConstructTufKey(ctx context.Context, signer signature.Signer, deprecated bool) (*data.PublicKey, error) {
pub, err := signer.PublicKey(options.WithContext(ctx))
if err != nil {
return nil, err
}
return ConstructTufKeyFromPublic(ctx, pub)
return ConstructTufKeyFromPublic(ctx, pub, deprecated)
}

// ConstructTufKey constructs a TUF public key from a public key
func ConstructTufKeyFromPublic(_ context.Context, pubKey crypto.PublicKey) (*data.PublicKey, error) {
func ConstructTufKeyFromPublic(_ context.Context, pubKey crypto.PublicKey, deprecated bool) (*data.PublicKey, error) {
switch kt := pubKey.(type) {
case *ecdsa.PublicKey:
return EcdsaTufKey(kt)
return EcdsaTufKey(kt, deprecated)
default:
return nil, fmt.Errorf("ConstructTufKeyFromPublic: key type %s not supported", kt)
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/keys/keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func TestToSigningKey(t *testing.T) {
t.Errorf("unexpected error generating signing key (%s): %s", tt.name, err)
}
if tt.expectSuccess {
pemPubKey, err := EcdsaTufKey(key.PublicKey)
pemPubKey, err := EcdsaTufKey(key.PublicKey, true)
if err != nil {
t.Errorf("unexpected error generating PEM TUF public key: %s", err)
}
Expand All @@ -184,7 +184,7 @@ func TestGetSigningKey(t *testing.T) {
}

t.Run("valid signing key with PEM", func(t *testing.T) {
signingKeyPem, err := ConstructTufKey(ctx, signingKey)
signingKeyPem, err := ConstructTufKey(ctx, signingKey, true)
if err != nil {
t.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/step-2.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ checkout_branch
read -n1 -r -s -p "Insert your Yubikey, then press any key to continue...\n"

# Sign the root and targets with hardware key
./tuf sign -repository "$REPO" -roles root -roles targets -sk
./tuf sign -repository "$REPO" -roles root -roles targets -sk -add-old-type true

# Ask user to remove key (and replace with SSH security key)
read -n1 -r -s -p "Remove your Yubikey, then press any key to continue...\n"
Expand Down
Loading

0 comments on commit 1506910

Please sign in to comment.