github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/sdk/go/src/sawtooth_sdk/signing/secp256k1.go (about)

     1  /**
     2   * Copyright 2017 Intel Corporation
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   * ------------------------------------------------------------------------------
    16   */
    17  
    18  package signing
    19  
    20  import (
    21  	"crypto/sha256"
    22  	"crypto/sha512"
    23  	"encoding/hex"
    24  	ellcurv "github.com/btcsuite/btcd/btcec"
    25  	"math/big"
    26  )
    27  
    28  var cachedCurve = ellcurv.S256()
    29  
    30  // -- Private Key --
    31  
    32  type Secp256k1PrivateKey struct {
    33  	private_key []byte
    34  }
    35  
    36  // Creates a PrivateKey instance from private key bytes.
    37  func NewSecp256k1PrivateKey(private_key []byte) PrivateKey {
    38  	return &Secp256k1PrivateKey{private_key}
    39  }
    40  
    41  // PemToSecp256k1PrivateKey converts a PEM string to a private key.
    42  func PemToSecp256k1PrivateKey(pem string, password string) (*Secp256k1PrivateKey, error) {
    43  	priv, err := pemToPriv(pem, password)
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  
    48  	return &Secp256k1PrivateKey{priv}, nil
    49  }
    50  
    51  // Returns the string "secp256k1".
    52  func (self *Secp256k1PrivateKey) GetAlgorithmName() string {
    53  	return "secp256k1"
    54  }
    55  
    56  // Returns the private key as a hex-encoded string.
    57  func (self *Secp256k1PrivateKey) AsHex() string {
    58  	return hex.EncodeToString(self.private_key)
    59  }
    60  
    61  // Returns the bytes of the private key.
    62  func (self *Secp256k1PrivateKey) AsBytes() []byte {
    63  	return self.private_key
    64  }
    65  
    66  // -- Public Key --
    67  
    68  type Secp256k1PublicKey struct {
    69  	public_key []byte
    70  }
    71  
    72  // Creates a PublicKey instance from public key bytes.
    73  func NewSecp256k1PublicKey(public_key []byte) PublicKey {
    74  	return &Secp256k1PublicKey{public_key}
    75  }
    76  
    77  // Returns the string "secp256k1".
    78  func (self *Secp256k1PublicKey) GetAlgorithmName() string {
    79  	return "secp256k1"
    80  }
    81  
    82  // Returns the public key as a hex-encoded string.
    83  func (self *Secp256k1PublicKey) AsHex() string {
    84  	return hex.EncodeToString(self.public_key)
    85  }
    86  
    87  // Returns the bytes of the public key.
    88  func (self *Secp256k1PublicKey) AsBytes() []byte {
    89  	return self.public_key
    90  }
    91  
    92  // -- Context --
    93  
    94  type Secp256k1Context struct {
    95  	curve *ellcurv.KoblitzCurve
    96  }
    97  
    98  // Returns a new secp256k1 context.
    99  func NewSecp256k1Context() Context {
   100  	return &Secp256k1Context{ellcurv.S256()}
   101  }
   102  
   103  // Returns the string "secp256k1".
   104  func (self *Secp256k1Context) GetAlgorithmName() string {
   105  	return "secp256k1"
   106  }
   107  
   108  // Generates a new random secp256k1 private key.
   109  func (self *Secp256k1Context) NewRandomPrivateKey() PrivateKey {
   110  	priv, _ := ellcurv.NewPrivateKey(cachedCurve)
   111  
   112  	return &Secp256k1PrivateKey{priv.Serialize()}
   113  }
   114  
   115  // Produces a public key for the given private key.
   116  func (self *Secp256k1Context) GetPublicKey(private_key PrivateKey) PublicKey {
   117  	_, public_key := ellcurv.PrivKeyFromBytes(
   118  		cachedCurve,
   119  		private_key.AsBytes())
   120  
   121  	return NewSecp256k1PublicKey(public_key.SerializeCompressed())
   122  }
   123  
   124  // Sign uses the given private key to calculate a signature for the
   125  // given data. A sha256 hash of the data is first calculated and this
   126  // is what is actually signed. Returns the signature as bytes using
   127  // the compact serialization (which is just (r, s)).
   128  func (self *Secp256k1Context) Sign(message []byte, private_key PrivateKey) []byte {
   129  	priv, _ := ellcurv.PrivKeyFromBytes(
   130  		self.curve,
   131  		private_key.AsBytes())
   132  
   133  	hash := doSHA256(message)
   134  
   135  	sig, err := priv.Sign(hash)
   136  	if err != nil {
   137  		panic("Signing failed")
   138  	}
   139  
   140  	return serializeCompact(sig)
   141  }
   142  
   143  // Verify uses the given public key to verify that the given signature
   144  // was created from the given data using the associated private key. A
   145  // sha256 hash of the data is calculated first and this is what is
   146  // actually used to verify the signature.
   147  func (self *Secp256k1Context) Verify(signature []byte, message []byte, public_key PublicKey) bool {
   148  	sig := deserializeCompact(signature)
   149  	hash := doSHA256(message)
   150  
   151  	pub, err := ellcurv.ParsePubKey(
   152  		public_key.AsBytes(),
   153  		self.curve)
   154  	if err != nil {
   155  		panic(err.Error())
   156  	}
   157  
   158  	return sig.Verify(hash, pub)
   159  }
   160  
   161  // -- SHA --
   162  
   163  func doSHA512(input []byte) []byte {
   164  	hash := sha512.New()
   165  	hash.Write(input)
   166  	return hash.Sum(nil)
   167  }
   168  
   169  func doSHA256(input []byte) []byte {
   170  	hash := sha256.New()
   171  	hash.Write(input)
   172  	return hash.Sum(nil)
   173  }
   174  
   175  func pemToPriv(pem string, password string) ([]byte, error) {
   176  	pemlen := len(pem)
   177  	priv, _, err := loadPemKey(pem, pemlen, password)
   178  	if err != nil {
   179  		return nil, err
   180  	}
   181  	return hex.DecodeString(priv)
   182  }
   183  
   184  // ---
   185  
   186  func serializeCompact(sig *ellcurv.Signature) []byte {
   187  	b := make([]byte, 0, 64)
   188  	// TODO: Padding
   189  	rbytes := pad(sig.R.Bytes(), 32)
   190  	sbytes := pad(sig.S.Bytes(), 32)
   191  	b = append(b, rbytes...)
   192  	b = append(b, sbytes...)
   193  	if len(b) != 64 {
   194  		panic("Invalid signature length")
   195  	}
   196  	return b
   197  }
   198  
   199  func deserializeCompact(b []byte) *ellcurv.Signature {
   200  	return &ellcurv.Signature{
   201  		R: new(big.Int).SetBytes(b[:32]),
   202  		S: new(big.Int).SetBytes(b[32:]),
   203  	}
   204  }
   205  
   206  func pad(buf []byte, size int) []byte {
   207  	newbuf := make([]byte, 0, size)
   208  	padLength := size - len(buf)
   209  	for i := 0; i < padLength; i++ {
   210  		newbuf = append(newbuf, 0)
   211  	}
   212  	return append(newbuf, buf...)
   213  }