86 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package bls
 | |
| 
 | |
| import (
 | |
| 	"crypto/rand"
 | |
| 	"fmt"
 | |
| 
 | |
| 	ffi "github.com/filecoin-project/filecoin-ffi"
 | |
| 	"github.com/filecoin-project/go-address"
 | |
| 	"github.com/filecoin-project/go-state-types/crypto"
 | |
| 
 | |
| 	"github.com/filecoin-project/lotus/lib/sigs"
 | |
| )
 | |
| 
 | |
| const DST = string("BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_")
 | |
| 
 | |
| type SecretKey = ffi.PrivateKey
 | |
| type PublicKey = ffi.PublicKey
 | |
| type Signature = ffi.Signature
 | |
| type AggregateSignature = ffi.Signature
 | |
| 
 | |
| type blsSigner struct{}
 | |
| 
 | |
| func (blsSigner) GenPrivate() ([]byte, error) {
 | |
| 	// Generate 32 bytes of randomness
 | |
| 	var ikm [32]byte
 | |
| 	_, err := rand.Read(ikm[:])
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("bls signature error generating random data")
 | |
| 	}
 | |
| 	// Note private keys seem to be serialized little-endian!
 | |
| 	sk := ffi.PrivateKeyGenerateWithSeed(ikm)
 | |
| 	return sk[:], nil
 | |
| }
 | |
| 
 | |
| func (blsSigner) ToPublic(priv []byte) ([]byte, error) {
 | |
| 	if priv == nil || len(priv) != ffi.PrivateKeyBytes {
 | |
| 		return nil, fmt.Errorf("bls signature invalid private key")
 | |
| 	}
 | |
| 
 | |
| 	sk := new(SecretKey)
 | |
| 	copy(sk[:], priv[:ffi.PrivateKeyBytes])
 | |
| 
 | |
| 	pubkey := ffi.PrivateKeyPublicKey(*sk)
 | |
| 
 | |
| 	return pubkey[:], nil
 | |
| }
 | |
| 
 | |
| func (blsSigner) Sign(p []byte, msg []byte) ([]byte, error) {
 | |
| 	if p == nil || len(p) != ffi.PrivateKeyBytes {
 | |
| 		return nil, fmt.Errorf("bls signature invalid private key")
 | |
| 	}
 | |
| 
 | |
| 	sk := new(SecretKey)
 | |
| 	copy(sk[:], p[:ffi.PrivateKeyBytes])
 | |
| 
 | |
| 	sig := ffi.PrivateKeySign(*sk, msg)
 | |
| 
 | |
| 	return sig[:], nil
 | |
| }
 | |
| 
 | |
| func (blsSigner) Verify(sig []byte, a address.Address, msg []byte) error {
 | |
| 	payload := a.Payload()
 | |
| 	if sig == nil || len(sig) != ffi.SignatureBytes || len(payload) != ffi.PublicKeyBytes {
 | |
| 		return fmt.Errorf("bls signature failed to verify")
 | |
| 	}
 | |
| 
 | |
| 	pk := new(PublicKey)
 | |
| 	copy(pk[:], payload[:ffi.PublicKeyBytes])
 | |
| 
 | |
| 	sigS := new(Signature)
 | |
| 	copy(sigS[:], sig[:ffi.SignatureBytes])
 | |
| 
 | |
| 	msgs := [1]ffi.Message{msg}
 | |
| 	pks := [1]PublicKey{*pk}
 | |
| 
 | |
| 	if !ffi.HashVerify(sigS, msgs[:], pks[:]) {
 | |
| 		return fmt.Errorf("bls signature failed to verify")
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func init() {
 | |
| 	sigs.RegisterSignature(crypto.SigTypeBLS, blsSigner{})
 | |
| }
 |