Skip to content

Commit

Permalink
Add ECDSA private key proto serialization
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 680451595
Change-Id: I70f9dce76f2131795d0ca27a4634fd2cd05dd0a7
  • Loading branch information
morambro authored and copybara-github committed Sep 30, 2024
1 parent d7a3c29 commit 15f7b0e
Show file tree
Hide file tree
Showing 3 changed files with 318 additions and 122 deletions.
2 changes: 2 additions & 0 deletions signature/ecdsa/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,8 @@ func NewPrivateKeyFromPublicKey(publicKey *PublicKey, privateKeyValue secretdata
}

// PrivateKeyValue returns the private key value as [secretdata.Bytes].
//
// The returned private key value has length equal to the size of the curve.
func (k *PrivateKey) PrivateKeyValue() secretdata.Bytes { return k.privateKeyValue }

// PublicKey returns the corresponding public key as [key.Key].
Expand Down
54 changes: 54 additions & 0 deletions signature/ecdsa/protoserialization.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"fmt"

"google.golang.org/protobuf/proto"
"github.com/tink-crypto/tink-go/v2/insecuresecretdataaccess"
"github.com/tink-crypto/tink-go/v2/internal/protoserialization"
"github.com/tink-crypto/tink-go/v2/key"
commonpb "github.com/tink-crypto/tink-go/v2/proto/common_go_proto"
Expand Down Expand Up @@ -337,3 +338,56 @@ func (s *publicKeyParser) ParseKey(keySerialization *protoserialization.KeySeria
keyID, _ := keySerialization.IDRequirement()
return NewPublicKey(publicPoint, keyID, params)
}

type privateKeySerializer struct{}

var _ protoserialization.KeySerializer = (*privateKeySerializer)(nil)

func (s *privateKeySerializer) SerializeKey(key key.Key) (*protoserialization.KeySerialization, error) {
ecdsaPrivKey, ok := key.(*PrivateKey)
if !ok {
return nil, fmt.Errorf("invalid key type: %T, want *ecdsa.PrivateKey", key)
}
// This is nil if PrivateKey was created as a struct literal.
if ecdsaPrivKey.publicKey == nil {
return nil, fmt.Errorf("invalid key: public key is nil")
}
params := ecdsaPrivKey.publicKey.parameters
outputPrefixType, err := protoOutputPrefixTypeFromVariant(params.Variant())
if err != nil {
return nil, err
}

protoPublicKey, err := createProtoECDSAPublicKey(ecdsaPrivKey.publicKey, params)
if err != nil {
return nil, err
}

coordinateSize, err := coordinateSizeForCurve(params.CurveType())
if err != nil {
return nil, err
}
// Key value must be fixed size: 1 + coordinateSize (see b/264525021).
privateKeyValue := make([]byte, 1, coordinateSize+1)
// ecdsaPrivKey.PrivateKeyValue() is guaranteed to have a length of
// coordinateSize.
privateKeyValue = append(privateKeyValue, ecdsaPrivKey.PrivateKeyValue().Data(insecuresecretdataaccess.Token{})...)

protoKey := &ecdsapb.EcdsaPrivateKey{
KeyValue: privateKeyValue,
PublicKey: protoPublicKey,
Version: signerKeyVersion,
}
serializedKey, err := proto.Marshal(protoKey)
if err != nil {
return nil, err
}
// idRequirement is zero if the key doesn't have a key requirement.
idRequirement, _ := ecdsaPrivKey.IDRequirement()
keyData := &tinkpb.KeyData{
TypeUrl: signerTypeURL,
Value: serializedKey,
KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE,
}
return protoserialization.NewKeySerialization(keyData, outputPrefixType, idRequirement)
}
Loading

0 comments on commit 15f7b0e

Please sign in to comment.