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 }