package signature import ( "crypto/rand" "encoding/base64" "errors" "github.com/cloudflare/circl/sign/bls" ) type PrivateKey [32]byte func (pk PrivateKey) Bls() (privKey *bls.PrivateKey[bls.KeyG2SigG1], err error) { privKey = &bls.PrivateKey[bls.KeyG2SigG1]{} err = privKey.UnmarshalBinary(pk[:]) if err != nil { return } return } func (pk PrivateKey) Sign(msg []byte) (sig Signature, err error) { privKey, err := pk.Bls() if err != nil { return } sig = Signature(bls.Sign(privKey, msg)) return } func (pk PrivateKey) SignKey(key PublicKey) (sig Signature, err error) { pubKey := &bls.PublicKey[bls.KeyG2SigG1]{} err = pubKey.UnmarshalBinary(key[:]) if err != nil { return } return pk.Sign(key[:]) } func (pk PrivateKey) String() (out string) { out = base64.StdEncoding.EncodeToString(pk[:]) return } type PublicKey [96]byte func (pk PublicKey) Bls() (pubKey *bls.PublicKey[bls.KeyG2SigG1], err error) { pubKey = &bls.PublicKey[bls.KeyG2SigG1]{} err = pubKey.UnmarshalBinary(pk[:]) if err != nil { return } return } func (pk PublicKey) Verify(msg []byte, sig Signature) (ok bool, err error) { pubKey, err := pk.Bls() if err != nil { return } ok = bls.Verify(pubKey, msg, sig[:]) return } func (pk PublicKey) String() (out string) { out = base64.StdEncoding.EncodeToString(pk[:]) return } type Signature [48]byte type Keypair struct { PrivateKey PublicKey } func NewKeypair() (kp *Keypair, err error) { var ( ikm = make([]byte, 64) salt = make([]byte, 32) privKey *bls.PrivateKey[bls.KeyG2SigG1] pubKey *bls.PublicKey[bls.KeyG2SigG1] privKeyBytes = make([]byte, 32) pubKeyBytes = make([]byte, 96) ) _, err = rand.Read(ikm) if err != nil { return } _, err = rand.Read(salt) if err != nil { return } privKey, err = bls.KeyGen[bls.KeyG2SigG1](ikm, salt, []byte("")) if err != nil { return } privKeyBytes, err = privKey.MarshalBinary() if err != nil { return } pubKey = privKey.PublicKey() pubKeyBytes, err = pubKey.MarshalBinary() if err != nil { return } kp = &Keypair{ PrivateKey: PrivateKey(privKeyBytes), PublicKey: PublicKey(pubKeyBytes), } return } func (kp *Keypair) validate() (ok bool, err error) { var testMessage [128]byte _, err = rand.Read(testMessage[:]) if err != nil { return } sig, _ := kp.PrivateKey.Sign(testMessage[:]) ok, _ = kp.PublicKey.Verify(testMessage[:], sig) return } type SignatureService struct { *Keypair } func NewSignatureService(signer *Keypair) (srv *SignatureService, err error) { if signer == nil { var ok bool signer, err = NewKeypair() if err != nil { return } ok, err = signer.validate() if err != nil { return } if !ok { err = errors.New("failed to validate new signer keypair") return } } srv = &SignatureService{ Keypair: signer, } return }