github.com/klaytn/klaytn@v1.12.1/crypto/bls/bls.go (about)

     1  // Copyright 2023 The klaytn Authors
     2  // This file is part of the klaytn library.
     3  //
     4  // The klaytn library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The klaytn library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package bls
    18  
    19  import (
    20  	"crypto/ecdsa"
    21  	"encoding/hex"
    22  	"os"
    23  	"strings"
    24  
    25  	"github.com/klaytn/klaytn/crypto"
    26  	"github.com/klaytn/klaytn/crypto/bls/blst"
    27  	"github.com/klaytn/klaytn/crypto/bls/types"
    28  )
    29  
    30  type (
    31  	SecretKey = types.SecretKey
    32  	PublicKey = types.PublicKey
    33  	Signature = types.Signature
    34  )
    35  
    36  // Applications are expected to use below top-level functions,
    37  // Do not directly use 'blst' or other underlying implementations.
    38  //
    39  // Some functions are named after the equivalent functions in prysm Ethereum CL.
    40  // (https://github.com/prysmaticlabs/prysm/blob/v4.0.2/crypto/bls/bls.go)
    41  // Such naming should provide compatiblity with prysm code snippets,
    42  // in case prysm code snippets are integrated to klaytn.
    43  //
    44  // ikm -> SK:  GenerateKey
    45  // ()  -> SK:  RandKey
    46  // ec  -> SK:  DeriveFromECDSA
    47  // path -> SK: LoadKey
    48  // b32 -> SK:  SecretKeyFromBytes
    49  // b48 -> PK:  PublicKeyFromBytes
    50  // b96 -> Sig: SignatureFromBytes
    51  //
    52  // []b48 -> []PK:  MultiplePublicKeysFromBytes
    53  // []b96 -> []Sig: MultipleSignaturesFromBytes
    54  //
    55  // []PK  -> PK:    AggregateMultiplePubkeys
    56  // []Sig -> Sig:   AggregateSignatures
    57  //
    58  // []b48 -> PK:    AggregatePublicKeys
    59  // []b96 -> Sig:   AggregateCompressedSignatures
    60  //
    61  // Sign(SK, msg) -> Sig
    62  // VerifySignature(b96, msg, PK) -> ok, err
    63  // PopProve(SK) -> Proof
    64  // PoPVerify(PK, Proof) -> ok, err
    65  
    66  // GenerateKey generates a BLS secret key from the initial key material (IKM).
    67  // It is deterministic process. Same IKM yields the same secret key.
    68  func GenerateKey(ikm []byte) (SecretKey, error) {
    69  	return blst.GenerateKey(ikm)
    70  }
    71  
    72  // RandKey generates a random BLS secret key.
    73  func RandKey() (SecretKey, error) {
    74  	return blst.RandKey()
    75  }
    76  
    77  // DeriveFromECDSA generates a BLS secret key from the given EC private key.
    78  // It is deterministic process. Same EC private key yields the same secret key.
    79  func DeriveFromECDSA(priv *ecdsa.PrivateKey) (SecretKey, error) {
    80  	return GenerateKey(crypto.FromECDSA(priv))
    81  }
    82  
    83  // LoadKey loads a BLS secret key from the given file.
    84  func LoadKey(path string) (SecretKey, error) {
    85  	b, err := os.ReadFile(path)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	content := string(b)
    91  	content = strings.TrimSpace(content)
    92  	content = strings.TrimPrefix(content, "0x")
    93  	b, err = hex.DecodeString(content)
    94  	if err != nil {
    95  		return nil, err
    96  	}
    97  
    98  	return SecretKeyFromBytes(b)
    99  }
   100  
   101  // SaveKey stores a BLS secret key to the given file.
   102  func SaveKey(path string, sk SecretKey) error {
   103  	b := hex.EncodeToString(sk.Marshal())
   104  	return os.WriteFile(path, []byte(b), 0o600)
   105  }
   106  
   107  // SecretKeyFromBytes unmarshals and validates a BLS secret key from bytes.
   108  func SecretKeyFromBytes(b []byte) (SecretKey, error) {
   109  	return blst.SecretKeyFromBytes(b)
   110  }
   111  
   112  // PublicKeyFromBytes unmarshals and validates a BLS public key from bytes.
   113  func PublicKeyFromBytes(b []byte) (PublicKey, error) {
   114  	return blst.PublicKeyFromBytes(b)
   115  }
   116  
   117  // SignatureFromBytes unmarshals and validates a BLS signature from bytes.
   118  func SignatureFromBytes(b []byte) (Signature, error) {
   119  	return blst.SignatureFromBytes(b)
   120  }
   121  
   122  // MultiplePublicKeysFromBytes unmarshals and validates multiple BLS public keys
   123  // from bytes. Returns an empty slice if an empty slice is given.
   124  func MultiplePublicKeysFromBytes(bs [][]byte) ([]PublicKey, error) {
   125  	return blst.MultiplePublicKeysFromBytes(bs)
   126  }
   127  
   128  // MultipleSignaturesFromBytes unmarshals multiple BLS signatures from bytes.
   129  // Returns an empty slice if an empty slice is given.
   130  func MultipleSignaturesFromBytes(bs [][]byte) ([]Signature, error) {
   131  	return blst.MultipleSignaturesFromBytes(bs)
   132  }
   133  
   134  // AggregateMultiplePubkeys aggregates multiple BLS public keys.
   135  // Assumes that all given public keys are previously validated.
   136  // Returns error if an empty slice is given.
   137  func AggregateMultiplePubkeys(pks []PublicKey) (PublicKey, error) {
   138  	return blst.AggregatePublicKeys(pks)
   139  }
   140  
   141  // AggregateSignatures aggregates multiple BLS signatures.
   142  // Assumes that all given signatures are previously validated.
   143  // Returns error if an empty slice is given.
   144  func AggregateSignatures(sigs []Signature) (Signature, error) {
   145  	return blst.AggregateSignatures(sigs)
   146  }
   147  
   148  // AggregatePublicKeys unmarshals and validates multiple BLS public key from bytes
   149  // and then aggregates them. Returns error if an empty slice is given.
   150  func AggregatePublicKeys(bs [][]byte) (PublicKey, error) {
   151  	return blst.AggregatePublicKeysFromBytes(bs)
   152  }
   153  
   154  // AggregateCompressedSignatures unmarshals and validates multiple BLS signatures from bytes
   155  // and then aggregates them. Returns error if an empty slice is given.
   156  func AggregateCompressedSignatures(bs [][]byte) (Signature, error) {
   157  	return blst.AggregateSignaturesFromBytes(bs)
   158  }
   159  
   160  // Sign calculates a signature.
   161  func Sign(sk SecretKey, msg []byte) Signature {
   162  	return blst.Sign(sk, msg)
   163  }
   164  
   165  // VerifySignature checks a signature. To perform aggregate verify, supply the
   166  // aggregate signature and aggregate public key.
   167  func VerifySignature(sig []byte, msg [32]byte, pk PublicKey) (bool, error) {
   168  	return blst.VerifySignature(sig, msg, pk)
   169  }
   170  
   171  // VerifyMultipleSignatures verifies multiple signatures for distinct messages securely.
   172  func VerifyMultipleSignatures(sigs [][]byte, msgs [][32]byte, pubKeys []PublicKey) (bool, error) {
   173  	return blst.VerifyMultipleSignatures(sigs, msgs, pubKeys)
   174  }
   175  
   176  // PopProve calculates the proof-of-possession for the secret key,
   177  // which is the signature with its public key as message.
   178  func PopProve(sk SecretKey) Signature {
   179  	return blst.PopProve(sk)
   180  }
   181  
   182  // PopVerify verifies the proof-of-possession for the public key.
   183  func PopVerify(pk PublicKey, sig Signature) bool {
   184  	return blst.PopVerify(pk, sig)
   185  }