github.com/trustbloc/kms-go@v1.1.2/crypto/tinkcrypto/primitive/secp256k1/subtle/secp256k1_signer.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package subtle
     8  
     9  import (
    10  	"crypto/ecdsa"
    11  	"crypto/rand"
    12  	"errors"
    13  	"fmt"
    14  	"hash"
    15  	"math/big"
    16  
    17  	"github.com/google/tink/go/subtle"
    18  )
    19  
    20  // Secp256K1Signer is an implementation of Signer for secp256k1 Secp256k2 (Koblitz curve).
    21  // At the moment, the implementation only accepts DER encoding.
    22  type Secp256K1Signer struct {
    23  	privateKey *ecdsa.PrivateKey
    24  	hashFunc   func() hash.Hash
    25  	encoding   string
    26  }
    27  
    28  // NewSecp256K1Signer creates a new instance of Secp256K1Signer.
    29  func NewSecp256K1Signer(hashAlg string,
    30  	curve string,
    31  	encoding string,
    32  	keyValue []byte) (*Secp256K1Signer, error) {
    33  	privKey := new(ecdsa.PrivateKey)
    34  	c := GetCurve(curve)
    35  	privKey.PublicKey.Curve = c
    36  	privKey.D = new(big.Int).SetBytes(keyValue)
    37  	privKey.PublicKey.X, privKey.PublicKey.Y = c.ScalarBaseMult(keyValue)
    38  
    39  	return NewSecp256K1SignerFromPrivateKey(hashAlg, encoding, privKey)
    40  }
    41  
    42  // NewSecp256K1SignerFromPrivateKey creates a new instance of Secp256K1Signer.
    43  func NewSecp256K1SignerFromPrivateKey(hashAlg string, encoding string,
    44  	privateKey *ecdsa.PrivateKey) (*Secp256K1Signer, error) {
    45  	if privateKey.Curve == nil {
    46  		return nil, errors.New("secp256k1_signer: privateKey.Curve can't be nil")
    47  	}
    48  
    49  	curve := ConvertCurveName(privateKey.Curve.Params().Name)
    50  	if err := ValidateSecp256K1Params(hashAlg, curve, encoding); err != nil {
    51  		return nil, fmt.Errorf("secp256k1_signer: %w", err)
    52  	}
    53  
    54  	hashFunc := subtle.GetHashFunc(hashAlg)
    55  
    56  	return &Secp256K1Signer{
    57  		privateKey: privateKey,
    58  		hashFunc:   hashFunc,
    59  		encoding:   encoding,
    60  	}, nil
    61  }
    62  
    63  // Sign computes a signature for the given data.
    64  func (e *Secp256K1Signer) Sign(data []byte) ([]byte, error) {
    65  	hashed, err := subtle.ComputeHash(e.hashFunc, data)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	r, s, err := ecdsa.Sign(rand.Reader, e.privateKey, hashed)
    71  	if err != nil {
    72  		return nil, fmt.Errorf("secp256k1_signer: signing failed: %w", err)
    73  	}
    74  
    75  	// format the signature
    76  	sig := NewSecp256K1Signature(r, s)
    77  
    78  	ret, err := sig.EncodeSecp256K1Signature(e.encoding, e.privateKey.PublicKey.Curve.Params().Name)
    79  	if err != nil {
    80  		return nil, fmt.Errorf("secp256k1_signer: signing failed: %w", err)
    81  	}
    82  
    83  	return ret, nil
    84  }
    85  
    86  // ConvertCurveName converts different forms of a curve name to the name that tink recognizes.
    87  func ConvertCurveName(name string) string {
    88  	switch name {
    89  	case "secp256k1", "secp256K1":
    90  		return "SECP256K1"
    91  	default:
    92  		return ""
    93  	}
    94  }