Skip to content

Commit

Permalink
Merge pull request #98 from flynn/ecdsa
Browse files Browse the repository at this point in the history
ECDSA verification support
  • Loading branch information
titanous authored Aug 13, 2016
2 parents f861e9c + 596db52 commit 0b3fbb9
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 19 deletions.
5 changes: 3 additions & 2 deletions data/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import (
)

const (
KeyIDLength = sha256.Size * 2
KeyTypeEd25519 = "ed25519"
KeyIDLength = sha256.Size * 2
KeyTypeEd25519 = "ed25519"
KeyTypeECDSA_SHA2_P256 = "ecdsa-sha2-nistp256"
)

type Signed struct {
Expand Down
41 changes: 40 additions & 1 deletion verify/verifiers.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package verify

import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/sha256"
"encoding/asn1"
"math/big"

"github.com/flynn/go-tuf/data"
"golang.org/x/crypto/ed25519"
)
Expand All @@ -19,7 +25,8 @@ type Verifier interface {

// Verifiers is used to map key types to Verifier instances.
var Verifiers = map[string]Verifier{
data.KeyTypeEd25519: ed25519Verifier{},
data.KeyTypeEd25519: ed25519Verifier{},
data.KeyTypeECDSA_SHA2_P256: p256Verifier{},
}

type ed25519Verifier struct{}
Expand All @@ -34,3 +41,35 @@ func (ed25519Verifier) Verify(key, msg, sig []byte) error {
func (ed25519Verifier) ValidKey(k []byte) bool {
return len(k) == ed25519.PublicKeySize
}

type ecdsaSignature struct {
R, S *big.Int
}

type p256Verifier struct{}

func (p256Verifier) Verify(key, msg, sigBytes []byte) error {
x, y := elliptic.Unmarshal(elliptic.P256(), key)
k := &ecdsa.PublicKey{
Curve: elliptic.P256(),
X: x,
Y: y,
}

var sig ecdsaSignature
if _, err := asn1.Unmarshal(sigBytes, &sig); err != nil {
return ErrInvalid
}

hash := sha256.Sum256(msg)

if !ecdsa.Verify(k, hash[:], sig.R, sig.S) {
return ErrInvalid
}
return nil
}

func (p256Verifier) ValidKey(k []byte) bool {
x, _ := elliptic.Unmarshal(elliptic.P256(), k)
return x != nil
}
12 changes: 1 addition & 11 deletions verify/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (

"github.com/flynn/go-tuf/data"
"github.com/tent/canonical-json-go"
"golang.org/x/crypto/ed25519"
)

type signedMeta struct {
Expand Down Expand Up @@ -62,15 +61,7 @@ func (db *DB) VerifySignatures(s *data.Signed, role string) error {
}

valid := make(map[string]struct{})
var sigBytes [ed25519.SignatureSize]byte
for _, sig := range s.Signatures {
if _, ok := Verifiers[sig.Method]; !ok {
return ErrWrongMethod
}
if len(sig.Signature) != len(sigBytes) {
return ErrInvalid
}

if !roleData.ValidKey(sig.KeyID) {
continue
}
Expand All @@ -79,8 +70,7 @@ func (db *DB) VerifySignatures(s *data.Signed, role string) error {
continue
}

copy(sigBytes[:], sig.Signature)
if err := Verifiers[sig.Method].Verify(key.Value.Public, msg, sigBytes[:]); err != nil {
if err := Verifiers[key.Type].Verify(key.Value.Public, msg, sig.Signature); err != nil {
return err
}
valid[sig.KeyID] = struct{}{}
Expand Down
59 changes: 54 additions & 5 deletions verify/verify_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package verify

import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"io"
"testing"
"time"

Expand All @@ -18,6 +24,31 @@ type VerifySuite struct{}

var _ = Suite(&VerifySuite{})

type ecdsaSigner struct {
*ecdsa.PrivateKey
}

func (s ecdsaSigner) PublicData() *data.Key {
pub := s.Public().(*ecdsa.PublicKey)
return &data.Key{
Type: data.KeyTypeECDSA_SHA2_P256,
Value: data.KeyValue{Public: elliptic.Marshal(pub.Curve, pub.X, pub.Y)},
}
}

func (s ecdsaSigner) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
hash := sha256.Sum256(msg)
return s.PrivateKey.Sign(rand, hash[:], crypto.SHA256)
}

func (s ecdsaSigner) ID() string {
return s.PublicData().ID()
}

func (ecdsaSigner) Type() string {
return data.KeyTypeECDSA_SHA2_P256
}

func (VerifySuite) Test(c *C) {
type test struct {
name string
Expand Down Expand Up @@ -45,11 +76,6 @@ func (VerifySuite) Test(c *C) {
role: "foo",
err: ErrUnknownRole,
},
{
name: "wrong signature method",
mut: func(t *test) { t.s.Signatures[0].Method = "foo" },
err: ErrWrongMethod,
},
{
name: "signature wrong length",
mut: func(t *test) { t.s.Signatures[0].Signature = []byte{0} },
Expand Down Expand Up @@ -139,6 +165,29 @@ func (VerifySuite) Test(c *C) {
exp: &expiredTime,
err: ErrExpired{expiredTime},
},
{
name: "valid ecdsa signature",
mut: func(t *test) {
k, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
s := ecdsaSigner{k}
sign.Sign(t.s, s)
t.s.Signatures = t.s.Signatures[1:]
t.keys = []*data.Key{s.PublicData()}
t.roles["root"].KeyIDs = []string{s.PublicData().ID()}
},
},
{
name: "invalid ecdsa signature",
mut: func(t *test) {
k, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
s := ecdsaSigner{k}
sign.Sign(t.s, s)
t.s.Signatures[1].Signature[0]++
t.keys = append(t.keys, s.PublicData())
t.roles["root"].KeyIDs = append(t.roles["root"].KeyIDs, s.PublicData().ID())
},
err: ErrInvalid,
},
}
for _, t := range tests {
if t.role == "" {
Expand Down

0 comments on commit 0b3fbb9

Please sign in to comment.