github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/crypto/signature_cgo.go (about)

     1  // This file is part of the go-sberex library. The go-sberex library is 
     2  // free software: you can redistribute it and/or modify it under the terms 
     3  // of the GNU Lesser General Public License as published by the Free 
     4  // Software Foundation, either version 3 of the License, or (at your option)
     5  // any later version.
     6  //
     7  // The go-sberex library is distributed in the hope that it will be useful, 
     8  // but WITHOUT ANY WARRANTY; without even the implied warranty of
     9  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
    10  // General Public License <http://www.gnu.org/licenses/> for more details.
    11  
    12  // +build !nacl,!js,!nocgo
    13  
    14  package crypto
    15  
    16  import (
    17  	"crypto/ecdsa"
    18  	"crypto/elliptic"
    19  	"fmt"
    20  
    21  	"github.com/Sberex/go-sberex/common/math"
    22  	"github.com/Sberex/go-sberex/crypto/secp256k1"
    23  )
    24  
    25  // Ecrecover returns the uncompressed public key that created the given signature.
    26  func Ecrecover(hash, sig []byte) ([]byte, error) {
    27  	return secp256k1.RecoverPubkey(hash, sig)
    28  }
    29  
    30  // SigToPub returns the public key that created the given signature.
    31  func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
    32  	s, err := Ecrecover(hash, sig)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  
    37  	x, y := elliptic.Unmarshal(S256(), s)
    38  	return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y}, nil
    39  }
    40  
    41  // Sign calculates an ECDSA signature.
    42  //
    43  // This function is susceptible to chosen plaintext attacks that can leak
    44  // information about the private key that is used for signing. Callers must
    45  // be aware that the given hash cannot be chosen by an adversery. Common
    46  // solution is to hash any input before calculating the signature.
    47  //
    48  // The produced signature is in the [R || S || V] format where V is 0 or 1.
    49  func Sign(hash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) {
    50  	if len(hash) != 32 {
    51  		return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash))
    52  	}
    53  	seckey := math.PaddedBigBytes(prv.D, prv.Params().BitSize/8)
    54  	defer zeroBytes(seckey)
    55  	return secp256k1.Sign(hash, seckey)
    56  }
    57  
    58  // VerifySignature checks that the given public key created signature over hash.
    59  // The public key should be in compressed (33 bytes) or uncompressed (65 bytes) format.
    60  // The signature should have the 64 byte [R || S] format.
    61  func VerifySignature(pubkey, hash, signature []byte) bool {
    62  	return secp256k1.VerifySignature(pubkey, hash, signature)
    63  }
    64  
    65  // DecompressPubkey parses a public key in the 33-byte compressed format.
    66  func DecompressPubkey(pubkey []byte) (*ecdsa.PublicKey, error) {
    67  	x, y := secp256k1.DecompressPubkey(pubkey)
    68  	if x == nil {
    69  		return nil, fmt.Errorf("invalid public key")
    70  	}
    71  	return &ecdsa.PublicKey{X: x, Y: y, Curve: S256()}, nil
    72  }
    73  
    74  // CompressPubkey encodes a public key to the 33-byte compressed format.
    75  func CompressPubkey(pubkey *ecdsa.PublicKey) []byte {
    76  	return secp256k1.CompressPubkey(pubkey.X, pubkey.Y)
    77  }
    78  
    79  // S256 returns an instance of the secp256k1 curve.
    80  func S256() elliptic.Curve {
    81  	return secp256k1.S256()
    82  }