pubkey.go raw

   1  // Copyright (c) 2013-2014 The btcsuite developers
   2  // Use of this source code is governed by an ISC
   3  // license that can be found in the LICENSE file.
   4  
   5  package btcec
   6  
   7  import (
   8  	secp "github.com/decred/dcrd/dcrec/secp256k1/v4"
   9  )
  10  
  11  // These constants define the lengths of serialized public keys.
  12  const (
  13  	// PubKeyBytesLenCompressed is the bytes length of a serialized compressed
  14  	// public key.
  15  	PubKeyBytesLenCompressed = 33
  16  )
  17  
  18  const (
  19  	pubkeyCompressed   byte = 0x2 // y_bit + x coord
  20  	pubkeyUncompressed byte = 0x4 // x coord + y coord
  21  	pubkeyHybrid       byte = 0x6 // y_bit + x coord + y coord
  22  )
  23  
  24  // IsCompressedPubKey returns true the passed serialized public key has
  25  // been encoded in compressed format, and false otherwise.
  26  func IsCompressedPubKey(pubKey []byte) bool {
  27  	// The public key is only compressed if it is the correct length and
  28  	// the format (first byte) is one of the compressed pubkey values.
  29  	return len(pubKey) == PubKeyBytesLenCompressed &&
  30  		(pubKey[0]&^byte(0x1) == pubkeyCompressed)
  31  }
  32  
  33  // ParsePubKey parses a public key for a koblitz curve from a bytestring into a
  34  // ecdsa.Publickey, verifying that it is valid. It supports compressed,
  35  // uncompressed and hybrid signature formats.
  36  func ParsePubKey(pubKeyStr []byte) (*PublicKey, error) {
  37  	return secp.ParsePubKey(pubKeyStr)
  38  }
  39  
  40  // PublicKey is an ecdsa.PublicKey with additional functions to
  41  // serialize in uncompressed, compressed, and hybrid formats.
  42  type PublicKey = secp.PublicKey
  43  
  44  // NewPublicKey instantiates a new public key with the given x and y
  45  // coordinates.
  46  //
  47  // It should be noted that, unlike ParsePubKey, since this accepts arbitrary x
  48  // and y coordinates, it allows creation of public keys that are not valid
  49  // points on the secp256k1 curve.  The IsOnCurve method of the returned instance
  50  // can be used to determine validity.
  51  func NewPublicKey(x, y *FieldVal) *PublicKey {
  52  	return secp.NewPublicKey(x, y)
  53  }
  54  
  55  // SerializedKey is a type for representing a public key in its compressed
  56  // serialized form.
  57  //
  58  // NOTE: This type is useful when using public keys as keys in maps.
  59  type SerializedKey [PubKeyBytesLenCompressed]byte
  60  
  61  // ToPubKey returns the public key parsed from the serialized key.
  62  func (s SerializedKey) ToPubKey() (*PublicKey, error) {
  63  	return ParsePubKey(s[:])
  64  }
  65  
  66  // SchnorrSerialized returns the Schnorr serialized, x-only 32-byte
  67  // representation of the serialized key.
  68  func (s SerializedKey) SchnorrSerialized() [32]byte {
  69  	var serializedSchnorr [32]byte
  70  	copy(serializedSchnorr[:], s[1:])
  71  	return serializedSchnorr
  72  }
  73  
  74  // CopyBytes returns a copy of the underlying array as a byte slice.
  75  func (s SerializedKey) CopyBytes() []byte {
  76  	c := make([]byte, PubKeyBytesLenCompressed)
  77  	copy(c, s[:])
  78  
  79  	return c
  80  }
  81  
  82  // ToSerialized serializes a public key into its compressed form.
  83  func ToSerialized(pubKey *PublicKey) SerializedKey {
  84  	var serialized SerializedKey
  85  	copy(serialized[:], pubKey.SerializeCompressed())
  86  
  87  	return serialized
  88  }
  89