-
Notifications
You must be signed in to change notification settings - Fork 110
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
…357) * * fix!: ECDSA verifiers now expect PEM-encoded public keys per TUF specification * feat: ECDSA signers are now implemented * feat: RSA verifiers and signers are implemented BREAKING CHANGE: ECDSA verifiers expect PEM-encoded public keys. If you rely on previous behavior of hex-encoded public keys for verifiers, then you must import pkg/deprecated/set_ecdsa that will allow a fallback for hex-encoded ECDSA keys. Co-authored-by: Asra Ali <asraa@google.com> Co-authored-by: Toby Bristow <toby.bristow@qush.com> Signed-off-by: Asra Ali <asraa@google.com> * add comment Signed-off-by: Asra Ali <asraa@google.com> Signed-off-by: Asra Ali <asraa@google.com> Co-authored-by: Toby Bristow <toby.bristow@qush.com>
- Loading branch information
Showing
20 changed files
with
932 additions
and
148 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package deprecated | ||
|
||
import ( | ||
"crypto" | ||
"crypto/elliptic" | ||
"crypto/rand" | ||
"crypto/sha256" | ||
"encoding/json" | ||
"testing" | ||
|
||
"github.com/secure-systems-lab/go-securesystemslib/cjson" | ||
repo "github.com/theupdateframework/go-tuf" | ||
"github.com/theupdateframework/go-tuf/data" | ||
_ "github.com/theupdateframework/go-tuf/pkg/deprecated/set_ecdsa" | ||
"github.com/theupdateframework/go-tuf/pkg/keys" | ||
. "gopkg.in/check.v1" | ||
) | ||
|
||
func Test(t *testing.T) { TestingT(t) } | ||
|
||
type RepoSuite struct{} | ||
|
||
var _ = Suite(&RepoSuite{}) | ||
|
||
func genKey(c *C, r *repo.Repo, role string) []string { | ||
keyids, err := r.GenKey(role) | ||
c.Assert(err, IsNil) | ||
c.Assert(len(keyids) > 0, Equals, true) | ||
return keyids | ||
} | ||
|
||
// Deprecated ecdsa key support: Support verification against roots that were | ||
// signed with hex-encoded ecdsa keys. | ||
func (rs *RepoSuite) TestDeprecatedHexEncodedKeysSucceed(c *C) { | ||
files := map[string][]byte{"foo.txt": []byte("foo")} | ||
local := repo.MemoryStore(make(map[string]json.RawMessage), files) | ||
r, err := repo.NewRepo(local) | ||
c.Assert(err, IsNil) | ||
|
||
r.Init(false) | ||
// Add a root key with hex-encoded ecdsa format | ||
signer, err := keys.GenerateEcdsaKey() | ||
c.Assert(err, IsNil) | ||
type deprecatedP256Verifier struct { | ||
PublicKey data.HexBytes `json:"public"` | ||
} | ||
pub := signer.PublicKey | ||
keyValBytes, err := json.Marshal(&deprecatedP256Verifier{PublicKey: elliptic.Marshal(pub.Curve, pub.X, pub.Y)}) | ||
c.Assert(err, IsNil) | ||
publicData := &data.PublicKey{ | ||
Type: data.KeyTypeECDSA_SHA2_P256, | ||
Scheme: data.KeySchemeECDSA_SHA2_P256, | ||
Algorithms: data.HashAlgorithms, | ||
Value: keyValBytes, | ||
} | ||
err = r.AddVerificationKey("root", publicData) | ||
c.Assert(err, IsNil) | ||
// Add other keys as normal | ||
genKey(c, r, "targets") | ||
genKey(c, r, "snapshot") | ||
genKey(c, r, "timestamp") | ||
c.Assert(r.AddTarget("foo.txt", nil), IsNil) | ||
|
||
// Sign the root role manually | ||
rootMeta, err := r.SignedMeta("root.json") | ||
c.Assert(err, IsNil) | ||
rootCanonical, err := cjson.EncodeCanonical(rootMeta.Signed) | ||
c.Assert(err, IsNil) | ||
hash := sha256.Sum256(rootCanonical) | ||
rootSig, err := signer.PrivateKey.Sign(rand.Reader, hash[:], crypto.SHA256) | ||
c.Assert(err, IsNil) | ||
for _, id := range publicData.IDs() { | ||
c.Assert(r.AddOrUpdateSignature("root.json", data.Signature{ | ||
KeyID: id, | ||
Signature: rootSig}), IsNil) | ||
} | ||
|
||
// Committing should succeed because the deprecated key pkg is added. | ||
c.Assert(r.Snapshot(), IsNil) | ||
c.Assert(r.Timestamp(), IsNil) | ||
c.Assert(r.Commit(), IsNil) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package set_ecdsa | ||
|
||
import ( | ||
"errors" | ||
|
||
"github.com/theupdateframework/go-tuf/data" | ||
"github.com/theupdateframework/go-tuf/pkg/keys" | ||
) | ||
|
||
/* | ||
Importing this package will allow support for both hex-encoded ECDSA | ||
verifiers and PEM-encoded ECDSA verifiers. | ||
Note that this package imports "github.com/theupdateframework/go-tuf/pkg/keys" | ||
and overrides the ECDSA verifier loaded at init time in that package. | ||
*/ | ||
|
||
func init() { | ||
_, ok := keys.VerifierMap.Load(data.KeyTypeECDSA_SHA2_P256) | ||
if !ok { | ||
panic(errors.New("expected to override previously loaded PEM-only ECDSA verifier")) | ||
} | ||
keys.VerifierMap.Store(data.KeyTypeECDSA_SHA2_P256, keys.NewDeprecatedEcdsaVerifier) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package keys | ||
|
||
import ( | ||
"bytes" | ||
"crypto/ecdsa" | ||
"crypto/elliptic" | ||
"crypto/sha256" | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"io" | ||
"os" | ||
|
||
"github.com/theupdateframework/go-tuf/data" | ||
) | ||
|
||
func NewDeprecatedEcdsaVerifier() Verifier { | ||
return &ecdsaVerifierWithDeprecatedSupport{} | ||
} | ||
|
||
type ecdsaVerifierWithDeprecatedSupport struct { | ||
key *data.PublicKey | ||
// This will switch based on whether this is a PEM-encoded key | ||
// or a deprecated hex-encoded key. | ||
Verifier | ||
} | ||
|
||
func (p *ecdsaVerifierWithDeprecatedSupport) UnmarshalPublicKey(key *data.PublicKey) error { | ||
p.key = key | ||
pemVerifier := &EcdsaVerifier{} | ||
if err := pemVerifier.UnmarshalPublicKey(key); err != nil { | ||
// Try the deprecated hex-encoded verifier | ||
hexVerifier := &deprecatedP256Verifier{} | ||
if err := hexVerifier.UnmarshalPublicKey(key); err != nil { | ||
return err | ||
} | ||
p.Verifier = hexVerifier | ||
return nil | ||
} | ||
p.Verifier = pemVerifier | ||
return nil | ||
} | ||
|
||
/* | ||
Deprecated ecdsaVerifier that used hex-encoded public keys. | ||
This MAY be used to verify existing metadata that used this | ||
old format. This will be deprecated soon, ensure that repositories | ||
are re-signed and clients receieve a fully compliant root. | ||
*/ | ||
|
||
type deprecatedP256Verifier struct { | ||
PublicKey data.HexBytes `json:"public"` | ||
key *data.PublicKey | ||
} | ||
|
||
func (p *deprecatedP256Verifier) Public() string { | ||
return p.PublicKey.String() | ||
} | ||
|
||
func (p *deprecatedP256Verifier) Verify(msg, sigBytes []byte) error { | ||
x, y := elliptic.Unmarshal(elliptic.P256(), p.PublicKey) | ||
k := &ecdsa.PublicKey{ | ||
Curve: elliptic.P256(), | ||
X: x, | ||
Y: y, | ||
} | ||
|
||
hash := sha256.Sum256(msg) | ||
|
||
if !ecdsa.VerifyASN1(k, hash[:], sigBytes) { | ||
return errors.New("tuf: deprecated ecdsa signature verification failed") | ||
} | ||
return nil | ||
} | ||
|
||
func (p *deprecatedP256Verifier) MarshalPublicKey() *data.PublicKey { | ||
return p.key | ||
} | ||
|
||
func (p *deprecatedP256Verifier) UnmarshalPublicKey(key *data.PublicKey) error { | ||
// Prepare decoder limited to 512Kb | ||
dec := json.NewDecoder(io.LimitReader(bytes.NewReader(key.Value), MaxJSONKeySize)) | ||
|
||
// Unmarshal key value | ||
if err := dec.Decode(p); err != nil { | ||
if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) { | ||
return fmt.Errorf("tuf: the public key is truncated or too large: %w", err) | ||
} | ||
return err | ||
} | ||
|
||
curve := elliptic.P256() | ||
|
||
// Parse as uncompressed marshalled point. | ||
x, _ := elliptic.Unmarshal(curve, p.PublicKey) | ||
if x == nil { | ||
return errors.New("tuf: invalid ecdsa public key point") | ||
} | ||
|
||
p.key = key | ||
fmt.Fprintln(os.Stderr, "tuf: warning using deprecated ecdsa hex-encoded keys") | ||
return nil | ||
} |
Oops, something went wrong.