github.com/onflow/flow-go/crypto@v0.24.8/bls.go (about)

     1  //go:build relic
     2  // +build relic
     3  
     4  package crypto
     5  
     6  // BLS signature scheme implementation using BLS12-381 curve
     7  // ([zcash]https://electriccoin.co/blog/new-snark-curve/)
     8  // Pairing, ellipic curve and modular arithmetic is using Relic library.
     9  // This implementation does not include any security against side-channel attacks.
    10  
    11  // existing features:
    12  //  - the implementation variant is minimal-signature-size signatures:
    13  //    shorter signatures in G1, longer public keys in G2
    14  //  - serialization of points on G1 and G2 is compressed ([zcash]
    15  //     https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-08.html#name-zcash-serialization-format-)
    16  //  - hashing to curve uses the Simplified SWU map-to-curve
    17  //    (https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-14#section-6.6.3)
    18  //  - expanding the message in hash-to-curve uses a cSHAKE-based KMAC128 with a domain separation tag.
    19  //    KMAC128 serves as an expand_message_xof function.
    20  //  - this results in the full ciphersuite BLS_SIG_BLS12381G1_XOF:KMAC128_SSWU_RO_POP_ for signatures
    21  //    and BLS_POP_BLS12381G1_XOF:KMAC128_SSWU_RO_POP_ for proofs of possession.
    22  //  - signature verification checks the membership of signature in G1.
    23  //  - the public key membership check in G2 is implemented separately from the signature verification.
    24  //  - membership check in G1 is implemented using fast Bowe's check (to be updated to Scott's check).
    25  //  - membership check in G2 is using a simple scalar multiplication with the group order (to be updated to Scott's check).
    26  //  - multi-signature tools are defined in bls_multisg.go
    27  //  - SPoCK scheme based on BLS: verifies two signatures have been generated from the same message,
    28  //    that is unknown to the verifier.
    29  
    30  // future features:
    31  //  - membership checks G2 using Bowe's method (https://eprint.iacr.org/2019/814.pdf)
    32  //  - implement a G1/G2 swap (signatures on G2 and public keys on G1)
    33  
    34  // #cgo CFLAGS: -g -Wall -std=c99
    35  // #cgo LDFLAGS: -L${SRCDIR}/relic/build/lib -l relic_s
    36  // #include "bls_include.h"
    37  import "C"
    38  
    39  import (
    40  	"bytes"
    41  	"crypto/sha256"
    42  	"errors"
    43  	"fmt"
    44  
    45  	"golang.org/x/crypto/hkdf"
    46  
    47  	"github.com/onflow/flow-go/crypto/hash"
    48  )
    49  
    50  const (
    51  	// BLS12-381
    52  	// p size in bytes, where G1 is defined over the field Zp
    53  	fieldSize = 48
    54  	//
    55  	// 1 for compressed, 0 for uncompressed - values should not be changed
    56  	uncompressed = 0 //nolint
    57  	compressed   = 1
    58  	// Points compression when serialized
    59  	serializationG1 = compressed
    60  	serializationG2 = compressed
    61  	//
    62  	// SignatureLenBLSBLS12381 is the size of G1 elements
    63  	SignatureLenBLSBLS12381 = fieldSize * (2 - serializationG1) // the length is divided by 2 if compression is on
    64  	PrKeyLenBLSBLS12381     = 32
    65  	// PubKeyLenBLSBLS12381 is the size of G2 elements
    66  	PubKeyLenBLSBLS12381 = 2 * fieldSize * (2 - serializationG2) // the length is divided by 2 if compression is on
    67  
    68  	// Hash to curve params
    69  	// expandMsgOutput is the output length of the expand_message step as required by the hash_to_curve algorithm
    70  	expandMsgOutput = 2 * (fieldSize + (securityBits / 8))
    71  	// hash to curve suite ID of the form : CurveID_ || HashID_ || MapID_ || encodingVariant_
    72  	h2cSuiteID = "BLS12381G1_XOF:KMAC128_SSWU_RO_"
    73  	// scheme implemented as a countermasure for rogue attacks of the form : SchemeTag_
    74  	schemeTag = "POP_"
    75  	// Cipher suite used for BLS signatures of the form : BLS_SIG_ || h2cSuiteID || SchemeTag_
    76  	blsSigCipherSuite = "BLS_SIG_" + h2cSuiteID + schemeTag
    77  	// Cipher suite used for BLS PoP of the form : BLS_POP_ || h2cSuiteID || SchemeTag_
    78  	// The PoP cipher suite is guaranteed to be different than all signature ciphersuites
    79  	blsPOPCipherSuite = "BLS_POP_" + h2cSuiteID + schemeTag
    80  )
    81  
    82  // blsBLS12381Algo, embeds SignAlgo
    83  type blsBLS12381Algo struct {
    84  	// points to Relic context of BLS12-381 with all the parameters
    85  	context ctx
    86  	// the signing algo and parameters
    87  	algo SigningAlgorithm
    88  }
    89  
    90  // BLS context on the BLS 12-381 curve
    91  var blsInstance *blsBLS12381Algo
    92  
    93  // NewExpandMsgXOFKMAC128 returns a new expand_message_xof instance for
    94  // the hash-to-curve function, hashing data to G1 on BLS12 381.
    95  // This instance must only be used to generate signatures (and not PoP),
    96  // because the internal ciphersuite is customized for signatures. It
    97  // is guaranteed to be different than the expand_message_xof instance used
    98  // to generate proofs of possession.
    99  //
   100  // KMAC128 is used as the underligned extendable-output function (xof)
   101  // as required by https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-14#section-5.4.4.
   102  //
   103  // `domainTag` is a domain separation tag that defines the protocol and its subdomain. Such tag should be of the
   104  // format: <protocol>-V<xx>-CS<yy>-with- where <protocol> is the name of the protocol, <xx> the protocol
   105  // version number and <yy> the index of the ciphersuite in the protocol.
   106  // The function suffixes the given `domainTag` by the BLS ciphersuite supported by the library.
   107  //
   108  // The returned instance is a `Hasher` and can be used to generate BLS signatures
   109  // with the `Sign` method.
   110  func NewExpandMsgXOFKMAC128(domainTag string) hash.Hasher {
   111  	// application tag is guaranteed to be different than the tag used
   112  	// to generate proofs of possession
   113  	// postfix the domain tag with the BLS ciphersuite
   114  	key := domainTag + blsSigCipherSuite
   115  	return internalExpandMsgXOFKMAC128(key)
   116  }
   117  
   118  // returns an expand_message_xof instance for
   119  // the hash-to-curve function, hashing data to G1 on BLS12 381.
   120  // The key is used as a customizer rather than a MAC key.
   121  func internalExpandMsgXOFKMAC128(key string) hash.Hasher {
   122  	// blsKMACFunction is the customizer used for KMAC in BLS
   123  	const blsKMACFunction = "H2C"
   124  	// the error is ignored as the parameter lengths are chosen to be in the correct range for kmac
   125  	// (tested by TestBLSBLS12381Hasher)
   126  	kmac, _ := hash.NewKMAC_128([]byte(key), []byte(blsKMACFunction), expandMsgOutput)
   127  	return kmac
   128  }
   129  
   130  // checkBLSHasher asserts that the given `hasher` is not nil and
   131  // has an output size of `expandMsgOutput`. Otherwise an error is returned:
   132  //   - nilHasherError if the hasher is nil
   133  //   - invalidHasherSizeError if the hasher's output size is not `expandMsgOutput` (128 bytes)
   134  func checkBLSHasher(hasher hash.Hasher) error {
   135  	if hasher == nil {
   136  		return nilHasherError
   137  	}
   138  	if hasher.Size() != expandMsgOutput {
   139  		return invalidHasherSizeErrorf("hasher's size needs to be %d, got %d", expandMsgOutput, hasher.Size())
   140  	}
   141  	return nil
   142  }
   143  
   144  // Sign signs an array of bytes using the private key
   145  //
   146  // Signature is compressed [zcash]
   147  // https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-08.html#name-zcash-serialization-format-
   148  // The private key is read only.
   149  // If the hasher used is KMAC128, the hasher is read only.
   150  // It is recommended to use Sign with the hasher from NewExpandMsgXOFKMAC128. If not, the hasher used
   151  // must expand the message to 1024 bits. It is also recommended to use a hasher
   152  // with a domain separation tag.
   153  //
   154  // The function returns:
   155  //   - (false, nilHasherError) if a hasher is nil
   156  //   - (false, invalidHasherSizeError) if a hasher's output size is not 128 bytes
   157  //   - (signature, nil) otherwise
   158  func (sk *prKeyBLSBLS12381) Sign(data []byte, kmac hash.Hasher) (Signature, error) {
   159  	// sanity check of input hasher
   160  	err := checkBLSHasher(kmac)
   161  	if err != nil {
   162  		return nil, err
   163  	}
   164  
   165  	// hash the input to 128 bytes
   166  	h := kmac.ComputeHash(data)
   167  
   168  	// set BLS context
   169  	blsInstance.reInit()
   170  
   171  	s := make([]byte, SignatureLenBLSBLS12381)
   172  	C.bls_sign((*C.uchar)(&s[0]),
   173  		(*C.bn_st)(&sk.scalar),
   174  		(*C.uchar)(&h[0]),
   175  		(C.int)(len(h)))
   176  	return s, nil
   177  }
   178  
   179  // Verify verifies a signature of a byte array using the public key and the input hasher.
   180  //
   181  // If the input signature slice has an invalid length or fails to deserialize into a curve
   182  // subgroup point, the function returns false without an error.
   183  //
   184  // The function assumes the public key is in the valid G2 subgroup because
   185  // all the package functions generating a BLS `PublicKey` include a G2-membership check.
   186  // The public keys are not guaranteed to be non-identity, and therefore the function
   187  // includes an identity comparison. Verifications against an identity public key
   188  // are invalid to avoid equivocation issues.
   189  // The signature membership check in G1 is included in the verification.
   190  //
   191  // If the hasher used is ExpandMsgXOFKMAC128, the hasher is read only.
   192  //
   193  // The function returns:
   194  //   - (false, nilHasherError) if a hasher is nil
   195  //   - (false, invalidHasherSizeError) if a hasher's output size is not 128 bytes
   196  //   - (false, error) if an unexpected error occurs
   197  //   - (validity, nil) otherwise
   198  func (pk *pubKeyBLSBLS12381) Verify(s Signature, data []byte, kmac hash.Hasher) (bool, error) {
   199  	// check of input hasher
   200  	err := checkBLSHasher(kmac)
   201  	if err != nil {
   202  		return false, err
   203  	}
   204  
   205  	// intialize BLS context
   206  	blsInstance.reInit()
   207  
   208  	if len(s) != signatureLengthBLSBLS12381 {
   209  		return false, nil
   210  	}
   211  
   212  	// hash the input to 128 bytes
   213  	h := kmac.ComputeHash(data)
   214  
   215  	// check for identity public key
   216  	if pk.isIdentity {
   217  		return false, nil
   218  	}
   219  
   220  	verif := C.bls_verify((*C.ep2_st)(&pk.point),
   221  		(*C.uchar)(&s[0]),
   222  		(*C.uchar)(&h[0]),
   223  		(C.int)(len(h)))
   224  
   225  	switch verif {
   226  	case invalid:
   227  		return false, nil
   228  	case valid:
   229  		return true, nil
   230  	default:
   231  		return false, fmt.Errorf("signature verification failed")
   232  	}
   233  }
   234  
   235  // 0xC0 is the header of the point at infinity serialization (either in G1 or G2)
   236  const infinityPointHeader = 0xC0
   237  
   238  var identityBLSSignature = append([]byte{infinityPointHeader}, make([]byte, signatureLengthBLSBLS12381-1)...)
   239  
   240  // IsBLSSignatureIdentity checks whether the input signature is
   241  // the identity signature (point at infinity in G1).
   242  //
   243  // An identity signature is always an invalid signature even when
   244  // verified against the identity public key.
   245  // This identity check is useful when an aggregated signature is
   246  // suspected to be equal to identity, which avoids failing the aggregated
   247  // signature verification.
   248  func IsBLSSignatureIdentity(s Signature) bool {
   249  	return bytes.Equal(s, identityBLSSignature)
   250  }
   251  
   252  // generatePrivateKey deterministically generates a private key for BLS on BLS12-381 curve.
   253  // The minimum size of the input seed is 32 bytes.
   254  //
   255  // It is recommended to use a secure crypto RNG to generate the seed.
   256  // Otherwise, the seed must have enough entropy.
   257  //
   258  // The generated private key (resp. its corresponding public key) is guaranteed
   259  // to not be equal to the identity element of Z_r (resp. G2).
   260  func (a *blsBLS12381Algo) generatePrivateKey(ikm []byte) (PrivateKey, error) {
   261  	if len(ikm) < KeyGenSeedMinLen || len(ikm) > KeyGenSeedMaxLen {
   262  		return nil, invalidInputsErrorf(
   263  			"seed length should be at least %d bytes and at most %d bytes",
   264  			KeyGenSeedMinLen, KeyGenSeedMaxLen)
   265  	}
   266  
   267  	// HKDF parameters
   268  
   269  	// use SHA2-256 as the building block H in HKDF
   270  	hashFunction := sha256.New
   271  	// salt = H(UTF-8("BLS-SIG-KEYGEN-SALT-")) as per draft-irtf-cfrg-bls-signature-05 section 2.3.
   272  	saltString := "BLS-SIG-KEYGEN-SALT-"
   273  	hasher := hashFunction()
   274  	hasher.Write([]byte(saltString))
   275  	salt := make([]byte, hasher.Size())
   276  	hasher.Sum(salt[:0])
   277  
   278  	// L is the OKM length
   279  	// L = ceil((3 * ceil(log2(r))) / 16) which makes L (security_bits/8)-larger than r size
   280  	okmLength := (3 * PrKeyLenBLSBLS12381) / 2
   281  
   282  	// HKDF secret = IKM || I2OSP(0, 1)
   283  	secret := make([]byte, len(ikm)+1)
   284  	copy(secret, ikm)
   285  	defer overwrite(secret) // overwrite secret
   286  	// HKDF info = key_info || I2OSP(L, 2)
   287  	keyInfo := "" // use empty key diversifier. TODO: update header to accept input identifier
   288  	info := append([]byte(keyInfo), byte(okmLength>>8), byte(okmLength))
   289  
   290  	sk := newPrKeyBLSBLS12381(nil)
   291  	for {
   292  		// instantiate HKDF and extract L bytes
   293  		reader := hkdf.New(hashFunction, secret, salt, info)
   294  		okm := make([]byte, okmLength)
   295  		n, err := reader.Read(okm)
   296  		if err != nil || n != okmLength {
   297  			return nil, fmt.Errorf("key generation failed because of the HKDF reader, %d bytes were read: %w",
   298  				n, err)
   299  		}
   300  		defer overwrite(okm) // overwrite okm
   301  
   302  		// map the bytes to a private key : SK = OS2IP(OKM) mod r
   303  		isZero := mapToZr(&sk.scalar, okm)
   304  		if !isZero {
   305  			return sk, nil
   306  		}
   307  
   308  		// update salt = H(salt)
   309  		hasher.Reset()
   310  		hasher.Write(salt)
   311  		salt = hasher.Sum(salt[:0])
   312  	}
   313  }
   314  
   315  const invalidBLSSignatureHeader = byte(0xE0)
   316  
   317  // BLSInvalidSignature returns an invalid signature that fails when verified
   318  // with any message and public key.
   319  //
   320  // The signature bytes represent an invalid serialization of a point which
   321  // makes the verification fail early. The verification would return (false, nil).
   322  func BLSInvalidSignature() Signature {
   323  	signature := make([]byte, SignatureLenBLSBLS12381)
   324  	signature[0] = invalidBLSSignatureHeader // invalid header as per C.ep_read_bin_compact
   325  	return signature
   326  }
   327  
   328  // decodePrivateKey decodes a slice of bytes into a private key.
   329  // It checks the scalar is non-zero and is less than the group order.
   330  func (a *blsBLS12381Algo) decodePrivateKey(privateKeyBytes []byte) (PrivateKey, error) {
   331  	if len(privateKeyBytes) != prKeyLengthBLSBLS12381 {
   332  		return nil, invalidInputsErrorf("input length must be %d, got %d",
   333  			prKeyLengthBLSBLS12381, len(privateKeyBytes))
   334  	}
   335  	sk := newPrKeyBLSBLS12381(nil)
   336  
   337  	readScalar(&sk.scalar, privateKeyBytes)
   338  	if C.check_membership_Zr_star((*C.bn_st)(&sk.scalar)) == valid {
   339  		return sk, nil
   340  	}
   341  
   342  	return nil, invalidInputsErrorf("the private key is not a valid BLS12-381 curve key")
   343  }
   344  
   345  // decodePublicKey decodes a slice of bytes into a public key.
   346  // This function includes a membership check in G2.
   347  //
   348  // Note the function does not reject the infinity point (identity element of G2).
   349  // However, the comparison to identity is cached in the `PublicKey` structure for
   350  // a faster check during signature verifications. Any verification against an identity
   351  // public key outputs `false`.
   352  func (a *blsBLS12381Algo) decodePublicKey(publicKeyBytes []byte) (PublicKey, error) {
   353  	if len(publicKeyBytes) != pubKeyLengthBLSBLS12381 {
   354  		return nil, invalidInputsErrorf("input length must be %d, got %d",
   355  			pubKeyLengthBLSBLS12381, len(publicKeyBytes))
   356  	}
   357  	var pk pubKeyBLSBLS12381
   358  	err := readPointG2(&pk.point, publicKeyBytes)
   359  	if err != nil {
   360  		return nil, fmt.Errorf("decode public key failed %w", err)
   361  	}
   362  
   363  	// membership check in G2
   364  	if C.check_membership_G2((*C.ep2_st)(&pk.point)) != valid {
   365  		return nil, invalidInputsErrorf("input key is infinity or does not encode a BLS12-381 point in the valid group")
   366  	}
   367  
   368  	// check point is non-infinity and cache it
   369  	pk.isIdentity = (&pk.point).isInfinity()
   370  
   371  	return &pk, nil
   372  }
   373  
   374  // decodePublicKeyCompressed decodes a slice of bytes into a public key.
   375  // since we use the compressed representation by default, this checks the default and delegates to decodePublicKeyCompressed
   376  func (a *blsBLS12381Algo) decodePublicKeyCompressed(publicKeyBytes []byte) (PublicKey, error) {
   377  	if serializationG2 != compressed {
   378  		panic("library is not configured to use compressed public key serialization")
   379  	}
   380  	return a.decodePublicKey(publicKeyBytes)
   381  }
   382  
   383  // prKeyBLSBLS12381 is the private key of BLS using BLS12_381, it implements PrivateKey
   384  type prKeyBLSBLS12381 struct {
   385  	// public key
   386  	pk *pubKeyBLSBLS12381
   387  	// private key data
   388  	scalar scalar
   389  }
   390  
   391  // newPrKeyBLSBLS12381 creates a new BLS private key with the given scalar.
   392  // If no scalar is provided, the function allocates an
   393  // empty scalar.
   394  func newPrKeyBLSBLS12381(x *scalar) *prKeyBLSBLS12381 {
   395  	var sk prKeyBLSBLS12381
   396  	if x == nil {
   397  		// initialize the scalar
   398  		C.bn_new_wrapper((*C.bn_st)(&sk.scalar))
   399  	} else {
   400  		// set the scalar
   401  		sk.scalar = *x
   402  	}
   403  	// the embedded public key is only computed when needed
   404  	return &sk
   405  }
   406  
   407  // Algorithm returns the Signing Algorithm
   408  func (sk *prKeyBLSBLS12381) Algorithm() SigningAlgorithm {
   409  	return BLSBLS12381
   410  }
   411  
   412  // Size returns the private key length in bytes
   413  func (sk *prKeyBLSBLS12381) Size() int {
   414  	return PrKeyLenBLSBLS12381
   415  }
   416  
   417  // computePublicKey generates the public key corresponding to
   418  // the input private key. The function makes sure the public key
   419  // is valid in G2.
   420  func (sk *prKeyBLSBLS12381) computePublicKey() {
   421  	var newPk pubKeyBLSBLS12381
   422  	// compute public key pk = g2^sk
   423  	generatorScalarMultG2(&newPk.point, &sk.scalar)
   424  
   425  	// cache the identity comparison
   426  	newPk.isIdentity = (&sk.scalar).isZero()
   427  
   428  	sk.pk = &newPk
   429  }
   430  
   431  // PublicKey returns the public key corresponding to the private key
   432  func (sk *prKeyBLSBLS12381) PublicKey() PublicKey {
   433  	if sk.pk != nil {
   434  		return sk.pk
   435  	}
   436  	sk.computePublicKey()
   437  	return sk.pk
   438  }
   439  
   440  // Encode returns a byte encoding of the private key.
   441  // The encoding is a raw encoding in big endian padded to the group order
   442  func (a *prKeyBLSBLS12381) Encode() []byte {
   443  	dest := make([]byte, prKeyLengthBLSBLS12381)
   444  	writeScalar(dest, &a.scalar)
   445  	return dest
   446  }
   447  
   448  // Equals checks is two public keys are equal.
   449  func (sk *prKeyBLSBLS12381) Equals(other PrivateKey) bool {
   450  	otherBLS, ok := other.(*prKeyBLSBLS12381)
   451  	if !ok {
   452  		return false
   453  	}
   454  	return sk.scalar.equals(&otherBLS.scalar)
   455  }
   456  
   457  // String returns the hex string representation of the key.
   458  func (sk *prKeyBLSBLS12381) String() string {
   459  	return fmt.Sprintf("%#x", sk.Encode())
   460  }
   461  
   462  // pubKeyBLSBLS12381 is the public key of BLS using BLS12_381,
   463  // it implements PublicKey.
   464  type pubKeyBLSBLS12381 struct {
   465  	// The package guarantees an instance is only created with a point
   466  	// on the correct G2 subgroup. No membership check is needed when the
   467  	// instance is used in any BLS function.
   468  	// However, an instance can be created with an infinity point. Although
   469  	// infinity is a valid G2 point, some BLS functions fail (return false)
   470  	// when used with an infinity point. The package caches the infinity
   471  	// comparison in pubKeyBLSBLS12381 for a faster check. The package makes
   472  	// sure the comparison is performed after an instance is created.
   473  	//
   474  	// public key G2 point
   475  	point pointG2
   476  	// G2 identity check cache
   477  	isIdentity bool
   478  }
   479  
   480  // newPubKeyBLSBLS12381 creates a new BLS public key with the given point.
   481  // If no scalar is provided, the function allocates an
   482  // empty scalar.
   483  func newPubKeyBLSBLS12381(p *pointG2) *pubKeyBLSBLS12381 {
   484  	if p != nil {
   485  		key := &pubKeyBLSBLS12381{
   486  			point: *p,
   487  		}
   488  		// cache the identity comparison for a faster check
   489  		// during signature verifications
   490  		key.isIdentity = p.isInfinity()
   491  		return key
   492  	}
   493  	return &pubKeyBLSBLS12381{}
   494  }
   495  
   496  // Algorithm returns the Signing Algorithm
   497  func (pk *pubKeyBLSBLS12381) Algorithm() SigningAlgorithm {
   498  	return BLSBLS12381
   499  }
   500  
   501  // Size returns the public key lengh in bytes
   502  func (pk *pubKeyBLSBLS12381) Size() int {
   503  	return PubKeyLenBLSBLS12381
   504  }
   505  
   506  // EncodeCompressed returns a byte encoding of the public key.
   507  // The encoding is a compressed encoding of the point
   508  // [zcash] https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-08.html#name-zcash-serialization-format-
   509  func (a *pubKeyBLSBLS12381) EncodeCompressed() []byte {
   510  	if serializationG2 != compressed {
   511  		panic("library is not configured to use compressed public key serialization")
   512  	}
   513  	return a.Encode()
   514  }
   515  
   516  // Encode returns a byte encoding of the public key.
   517  // Since we use a compressed encoding by default, this delegates to EncodeCompressed
   518  func (a *pubKeyBLSBLS12381) Encode() []byte {
   519  	dest := make([]byte, pubKeyLengthBLSBLS12381)
   520  	writePointG2(dest, &a.point)
   521  	return dest
   522  }
   523  
   524  // Equals checks is two public keys are equal
   525  func (pk *pubKeyBLSBLS12381) Equals(other PublicKey) bool {
   526  	otherBLS, ok := other.(*pubKeyBLSBLS12381)
   527  	if !ok {
   528  		return false
   529  	}
   530  	return pk.point.equals(&otherBLS.point)
   531  }
   532  
   533  // String returns the hex string representation of the key.
   534  func (pk *pubKeyBLSBLS12381) String() string {
   535  	return fmt.Sprintf("%#x", pk.Encode())
   536  }
   537  
   538  // Get Macro definitions from the C layer as Cgo does not export macros
   539  var signatureLengthBLSBLS12381 = int(C.get_signature_len())
   540  var pubKeyLengthBLSBLS12381 = int(C.get_pk_len())
   541  var prKeyLengthBLSBLS12381 = int(C.get_sk_len())
   542  
   543  // init sets the context of BLS12-381 curve
   544  func (a *blsBLS12381Algo) init() error {
   545  	// initializes relic context and sets the B12_381 parameters
   546  	if err := a.context.initContext(); err != nil {
   547  		return err
   548  	}
   549  
   550  	// compare the Go and C layer constants as a sanity check
   551  	if signatureLengthBLSBLS12381 != SignatureLenBLSBLS12381 ||
   552  		pubKeyLengthBLSBLS12381 != PubKeyLenBLSBLS12381 ||
   553  		prKeyLengthBLSBLS12381 != PrKeyLenBLSBLS12381 {
   554  		return errors.New("BLS-12381 length settings in Go and C are not consistent, check hardcoded lengths and compressions")
   555  	}
   556  	return nil
   557  }
   558  
   559  // set the context of BLS 12-381 curve in the lower C and Relic layers assuming the context
   560  // was previously initialized with a call to init().
   561  //
   562  // If the implementation evolves to support multiple contexts,
   563  // reinit should be called at every blsBLS12381Algo operation.
   564  func (a *blsBLS12381Algo) reInit() {
   565  	a.context.setContext()
   566  }
   567  
   568  // This is only a TEST/DEBUG/BENCH function.
   569  // It returns the hash to G1 point from a slice of 128 bytes
   570  func mapToG1(data []byte) *pointG1 {
   571  	l := len(data)
   572  	var h pointG1
   573  	C.map_to_G1((*C.ep_st)(&h), (*C.uchar)(&data[0]), (C.int)(l))
   574  	return &h
   575  }
   576  
   577  // This is only a TEST function.
   578  // signWithXMDSHA256 signs a message using XMD_SHA256 as a hash to field.
   579  //
   580  // The function is in this file because cgo can't be used in go test files.
   581  // TODO: implement a hasher for XMD SHA256 and use the `Sign` function.
   582  func (sk *prKeyBLSBLS12381) signWithXMDSHA256(data []byte) Signature {
   583  
   584  	dst := []byte("BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_")
   585  	hash := make([]byte, expandMsgOutput)
   586  	// XMD using SHA256
   587  	C.xmd_sha256((*C.uchar)(&hash[0]),
   588  		(C.int)(expandMsgOutput),
   589  		(*C.uchar)(&data[0]), (C.int)(len(data)),
   590  		(*C.uchar)(&dst[0]), (C.int)(len(dst)))
   591  
   592  	// sign the hash
   593  	s := make([]byte, SignatureLenBLSBLS12381)
   594  	C.bls_sign((*C.uchar)(&s[0]),
   595  		(*C.bn_st)(&sk.scalar),
   596  		(*C.uchar)(&hash[0]),
   597  		(C.int)(len(hash)))
   598  	return s
   599  }