github.com/MetalBlockchain/metalgo@v1.11.9/utils/crypto/bls/public.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package bls
     5  
     6  import (
     7  	"errors"
     8  
     9  	blst "github.com/supranational/blst/bindings/go"
    10  )
    11  
    12  const PublicKeyLen = blst.BLST_P1_COMPRESS_BYTES
    13  
    14  var (
    15  	ErrNoPublicKeys               = errors.New("no public keys")
    16  	ErrFailedPublicKeyDecompress  = errors.New("couldn't decompress public key")
    17  	errInvalidPublicKey           = errors.New("invalid public key")
    18  	errFailedPublicKeyAggregation = errors.New("couldn't aggregate public keys")
    19  )
    20  
    21  type (
    22  	PublicKey          = blst.P1Affine
    23  	AggregatePublicKey = blst.P1Aggregate
    24  )
    25  
    26  // PublicKeyToCompressedBytes returns the compressed big-endian format of the
    27  // public key.
    28  func PublicKeyToCompressedBytes(pk *PublicKey) []byte {
    29  	return pk.Compress()
    30  }
    31  
    32  // PublicKeyFromCompressedBytes parses the compressed big-endian format of the
    33  // public key into a public key.
    34  func PublicKeyFromCompressedBytes(pkBytes []byte) (*PublicKey, error) {
    35  	pk := new(PublicKey).Uncompress(pkBytes)
    36  	if pk == nil {
    37  		return nil, ErrFailedPublicKeyDecompress
    38  	}
    39  	if !pk.KeyValidate() {
    40  		return nil, errInvalidPublicKey
    41  	}
    42  	return pk, nil
    43  }
    44  
    45  // PublicKeyToUncompressedBytes returns the uncompressed big-endian format of
    46  // the public key.
    47  func PublicKeyToUncompressedBytes(key *PublicKey) []byte {
    48  	return key.Serialize()
    49  }
    50  
    51  // PublicKeyFromValidUncompressedBytes parses the uncompressed big-endian format
    52  // of the public key into a public key. It is assumed that the provided bytes
    53  // are valid.
    54  func PublicKeyFromValidUncompressedBytes(pkBytes []byte) *PublicKey {
    55  	return new(PublicKey).Deserialize(pkBytes)
    56  }
    57  
    58  // AggregatePublicKeys aggregates a non-zero number of public keys into a single
    59  // aggregated public key.
    60  // Invariant: all [pks] have been validated.
    61  func AggregatePublicKeys(pks []*PublicKey) (*PublicKey, error) {
    62  	if len(pks) == 0 {
    63  		return nil, ErrNoPublicKeys
    64  	}
    65  
    66  	var agg AggregatePublicKey
    67  	if !agg.Aggregate(pks, false) {
    68  		return nil, errFailedPublicKeyAggregation
    69  	}
    70  	return agg.ToAffine(), nil
    71  }
    72  
    73  // Verify the [sig] of [msg] against the [pk].
    74  // The [sig] and [pk] may have been an aggregation of other signatures and keys.
    75  // Invariant: [pk] and [sig] have both been validated.
    76  func Verify(pk *PublicKey, sig *Signature, msg []byte) bool {
    77  	return sig.Verify(false, pk, false, msg, ciphersuiteSignature)
    78  }
    79  
    80  // Verify the possession of the secret pre-image of [sk] by verifying a [sig] of
    81  // [msg] against the [pk].
    82  // The [sig] and [pk] may have been an aggregation of other signatures and keys.
    83  // Invariant: [pk] and [sig] have both been validated.
    84  func VerifyProofOfPossession(pk *PublicKey, sig *Signature, msg []byte) bool {
    85  	return sig.Verify(false, pk, false, msg, ciphersuiteProofOfPossession)
    86  }