The blst package provides a Go interface to the blst BLS12-381 signature library.
The build process consists of two steps, code generation followed by compilation.
./generate.py # Optional - only required if making code changes
go build
go test
The generate.py script is used to generate both min-pk and min-sig variants of the binding from a common code base. It consumes the *.tgo files along with blst_minpk_test.go and produces blst.go and blst_minsig_test.go. The .tgo files can treated as if they were .go files, including the use of gofmt and goimports. The generate script will filter out extra imports while processing and automatically run goimports on the final blst.go file.
After running generate.py, go build and go test can be run as usual. Cgo will compile cgo_server.c, which includes the required C implementation files, and cgo_assembly.S, which includes appropriate pre-generated assembly code for the platform.
If the test or target application crashes with an "illegal instruction" exception [after copying to an older system], rebuild with CGO_CFLAGS environment variable set to -O2 -D__BLST_PORTABLE__. Don't forget -O2!
On Windows the C compiler invoked by cgo, one denoted in go env CC output, has to target MinGW. Verify with <go-env-CC-output> -dM -E -x c nul: | findstr "MINGW64".
If you're cross-compiling, you have to set CC environment variable to the target C cross-compiler and CGO_ENABLED to 1. For example, to compile the test program for ARM:
env GOARCH=arm CC=arm-linux-gnueabi-gcc CGO_ENABLED=1 go test -c
There are two primary modes of operation that can be chosen based on type definitions in the application.
For minimal-pubkey-size operations the application would define core types as:
type PublicKey = blst.P1Affine
type Signature = blst.P2Affine
type AggregateSignature = blst.P2Aggregate
type AggregatePublicKey = blst.P1Aggregate
For minimal-signature-size operations:
type PublicKey = blst.P2Affine
type Signature = blst.P1Affine
type AggregateSignature = blst.P1Aggregate
type AggregatePublicKey = blst.P2Aggregate
A complete example for generating a key, signing a message, and verifying the message:
package main
import (
"crypto/rand"
"fmt"
blst "github.com/supranational/blst/bindings/go"
)
type PublicKey = blst.P1Affine
type Signature = blst.P2Affine
type AggregateSignature = blst.P2Aggregate
type AggregatePublicKey = blst.P1Aggregate
func main() {
var ikm [32]byte
_, _ = rand.Read(ikm[:])
sk := blst.KeyGen(ikm[:])
pk := new(PublicKey).From(sk)
var dst = []byte("BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_")
msg := []byte("hello foo")
sig := new(Signature).Sign(sk, msg, dst)
if !sig.Verify(true, pk, true, msg, dst) {
fmt.Println("ERROR: Invalid!")
} else {
fmt.Println("Valid!")
}
}
See the tests for further examples of usage.
KeyGen(ikm []byte, optional ...[]byte) *SecretKey- Derive the secret key scalar from secret input key material, optionally application-specificSerialize() []byte- Serialize the secret key to bytesDeserialize(data []byte) *SecretKey- Deserialize secret key from bytesZeroize()- Securely zero out the secret key
From(sk *SecretKey) *PublicKey- Derive public key from secret keyCompress() []byte- Serialize public key to compressed formatUncompress(data []byte) *PublicKey- Decompress public key from bytesSerialize() []byte- Serialize public key to uncompressed formatDeserialize(data []byte) *PublicKey- Deserialize public key from bytes
Sign(sk *SecretKey, msg []byte, dst []byte, ...interface{}) *Signature- Sign a messageCompress() []byte- Serialize signature to compressed formatUncompress(data []byte) *Signature- Decompress signature from bytesBatchUncompress(compressedSigs [][]byte) []*Signature- Efficiently uncompress multiple signaturesSerialize() []byte- Serialize signature to uncompressed formatDeserialize(data []byte) *Signature- Deserialize signature from bytesVerify(sigCheck bool, pk *PublicKey, pkCheck bool, msg []byte, dst []byte, ...interface{}) bool- Verify a signatureVerifyCompressed(sig []byte, sigCheck bool, pk []byte, msgCheck bool, msg []byte, dst []byte, ...interface{}) bool- Verify a serialized signature in compressed formatAggregateVerify(sigCheck bool, pks []*PublicKey, msgCheck bool, msgs [][]byte, dst []byte) bool- Verify an aggregated signature for multiple messagesAggregateVerifyCompressed(sig []byte, sigCheck bool, pks [][]byte, msgCheck bool, msgs [][]byte, dst []byte) bool- Verify an aggregated serialized signature in compressed formatFastAggregateVerify(sigCheck bool, pks []*PublicKey, msg []byte, dst []byte) bool- Fast verify for same messageMultipleAggregateVerify(sigs []*Signature, sigCheck bool, pks []*PublicKey, msgCheck bool, msgs [][]byte, dst []byte, randFn func(*Scalar), randBits int) bool- Verify multiple signatures
AggregatePublicKey.Aggregate(pks []*PublicKey, check bool)- Aggregate multiple public keysAggregateSignature.Aggregate(sigs []*Signature, check bool)- Aggregate multiple signaturesAggregateSignature.AggregateCompressed(compressedSigs [][]byte, check bool)- Aggregate multiple serialized signatures in compressed formatAggregatePublicKey.ToAffine() *PublicKey- Convert aggregate to affine formAggregateSignature.ToAffine() *Signature- Convert aggregate to affine form
HashToG1(msg []byte, dst []byte, optional... []byte) *P1- Hash message [with optional augmentation] to G1 pointHashToG2(msg []byte, dst []byte, optional... []byte) *P2- Hash message [with optional augmentation] to G2 pointP1Generator() *P1- Get G1 generator pointP2Generator() *P2- Get G2 generator pointUniq(msgs [][]byte)- Check messages for uniquenessSetMaxProcs(procs int)- Set maximum number of threads for parallel operations