diff --git a/pkg/libzmix/bbs/bbs.go b/pkg/libzmix/bbs/bbs.go new file mode 100644 index 0000000..9e0c864 --- /dev/null +++ b/pkg/libzmix/bbs/bbs.go @@ -0,0 +1,720 @@ +package bbs + +/* + #cgo LDFLAGS: -L${SRCDIR} -lbbs + #include "bbs_cl.h" + #include +*/ +import "C" +import ( + "unsafe" + + "github.com/pkg/errors" +) + +type BlsKeyPair struct { + PublicKey C.ByteBuffer + SecretKey C.ByteBuffer +} + +type HandleByteBuffer struct { + Buffer C.ByteBuffer +} + +func (r HandleByteBuffer) Free() { + C.bbs_byte_buffer_free(r.Buffer) +} + +//GenerateKey generates a bls key pair +func GenerateBlsKey(data []byte) (*BlsKeyPair, error) { + var seed C.ByteBuffer + defer C.bbs_byte_buffer_free(seed) + var publicKey C.ByteBuffer + var secretKey C.ByteBuffer + var err C.ExternError + + seed.len = (C.long)(len(data)) + if len(data) > 0 { + seed.data = (*C.uchar)(unsafe.Pointer(&data)) + } + + code := C.bls_generate_key(seed, &publicKey, &secretKey, &err) + if code != 0 { + return nil, errors.Errorf("err occurred generating BLS key pair: %s", C.GoString(err.message)) + } + + pkSize := C.bls_public_key_size() + skSize := C.bls_secret_key_size() + if publicKey.len != (C.long)(pkSize) || secretKey.len != (C.long)(skSize) { + return nil, errors.Errorf("key pair lengths are invalid") + } + + return &BlsKeyPair{ + PublicKey: publicKey, + SecretKey: secretKey, + }, nil +} + +//FreeSecretKey deallocates the secret key instance +func (r *BlsKeyPair) FreeSecretKey() { + C.bbs_byte_buffer_free(r.SecretKey) +} + +//FreeSecretKey deallocates the public key instance +func (r *BlsKeyPair) FreePublicKey() { + C.bbs_byte_buffer_free(r.PublicKey) +} + +//BlsPublicKeyToBBSKey converts a bls public key to a BBS public key +func (r *BlsKeyPair) BlsPublicKeyToBBSKey(messageCount int) (*HandleByteBuffer, error) { + var bbsPublicKey C.ByteBuffer + var err C.ExternError + + count := (C.uint)(messageCount) + + code := C.bls_public_key_to_bbs_key(r.PublicKey, count, &bbsPublicKey, &err) + if code != 0 { + return nil, errors.Errorf("error occurred converting BLS public key to BBS public key: %s", C.GoString(err.message)) + } + + return &HandleByteBuffer{Buffer: bbsPublicKey}, nil +} + +type Handle struct { + data C.ulong +} + +type BlindSignContext Handle + +//BlindSignContext initializes a blind sign context +func BlindSignContextInit() (*BlindSignContext, error) { + var err C.ExternError + + handle := C.bbs_blind_sign_context_init(&err) + if err.code != 0 { + return nil, errors.Errorf("error occurred initializing BBS sign context: %s", C.GoString(err.message)) + } + + return &BlindSignContext{handle}, nil +} + +//SetPublicKey sets the bbs public key on the BlindSignContext +func (r *BlindSignContext) SetPublicKey(publicKey HandleByteBuffer) error { + var err C.ExternError + + code := C.bbs_blind_sign_context_set_public_key(r.data, publicKey.Buffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting secret key to BBS sign context: %s", C.GoString(err.message)) + } + + return nil +} + +//SetSecretKey sets the bls secret key on the BlindSignContext +func (r *BlindSignContext) SetSecretKey(secretKey HandleByteBuffer) error { + var err C.ExternError + + code := C.bbs_blind_sign_context_set_secret_key(r.data, secretKey.Buffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting secret key to BBS sign context: %s", C.GoString(err.message)) + } + + return nil +} + +//SetCommitment sets the commitment on the BlindSignContext +func (r *BlindSignContext) SetCommitment(blindCommitment HandleByteBuffer) error { + var err C.ExternError + + code := C.bbs_blind_sign_context_set_commitment(r.data, blindCommitment.Buffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting blind commitment to BBS blind sign context: %s", C.GoString(err.message)) + } + + return nil +} + +//AddMessage adds the message and associated index to BlindSignContext +func (r *BlindSignContext) AddMessage(message string, index int) error { + var err C.ExternError + var cMessage C.ByteBuffer + + cm := C.CString(message) + cMessage.len = (C.long)(len(message)) + cMessage.data = (*C.uchar)(unsafe.Pointer(cm)) + code := C.bbs_blind_sign_context_add_message_bytes(r.data, (C.uint)(index), cMessage, &err) + if code != 0 { + return errors.Errorf("error occurred adding message bytes to BBS sign context: %s", C.GoString(err.message)) + } + + return nil +} + +type BlindedSignature HandleByteBuffer + +//Finish generates a BlindedSignature from a BlindSignContext +func (r *BlindSignContext) Finish() (*BlindedSignature, error) { + var err C.ExternError + var blindedSignature C.ByteBuffer + + code := C.bbs_blind_sign_context_finish(r.data, &blindedSignature, &err) + if code != 0 { + return nil, errors.Errorf("error occurred finishing BBS sign context: %s", C.GoString(err.message)) + } + + sigSize := C.bbs_blind_signature_size() + if blindedSignature.len != (C.long)(sigSize) { + return nil, errors.Errorf("signature is incorrect size") + } + + return &BlindedSignature{Buffer: blindedSignature}, nil +} + +//Unblind returns the Signature from the BlindedSignature +func (r *BlindedSignature) Unblind(blindingFactor HandleByteBuffer) (*Signature, error) { + var unblindSignature C.ByteBuffer + var err C.ExternError + + code := C.bbs_unblind_signature(r.Buffer, blindingFactor.Buffer, &unblindSignature, &err) + if code != 0 { + return nil, errors.Errorf("error occurred unblinding signature: %s", C.GoString(err.message)) + } + + sigSize := C.bbs_signature_size() + if unblindSignature.len != (C.long)(sigSize) { + return nil, errors.Errorf("signature is incorrect size") + } + + return &Signature{unblindSignature}, nil +} + +type SignContext Handle + +//SignContextInit initializes a sign context +func SignContextInit() (*SignContext, error) { + var err C.ExternError + + handle := C.bbs_sign_context_init(&err) + if err.code != 0 { + return nil, errors.Errorf("error occurred initializing BBS sign context: %s", C.GoString(err.message)) + } + + return &SignContext{handle}, nil +} + +//SetPublicKey sets the public key on the SignContext +func (r *SignContext) SetPublicKey(publicKey HandleByteBuffer) error { + var err C.ExternError + + code := C.bbs_sign_context_set_public_key(r.data, publicKey.Buffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting secret key to BBS sign context: %s", C.GoString(err.message)) + } + + return nil +} + +//SetSecretKey sets the bls secret key on teh SignContext +func (r *SignContext) SetSecretKey(secretKey HandleByteBuffer) error { + var err C.ExternError + + code := C.bbs_sign_context_set_secret_key(r.data, secretKey.Buffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting secret key to BBS sign context: %s", C.GoString(err.message)) + } + + return nil +} + +//AddMessages adds messages to the SignContext +func (r *SignContext) AddMessages(messages []string) error { + var err C.ExternError + var message C.ByteBuffer + defer C.bbs_byte_buffer_free(message) + + for _, m := range messages { + message.len = (C.long)(len(m)) + cm := C.CString(m) + message.data = (*C.uchar)(unsafe.Pointer(&cm)) + code := C.bbs_sign_context_add_message_bytes(r.data, message, &err) + if code != 0 { + return errors.Errorf("error occurred adding message bytes to BBS sign context: %s", C.GoString(err.message)) + } + } + + return nil +} + +type Signature HandleByteBuffer + +//Finish generates a Signature from the SignContext +func (r *SignContext) Finish() (*Signature, error) { + var err C.ExternError + var signature C.ByteBuffer + + code := C.bbs_sign_context_finish(r.data, &signature, &err) + if code != 0 { + return nil, errors.Errorf("error occurred finishing BBS sign context: %s", C.GoString(err.message)) + } + + sigSize := C.bbs_signature_size() + if signature.len != (C.long)(sigSize) { + return nil, errors.Errorf("signature is incorrect size") + } + + return &Signature{Buffer: signature}, nil +} + +//Free deallocates the Signature instance +func (r *Signature) Free() { + C.bbs_byte_buffer_free(r.Buffer) +} + +type BlindCommitmentContext Handle + +//BlindCommitmentContextInit initializes a BlindCommitmentContext +func BlindCommitmentContextInit() (*BlindCommitmentContext, error) { + var err C.ExternError + + handle := C.bbs_blind_commitment_context_init(&err) + if err.code != 0 { + return nil, errors.Errorf("error occurred initializing BBS blind commitment context: %s", C.GoString(err.message)) + } + + return &BlindCommitmentContext{handle}, nil +} + +//SetPublicKey sets the bbs public key on the BlindCommitmentContext +func (r *BlindCommitmentContext) SetPublicKey(publicKey HandleByteBuffer) error { + var err C.ExternError + + code := C.bbs_blind_commitment_context_set_public_key(r.data, publicKey.Buffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting secret key to BBS sign context: %s", C.GoString(err.message)) + } + + return nil +} + +//AddMessage adds a message and its associated index to the BlindCommitmentContext +func (r *BlindCommitmentContext) AddMessage(message string, index int) error { + var err C.ExternError + var cMessage C.ByteBuffer + defer C.bbs_byte_buffer_free(cMessage) + + cMessage.len = (C.long)(len(message)) + cm := C.CString(message) + cMessage.data = (*C.uchar)(unsafe.Pointer(cm)) + code := C.bbs_blind_commitment_context_add_message_bytes(r.data, (C.uint)(index), cMessage, &err) + if code != 0 { + return errors.Errorf("error occurred adding message bytes to BBS blind commitment context: %s", C.GoString(err.message)) + } + + return nil +} + +//SetNonce sets the nonce on the BlindedCommitmentContext +func (r *BlindCommitmentContext) SetNonce(nonce []byte) error { + var err C.ExternError + var nonceBuffer C.ByteBuffer + defer C.bbs_byte_buffer_free(nonceBuffer) + + nonceBuffer.len = (C.long)(len(nonce)) + nonceBuffer.data = (*C.uchar)(unsafe.Pointer(&nonce)) + + code := C.bbs_blind_commitment_context_set_nonce_bytes(r.data, nonceBuffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting nonce bytes on BBS blind commitment context: %s", C.GoString(err.message)) + } + + return nil +} + +type BlindedCommitment struct { + Commitment C.ByteBuffer + Context C.ByteBuffer + BlindingFactor C.ByteBuffer +} + +//Finish generates a commitment, context, and blinding factor from the BlindCommitmentContext +func (r *BlindCommitmentContext) Finish() (*BlindedCommitment, error) { + var err C.ExternError + var commitment C.ByteBuffer + var outContext C.ByteBuffer + var blindingFactor C.ByteBuffer + + code := C.bbs_blind_commitment_context_finish(r.data, &commitment, &outContext, &blindingFactor, &err) + if code > 0 { + return nil, errors.Errorf("error occurred finishing BBS sign context: %s", C.GoString(err.message)) + } + + return &BlindedCommitment{ + Commitment: commitment, + Context: outContext, + BlindingFactor: blindingFactor, + }, nil +} + +//FreeCommitment deallocates the Commitment, Context, and BlindingFactor instances from the BlindedCommitment +func (r *BlindedCommitment) Free() { + C.bbs_byte_buffer_free(r.Commitment) + C.bbs_byte_buffer_free(r.Context) + C.bbs_byte_buffer_free(r.BlindingFactor) +} + +type VerifyBlindCommitmentContext Handle + +//VerifyBlindCommitmentContextInit initializes a VerifyBlindCommitmentContext +func VerifyBlindCommitmentContextInit() (*VerifyBlindCommitmentContext, error) { + var err C.ExternError + + handle := C.bbs_verify_blind_commitment_context_init(&err) + if err.code != 0 { + return nil, errors.Errorf("error occurred initializing BBS verify blinded commitment context: %s", C.GoString(err.message)) + } + + return &VerifyBlindCommitmentContext{data: handle}, nil +} + +//SetPublicKey sets the bbs public key on the VerifyBlindCommitmentContext +func (r *VerifyBlindCommitmentContext) SetPublicKey(publicKey HandleByteBuffer) error { + var err C.ExternError + + code := C.bbs_verify_blind_commitment_context_set_public_key(r.data, publicKey.Buffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting secret key to BBS sign context: %s", C.GoString(err.message)) + } + + return nil +} + +//SetNonce sets the nonce on the VerifyBlindCommitmentContext +func (r *VerifyBlindCommitmentContext) SetNonce(nonce []byte) error { + var err C.ExternError + var nonceBuffer C.ByteBuffer + defer C.bbs_byte_buffer_free(nonceBuffer) + + nonceBuffer.len = (C.long)(len(nonce)) + nonceBuffer.data = (*C.uchar)(unsafe.Pointer(&nonce)) + + code := C.bbs_verify_blind_commitment_context_set_nonce_bytes(r.data, nonceBuffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting nonce bytes on BBS verify blind commitment context: %s", C.GoString(err.message)) + } + + return nil +} + +//AddBlinded adds the index of the blinded message to the VerifyBlindCommitmentContext +func (r *VerifyBlindCommitmentContext) AddBlinded(index int) error { + var err C.ExternError + + code := C.bbs_verify_blind_commitment_context_add_blinded(r.data, (C.uint)(index), &err) + if code != 0 { + return errors.Errorf("error occurred setting blinded index on BBS verify blind commitment context: %s", C.GoString(err.message)) + } + + return nil +} + +//SetProof sets the context from the BlindCommitmentContext on the VerifyBlindCommitmentContext +func (r *VerifyBlindCommitmentContext) SetProof(proof HandleByteBuffer) error { + var err C.ExternError + + code := C.bbs_verify_blind_commitment_context_set_proof(r.data, proof.Buffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting proof on BBS verify blind commitment context: %s", C.GoString(err.message)) + } + + return nil +} + +//Finish verifies the BlindCommitmentContext +func (r *VerifyBlindCommitmentContext) Finish() error { + var err C.ExternError + + code := C.bbs_verify_blind_commitment_context_finish(r.data, &err) + if err.code != 0 { + return errors.Errorf("error occurred finishing BBS verify proof context: %s", C.GoString(err.message)) + } + + if code != 200 { + if ProofStatus[code] != "" { + return errors.Errorf("failed to verify proof: %s", ProofStatus[code]) + } + return errors.Errorf("unknown error occurred verifying proof: %d", code) + } + + return nil +} + +type VerifyContext Handle + +//VerifyContextInit initializes a VerifyContext +func VerifyContextInit() (*VerifyContext, error) { + var err C.ExternError + + handle := C.bbs_verify_context_init(&err) + if err.code != 0 { + return nil, errors.Errorf("error occurred initializing BBS verify context: %s", C.GoString(err.message)) + } + + return &VerifyContext{data: handle}, nil +} + +//AddMessages adds the messages to the VerifyContext +func (r *VerifyContext) AddMessages(messages []string) error { + var err C.ExternError + var message C.ByteBuffer + + for _, m := range messages { + message.len = (C.long)(len(m)) + cm := C.CString(m) + message.data = (*C.uchar)(unsafe.Pointer(cm)) + code := C.bbs_verify_context_add_message_bytes(r.data, message, &err) + if code != 0 { + return errors.Errorf("error occurred adding message bytes to BBS verify context: %s", C.GoString(err.message)) + } + } + + return nil +} + +//SetPublicKey sets the bbs public key on the VerifyContext +func (r *VerifyContext) SetPublicKey(publicKey HandleByteBuffer) error { + var err C.ExternError + + code := C.bbs_verify_context_set_public_key(r.data, publicKey.Buffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting secret key to BBS verify context: %s", C.GoString(err.message)) + } + + return nil +} + +//SetSignature sets the signature on the VerifyContext +func (r *VerifyContext) SetSignature(signature *Signature) error { + var err C.ExternError + + code := C.bbs_verify_context_set_signature(r.data, signature.Buffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting signature to BBS verify context: %s", C.GoString(err.message)) + } + + return nil +} + +//Finish verifies a BBS+ signature for a set of messages with a BBS public key +func (r *VerifyContext) Finish() (bool, error) { + var err C.ExternError + code := C.bbs_verify_context_finish(r.data, &err) + if err.code != 0 { + return code == 0, errors.Errorf("error occurred finishing VerifyContext: %s", C.GoString(err.message)) + } + return code == 0, nil +} + +type ProofContext Handle + +//ProofContextInit creates the proof asynchronous +func ProofContextInit() (*ProofContext, error) { + var err C.ExternError + + handle := C.bbs_create_proof_context_init(&err) + if err.code != 0 { + return nil, errors.Errorf("error occurred initializing BBS create proof context: %s", C.GoString(err.message)) + } + + return &ProofContext{data: handle}, nil +} + +type ProofMessageType int + +const ( + Revealed ProofMessageType = 1 + HiddenProofSpecificBlinding ProofMessageType = 2 + HiddenExternalBlinding ProofMessageType = 3 +) + +//AddProofMessage adds a proof message to the proof context +func (r *ProofContext) AddProofMessages(messages []string, messageType ProofMessageType, blindingFactor HandleByteBuffer) error { + var err C.ExternError + var proofMessageType C.proof_message_t + + switch messageType { + case 1: + proofMessageType = C.Revealed + case 2: + proofMessageType = C.HiddenProofSpecificBlinding + case 3: + proofMessageType = C.HiddenExternalBlinding + } + + for _, m := range messages { + var message C.ByteBuffer + message.len = (C.long)(len(m)) + cm := C.CString(m) + message.data = (*C.uchar)(unsafe.Pointer(cm)) + code := C.bbs_create_proof_context_add_proof_message_bytes(r.data, message, proofMessageType, blindingFactor.Buffer, &err) + if code != 0 { + return errors.Errorf("error occurred adding message bytes to BBS create proof context: %s", C.GoString(err.message)) + } + } + + return nil +} + +//SetSignature sets the signature on the ProofContext +func (r *ProofContext) SetSignature(signature *Signature) error { + var err C.ExternError + + code := C.bbs_create_proof_context_set_signature(r.data, signature.Buffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting signature to BBS create proof context: %s", C.GoString(err.message)) + } + + return nil +} + +//SetPublicKey sets the bbs public key on the ProofContext +func (r *ProofContext) SetPublicKey(publicKey HandleByteBuffer) error { + var err C.ExternError + + code := C.bbs_create_proof_context_set_public_key(r.data, publicKey.Buffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting secret key to BBS create proof context: %s", C.GoString(err.message)) + } + + return nil +} + +//SetNonce sets the nonce on the ProofContext +func (r *ProofContext) SetNonce(nonce []byte) error { + var err C.ExternError + var nonceBuffer C.ByteBuffer + + nonceBuffer.len = (C.long)(len(nonce)) + nonceBuffer.data = (*C.uchar)(unsafe.Pointer(&nonce)) + + code := C.bbs_create_proof_context_set_nonce_bytes(r.data, nonceBuffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting nonce bytes on BBS create proof context: %s", C.GoString(err.message)) + } + + return nil +} + +type Proof HandleByteBuffer + +//Finish generates a proof from the ProofContext +func (r *ProofContext) Finish() (*Proof, error) { + var proof C.ByteBuffer + var err C.ExternError + + code := C.bbs_create_proof_context_finish(r.data, &proof, &err) + if code != 0 { + return nil, errors.Errorf("error occurred finishing BBS create proof context: %s", C.GoString(err.message)) + } + + return &Proof{Buffer: proof}, nil +} + +//Free deallocates the proof instance +func (r *Proof) Free() { + C.bbs_byte_buffer_free(r.Buffer) +} + +type VerifyProofContext Handle + +//VerifyProofContextInit initializes a VerifyProofContext +func VerifyProofContextInit() (*VerifyProofContext, error) { + var err C.ExternError + + handle := C.bbs_verify_proof_context_init(&err) + if err.code != 0 { + return nil, errors.Errorf("error occurred initializing BBS verify proof context: %s", C.GoString(err.message)) + } + + return &VerifyProofContext{data: handle}, nil +} + +//AddMessages adds the message and the associated index to the VerifyProofContext +func (r *VerifyProofContext) AddMessage(message string, index int) error { + var err C.ExternError + var cMessage C.ByteBuffer + + cMessage.len = (C.long)(len(message)) + cm := C.CString(message) + cMessage.data = (*C.uchar)(unsafe.Pointer(cm)) + code := C.bbs_verify_proof_context_add_message_bytes(r.data, (C.uint)(index), cMessage, &err) + if code != 0 { + return errors.Errorf("error occurred adding message bytes to BBS verify proof context: %s", C.GoString(err.message)) + } + + return nil +} + +//SetProof sets the proof on the VerifyProofContext +func (r *VerifyProofContext) SetProof(proof HandleByteBuffer) error { + var err C.ExternError + + code := C.bbs_verify_proof_context_set_proof(r.data, proof.Buffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting proof to BBS verify proof context: %s", C.GoString(err.message)) + } + + return nil +} + +//SetPublicKey sets the bbs public key on the VerifyProofContext +func (r *VerifyProofContext) SetPublicKey(publicKey HandleByteBuffer) error { + var err C.ExternError + + code := C.bbs_verify_proof_context_set_public_key(r.data, publicKey.Buffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting secret key to BBS create proof context: %s", C.GoString(err.message)) + } + + return nil +} + +//SetNonce sets the nonce on the VerifyProofContext +func (r *VerifyProofContext) SetNonce(nonce []byte) error { + var err C.ExternError + var nonceBuffer C.ByteBuffer + + nonceBuffer.len = (C.long)(len(nonce)) + nonceBuffer.data = (*C.uchar)(unsafe.Pointer(&nonce)) + + code := C.bbs_verify_proof_context_set_nonce_bytes(r.data, nonceBuffer, &err) + if code != 0 { + return errors.Errorf("error occurred setting nonce bytes on BBS create proof context: %s", C.GoString(err.message)) + } + + return nil +} + +//Finish verifies a proof +func (r *VerifyProofContext) Finish() error { + var err C.ExternError + + code := C.bbs_verify_proof_context_finish(r.data, &err) + if err.code != 0 { + return errors.Errorf("error occurred finishing BBS verify proof context: %s", C.GoString(err.message)) + } + + if code != 200 { + if ProofStatus[code] != "" { + return errors.Errorf("failed to verify proof: %s", ProofStatus[code]) + } + return errors.Errorf("unknown error occurred verifying proof: %d", code) + } + + return nil +} + +var ProofStatus = map[C.int]string{ + 400: "The proof failed because the signature proof of knowledge failed", + 401: "The proof failed because a hidden message was invalid when the proof was created", + 402: "The proof failed because a revealed message was invalid", +} diff --git a/pkg/libzmix/bbs/bbs_cl.h b/pkg/libzmix/bbs/bbs_cl.h new file mode 100644 index 0000000..89126e2 --- /dev/null +++ b/pkg/libzmix/bbs/bbs_cl.h @@ -0,0 +1,211 @@ +#ifndef __bbs__plus__included__ +#define __bbs__plus__included__ + +#include + +/* Used for receiving a ByteBuffer from C that was allocated by either C or Rust. +* If Rust allocated, then the outgoing struct is `ffi_support::ByteBuffer` +* Caller is responsible for calling free where applicable. +*/ +typedef struct { + int64_t len; + uint8_t *data; +} ByteBuffer; + +typedef struct { + int32_t code; + char* message; /* note: nullable */ +} ExternError; + +typedef enum { + Revealed = 1, + HiddenProofSpecificBlinding = 2, + HiddenExternalBlinding = 3, +} proof_message_t; + +typedef enum { + /* The proof verified */ + Success = 200, + /* The proof failed because the signature proof of knowledge failed */ + BadSignature = 400, + /* The proof failed because a hidden message was invalid when the proof was created */ + BadHiddenMessage = 401, + /* The proof failed because a revealed message was invalid */ + BadRevealedMessage = 402, +} signature_proof_status; + +#ifdef __cplusplus +extern "C" { +#endif + +void bbs_string_free(char* string); +void bbs_byte_buffer_free(ByteBuffer data); + +uint64_t bbs_blind_commitment_context_init(ExternError *err); + +int32_t bbs_blind_commitment_context_finish(uint64_t handle, + ByteBuffer *commitment, + ByteBuffer *out_context, + ByteBuffer *blinding_factor, + ExternError *err); + +int32_t bbs_blind_commitment_context_add_message_bytes(uint64_t handle, + uint32_t index, + ByteBuffer message, + ExternError *err); + +int32_t bbs_blind_commitment_context_set_public_key(uint64_t handle, + ByteBuffer public_key, + ExternError *err); + +int32_t bbs_blind_commitment_context_set_nonce_bytes(uint64_t handle, + ByteBuffer message, + ExternError *err); + + +int32_t bbs_blind_sign_context_finish(uint64_t handle, + ByteBuffer *blinded_signature, + ExternError *err); + +int32_t bbs_blind_sign_context_add_message_bytes(uint64_t handle, + uint32_t index, + ByteBuffer message, + ExternError *err); + +int32_t bbs_blind_sign_context_set_secret_key(uint64_t handle, + ByteBuffer secret_key, + ExternError *err); + +int32_t bbs_blind_sign_context_set_public_key(uint64_t handle, + ByteBuffer public_key, + ExternError *err); + +int32_t bbs_blind_sign_context_set_commitment(uint64_t handle, + ByteBuffer commitment, + ExternError *err); + +uint64_t bbs_blind_sign_context_init(ExternError *err); + +int32_t bbs_blind_signature_size(void); + +int32_t bbs_unblind_signature(ByteBuffer blind_signature, + ByteBuffer blinding_factor, + ByteBuffer *unblind_signature, + ExternError *err); + +int32_t bbs_create_proof_context_finish(uint64_t handle, ByteBuffer *proof, ExternError *err); + +int32_t bbs_create_proof_context_set_public_key(uint64_t handle, + ByteBuffer public_key, + ExternError *err); + +int32_t bbs_create_proof_context_set_signature(uint64_t handle, + ByteBuffer signature , + ExternError *err); + +int32_t bbs_create_proof_context_set_nonce_bytes(uint64_t handle, + ByteBuffer message, + ExternError *err); + +int32_t bbs_create_proof_context_add_proof_message_bytes(uint64_t handle, + ByteBuffer message, + proof_message_t xtype, + ByteBuffer blinding_factor, + ExternError *err); + +uint64_t bbs_create_proof_context_init(ExternError *err); + +int32_t bbs_sign_context_add_message_bytes(uint64_t handle, + ByteBuffer message, + ExternError *err); + +int32_t bbs_sign_context_set_secret_key(uint64_t handle, + ByteBuffer secret_key, + ExternError *err); + +int32_t bbs_sign_context_set_public_key(uint64_t handle, + ByteBuffer public_key, + ExternError *err); + +int32_t bbs_sign_context_finish(uint64_t handle, ByteBuffer *signature, ExternError *err); + +uint64_t bbs_sign_context_init(ExternError *err); + +int32_t bbs_signature_size(void); + +int32_t bbs_verify_context_add_message_bytes(uint64_t handle, + ByteBuffer message, + ExternError *err); + +int32_t bbs_verify_context_set_public_key(uint64_t handle, + ByteBuffer public_key, + ExternError *err); +int32_t bbs_verify_context_set_signature(uint64_t handle, + ByteBuffer signature, + ExternError *err); + +int32_t bbs_verify_context_finish(uint64_t handle, ExternError *err); + +uint64_t bbs_verify_context_init(ExternError *err); + +int32_t bbs_verify_blind_commitment_context_add_blinded(uint64_t handle, + uint32_t index, + ExternError *err); + +int32_t bbs_verify_blind_commitment_context_set_public_key(uint64_t handle, + ByteBuffer public_key, + ExternError *err); + +int32_t bbs_verify_blind_commitment_context_set_nonce_bytes(uint64_t handle, + ByteBuffer message, + ExternError *err); + +int32_t bbs_verify_blind_commitment_context_set_proof(uint64_t handle, + ByteBuffer proof, + ExternError *err); + +uint64_t bbs_verify_blind_commitment_context_init(ExternError *err); + +int32_t bbs_verify_blind_commitment_context_finish(uint64_t handle, ExternError *err); + +int32_t bbs_verify_proof_context_finish(uint64_t handle, ExternError *err); + + +int32_t bbs_verify_proof_context_set_proof(uint64_t handle, + ByteBuffer proof, + ExternError *err); + +int32_t bbs_verify_proof_context_set_public_key(uint64_t handle, + ByteBuffer public_key, + ExternError *err); + +int32_t bbs_verify_proof_context_set_nonce_bytes(uint64_t handle, + ByteBuffer message, + ExternError *err); + +int32_t bbs_verify_proof_context_add_message_bytes(uint64_t handle, + uint32_t index, + ByteBuffer message, + ExternError *err); + +uint64_t bbs_verify_proof_context_init(ExternError *err); + +int32_t bls_generate_key(ByteBuffer seed, + ByteBuffer *public_key, + ByteBuffer *secret_key, + ExternError *err); + +int32_t bls_public_key_size(void); + +int32_t bls_public_key_to_bbs_key(ByteBuffer d_public_key, + uint32_t message_count, + ByteBuffer *public_key, + ExternError *err); + +int32_t bls_secret_key_size(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/pkg/libzmix/bbs/bbs_test.go b/pkg/libzmix/bbs/bbs_test.go new file mode 100644 index 0000000..b329bf5 --- /dev/null +++ b/pkg/libzmix/bbs/bbs_test.go @@ -0,0 +1,661 @@ +package bbs + +import ( + "math/rand" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/hyperledger/ursa-wrapper-go/pkg/libursa/ursa" +) + +func TestGenerateKey(t *testing.T) { + t.Run("GenerateKey", func(t *testing.T) { + data := make([]byte, 4) + rand.Read(data) + kp, err := GenerateBlsKey(nil) + + assert.Empty(t, err) + assert.NotEmpty(t, kp) + assert.NotEmpty(t, kp.PublicKey) + assert.NotEmpty(t, kp.SecretKey) + + kp.FreePublicKey() + kp.FreeSecretKey() + }) +} + +func TestBlsKeyPair(t *testing.T) { + data := make([]byte, 4) + rand.Read(data) + blskp, err := GenerateBlsKey(data) + assert.Empty(t, err) + t.Run("BlsPublicKeyToBBSKey", func(t *testing.T) { + bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(5) + assert.Empty(t, err) + assert.NotEmpty(t, bbsPublicKey) + + bbsPublicKey.Free() + }) + + blskp.FreeSecretKey() + blskp.FreePublicKey() +} + +func TestSignContextInit(t *testing.T) { + t.Run("SignContextInit", func(t *testing.T) { + handle, err := SignContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, handle.data) + }) +} + +func TestSignContext(t *testing.T) { + data := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 21, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 31, 32} + t.Run("SetPublicKey", func(t *testing.T) { + signContext, err := SignContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, signContext.data) + + blskp, err := GenerateBlsKey(data) + assert.Empty(t, err) + + bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(5) + assert.Empty(t, err) + + err = signContext.SetPublicKey(*bbsPublicKey) + assert.Empty(t, err) + }) + + t.Run("SetSecretKey", func(t *testing.T) { + signContext, err := SignContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, signContext.data) + + blskp, err := GenerateBlsKey(data) + assert.Empty(t, err) + + err = signContext.SetSecretKey(HandleByteBuffer{ + Buffer: blskp.SecretKey, + }) + assert.Empty(t, err) + }) + + t.Run("AddMessageBytes", func(t *testing.T) { + signContext, err := SignContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, signContext.data) + + err = signContext.AddMessages([]string{"a message", "another message", "the last message"}) + assert.Empty(t, err) + assert.NotEmpty(t, signContext) + }) + + t.Run("Finish full SignContext", func(t *testing.T) { + signContext, err := SignContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, signContext.data) + + blskp, err := GenerateBlsKey(data) + assert.Empty(t, err) + bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(2) + assert.Empty(t, err) + + err = signContext.SetPublicKey(*bbsPublicKey) + assert.Empty(t, err) + + err = signContext.SetSecretKey(HandleByteBuffer{ + Buffer: blskp.SecretKey, + }) + assert.Empty(t, err) + + err = signContext.AddMessages([]string{"a message", "one more message"}) + assert.Empty(t, err) + assert.NotEmpty(t, signContext) + + signature, err := signContext.Finish() + assert.Empty(t, err) + assert.NotEmpty(t, signature) + signature.Free() + }) + + t.Run("Should error if public key isn't set", func(t *testing.T) { + signContext, err := SignContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, signContext.data) + + blskp, err := GenerateBlsKey(data) + assert.Empty(t, err) + + err = signContext.SetSecretKey(HandleByteBuffer{ + Buffer: blskp.SecretKey, + }) + assert.Empty(t, err) + + err = signContext.AddMessages([]string{"a message"}) + assert.Empty(t, err) + assert.NotEmpty(t, signContext) + + signature, err := signContext.Finish() + assert.Error(t, err) + assert.Contains(t, err.Error(), "Public Key must be set") + assert.Empty(t, signature) + }) + + t.Run("Should error if secret key isn't set", func(t *testing.T) { + signContext, err := SignContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, signContext.data) + + blskp, err := GenerateBlsKey(data) + assert.Empty(t, err) + bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(1) + assert.Empty(t, err) + + err = signContext.SetPublicKey(*bbsPublicKey) + assert.Empty(t, err) + + err = signContext.AddMessages([]string{"a message"}) + assert.Empty(t, err) + assert.NotEmpty(t, signContext) + + signature, err := signContext.Finish() + assert.Error(t, err) + assert.Contains(t, err.Error(), "Secret Key must be set") + assert.Empty(t, signature) + }) + + t.Run("Should error if messages aren't set", func(t *testing.T) { + signContext, err := SignContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, signContext.data) + + blskp, err := GenerateBlsKey(data) + assert.Empty(t, err) + bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(5) + assert.Empty(t, err) + + err = signContext.SetPublicKey(*bbsPublicKey) + assert.Empty(t, err) + + err = signContext.SetSecretKey(HandleByteBuffer{ + Buffer: blskp.SecretKey, + }) + assert.Empty(t, err) + + signature, err := signContext.Finish() + assert.Error(t, err) + assert.Contains(t, err.Error(), "Messages cannot be empty") + assert.Empty(t, signature) + }) +} + +func TestBlindCommitmentContextInit(t *testing.T) { + t.Run("BlindCommitmentContextInit", func(t *testing.T) { + handle, err := BlindCommitmentContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, handle.data) + }) +} + +func TestBlindCommitmentContext(t *testing.T) { + data := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 21, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 31, 32} + + t.Run("Finish full BlindCommitmentContext", func(t *testing.T) { + blindCommitmentContext, err := BlindCommitmentContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, blindCommitmentContext.data) + + blskp, err := GenerateBlsKey(data) + assert.Empty(t, err) + bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(3) + assert.Empty(t, err) + + err = blindCommitmentContext.SetPublicKey(*bbsPublicKey) + assert.Empty(t, err) + + nonce, err := ursa.NewNonce() + assert.Empty(t, err) + nonceBytes, err := nonce.ToJSON() + assert.Empty(t, err) + err = blindCommitmentContext.SetNonce(nonceBytes) + assert.Empty(t, err) + + err = blindCommitmentContext.AddMessage("a message", 0) + assert.Empty(t, err) + assert.NotEmpty(t, blindCommitmentContext) + + blindedCommitment, err := blindCommitmentContext.Finish() + assert.Empty(t, err) + assert.NotEmpty(t, blindedCommitment) + assert.NotEmpty(t, blindedCommitment.BlindingFactor) + assert.NotEmpty(t, blindedCommitment.Commitment) + assert.NotEmpty(t, blindedCommitment.Context) + blindedCommitment.Free() + }) +} + +func TestVerifyBlindCommitmentContextInit(t *testing.T) { + t.Run("VerifyBlindCommitmentContextInit", func(t *testing.T) { + handle, err := VerifyBlindCommitmentContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, handle.data) + }) +} + +func TestVerifyBlindCommitmentContext(t *testing.T) { + data := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 21, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 31, 32} + + t.Run("SetPublicKey", func(t *testing.T) { + verifyBlindCommitmentContext, err := VerifyBlindCommitmentContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, verifyBlindCommitmentContext.data) + + blskp, err := GenerateBlsKey(data) + assert.Empty(t, err) + bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(5) + assert.Empty(t, err) + + err = verifyBlindCommitmentContext.SetPublicKey(*bbsPublicKey) + assert.Empty(t, err) + }) + t.Run("SetNonceBytes", func(t *testing.T) { + verifyBlindCommitmentContext, err := VerifyBlindCommitmentContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, verifyBlindCommitmentContext.data) + + nonce, err := ursa.NewNonce() + assert.Empty(t, err) + nonceBytes, err := nonce.ToJSON() + assert.Empty(t, err) + err = verifyBlindCommitmentContext.SetNonce(nonceBytes) + assert.Empty(t, err) + }) + + t.Run("Finish", func(t *testing.T) { + verifyBlindCommitmentContext, err := VerifyBlindCommitmentContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, verifyBlindCommitmentContext.data) + + blskp, err := GenerateBlsKey(data) + assert.Empty(t, err) + bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(5) + assert.Empty(t, err) + err = verifyBlindCommitmentContext.SetPublicKey(*bbsPublicKey) + assert.Empty(t, err) + + nonce, err := ursa.NewNonce() + assert.Empty(t, err) + nonceBytes, err := nonce.ToJSON() + assert.Empty(t, err) + err = verifyBlindCommitmentContext.SetNonce(nonceBytes) + assert.Empty(t, err) + + err = verifyBlindCommitmentContext.AddBlinded(0) + assert.Empty(t, err) + + blindedCommitment := createBlindedCommitment(t, *bbsPublicKey, nonceBytes, []string{"a message"}) + + err = verifyBlindCommitmentContext.SetProof(HandleByteBuffer{Buffer: blindedCommitment.Context}) + assert.Empty(t, err) + + err = verifyBlindCommitmentContext.Finish() + assert.Empty(t, err) + blindedCommitment.Free() + }) +} + +func TestBlindSignContext(t *testing.T) { + data := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 21, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 31, 32} + + t.Run("full run", func(t *testing.T) { + messages := []string{"a message", "another message", "one more message"} + blindSignContext, err := BlindSignContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, blindSignContext) + + blskp, err := GenerateBlsKey(data) + assert.Empty(t, err) + bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(3) + assert.Empty(t, err) + + err = blindSignContext.SetPublicKey(*bbsPublicKey) + assert.Empty(t, err) + + err = blindSignContext.SetSecretKey(HandleByteBuffer{ + Buffer: blskp.SecretKey, + }) + assert.Empty(t, err) + + err = blindSignContext.AddMessage(messages[0], 0) + assert.Empty(t, err) + assert.NotEmpty(t, blindSignContext) + + nonce, err := ursa.NewNonce() + assert.Empty(t, err) + assert.NotEmpty(t, nonce) + + nonceBytes, err := nonce.ToJSON() + assert.Empty(t, err) + assert.NotEmpty(t, nonceBytes) + + blindedCommitment := createBlindedCommitment(t, *bbsPublicKey, nonceBytes, messages) + assert.NotEmpty(t, blindedCommitment) + + err = blindSignContext.SetCommitment(HandleByteBuffer{blindedCommitment.Commitment}) + assert.Empty(t, err) + assert.NotEmpty(t, blindSignContext) + + blindedSignature, err := blindSignContext.Finish() + assert.Empty(t, err) + assert.NotEmpty(t, blindedSignature) + + unblindedSignature, err := blindedSignature.Unblind(HandleByteBuffer{blindedCommitment.BlindingFactor}) + assert.Empty(t, err) + assert.NotEmpty(t, unblindedSignature) + blindedCommitment.Free() + }) +} + +func TestVerifyContext(t *testing.T) { + data := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 21, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 31, 32} + + t.Run("verify unblinded signature", func(t *testing.T) { + messages := []string{"a message", "another message", "one more message"} + blindSignContext, err := BlindSignContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, blindSignContext) + + blskp, err := GenerateBlsKey(data) + assert.Empty(t, err) + bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(3) + assert.Empty(t, err) + + nonce, err := ursa.NewNonce() + assert.Empty(t, err) + assert.NotEmpty(t, nonce) + + nonceBytes, err := nonce.ToJSON() + assert.Empty(t, err) + assert.NotEmpty(t, nonceBytes) + + blindedCommitment := createBlindedCommitment(t, *bbsPublicKey, nonceBytes, messages) + + unblindedSignature := createUnblindedSignature(t, *bbsPublicKey, HandleByteBuffer{blskp.SecretKey}, messages[0], 0, *blindedCommitment) + + verifyContext, err := VerifyContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, verifyContext) + + err = verifyContext.SetPublicKey(*bbsPublicKey) + assert.Empty(t, err) + + err = verifyContext.SetSignature(unblindedSignature) + assert.Empty(t, err) + + err = verifyContext.AddMessages([]string{"a message", "another message", "one more message"}) + assert.Empty(t, err) + + result, err := verifyContext.Finish() + assert.True(t, result) + assert.Empty(t, err) + }) + + t.Run("verify signature", func(t *testing.T) { + messages := []string{"a message", "another message", "one more message"} + blindSignContext, err := BlindSignContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, blindSignContext) + + blskp, err := GenerateBlsKey(data) + assert.Empty(t, err) + bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(3) + assert.Empty(t, err) + + signature := createSignature(t, *bbsPublicKey, HandleByteBuffer{blskp.SecretKey}, messages) + + verifyContext, err := VerifyContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, verifyContext) + + err = verifyContext.SetPublicKey(*bbsPublicKey) + assert.Empty(t, err) + + err = verifyContext.SetSignature(signature) + assert.Empty(t, err) + + err = verifyContext.AddMessages(messages) + assert.Empty(t, err) + + result, err := verifyContext.Finish() + assert.True(t, result) + assert.Empty(t, err) + }) +} + +func TestProofContext(t *testing.T) { + t.Run("ProofContextInit", func(t *testing.T) { + handle, err := ProofContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, handle.data) + }) + + t.Run("Full run of ProofContext", func(t *testing.T) { + data := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 21, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 31, 32} + messages := []string{"a message", "another message", "the third message", "the fourth message", "the last message"} + + blskp, err := GenerateBlsKey(data) + assert.Empty(t, err) + bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(5) + assert.Empty(t, err) + + signContext, err := SignContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, signContext) + + err = signContext.SetPublicKey(*bbsPublicKey) + assert.Empty(t, err) + + err = signContext.SetSecretKey(HandleByteBuffer{blskp.SecretKey}) + assert.Empty(t, err) + + err = signContext.AddMessages(messages) + assert.Empty(t, err) + + signature, err := signContext.Finish() + assert.Empty(t, err) + assert.NotEmpty(t, signature) + + nonce, err := ursa.NewNonce() + assert.Empty(t, err) + assert.NotEmpty(t, nonce) + + nonceBytes, err := nonce.ToJSON() + assert.Empty(t, err) + assert.NotEmpty(t, nonceBytes) + + blindCommitmentContext, err := BlindCommitmentContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, blindCommitmentContext.data) + + err = blindCommitmentContext.AddMessage(messages[0], 0) + assert.Empty(t, err) + assert.NotEmpty(t, blindCommitmentContext) + + err = blindCommitmentContext.SetPublicKey(*bbsPublicKey) + assert.Empty(t, err) + + err = blindCommitmentContext.SetNonce(nonceBytes) + assert.Empty(t, err) + + blindedCommitment, err := blindCommitmentContext.Finish() + assert.Empty(t, err) + + verifyContext, err := VerifyBlindCommitmentContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, verifyContext) + + err = verifyContext.AddBlinded(0) + assert.Empty(t, err) + + err = verifyContext.SetPublicKey(*bbsPublicKey) + assert.Empty(t, err) + + err = verifyContext.SetNonce(nonceBytes) + assert.NoError(t, err) + + err = verifyContext.SetProof(HandleByteBuffer{blindedCommitment.Context}) + assert.Empty(t, err) + + err = verifyContext.Finish() + assert.NoError(t, err) + + blindSignCtx, err := BlindSignContextInit() + assert.NoError(t, err) + + for i, message := range messages[1:] { + err := blindSignCtx.AddMessage(message, i+1) + assert.NoError(t, err) + } + + err = blindSignCtx.SetPublicKey(*bbsPublicKey) + assert.NoError(t, err) + + err = blindSignCtx.SetSecretKey(HandleByteBuffer{blskp.SecretKey}) + assert.NoError(t, err) + + err = blindSignCtx.SetCommitment(HandleByteBuffer{blindedCommitment.Commitment}) + assert.NoError(t, err) + + blindedSignature, err := blindSignCtx.Finish() + assert.NoError(t, err) + + unblindedSignature, err := blindedSignature.Unblind(HandleByteBuffer{blindedCommitment.BlindingFactor}) + assert.NoError(t, err) + + proofContext, err := ProofContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, proofContext.data) + + err = proofContext.AddProofMessages(messages[0:2], Revealed, HandleByteBuffer{blindedCommitment.BlindingFactor}) + assert.Empty(t, err) + + err = proofContext.AddProofMessages(messages[2:], HiddenProofSpecificBlinding, HandleByteBuffer{blindedCommitment.BlindingFactor}) + assert.Empty(t, err) + + err = proofContext.SetSignature(unblindedSignature) + assert.Empty(t, err) + + err = proofContext.SetPublicKey(*bbsPublicKey) + assert.Empty(t, err) + + err = proofContext.SetNonce(nonceBytes) + assert.NoError(t, err) + + proof, err := proofContext.Finish() + assert.NoError(t, err) + assert.NotEmpty(t, proof) + + verifyProofContext, err := VerifyProofContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, verifyProofContext) + + err = verifyProofContext.AddMessage(messages[0], 0) + assert.Empty(t, err) + + err = verifyProofContext.AddMessage(messages[1], 1) + assert.Empty(t, err) + + err = verifyProofContext.SetNonce(nonceBytes) + assert.Empty(t, err) + + err = verifyProofContext.SetPublicKey(*bbsPublicKey) + assert.Empty(t, err) + + err = verifyProofContext.SetProof(HandleByteBuffer{Buffer: proof.Buffer}) + assert.Empty(t, err) + + err = verifyProofContext.Finish() + assert.Empty(t, err) + + }) +} + +func createBlindedCommitment(t *testing.T, bbsPublicKey HandleByteBuffer, nonce []byte, messages []string) *BlindedCommitment { + blindCommitmentContext, err := BlindCommitmentContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, blindCommitmentContext.data) + + err = blindCommitmentContext.AddMessage(messages[0], 0) + assert.Empty(t, err) + assert.NotEmpty(t, blindCommitmentContext) + + err = blindCommitmentContext.SetPublicKey(bbsPublicKey) + assert.Empty(t, err) + + err = blindCommitmentContext.SetNonce(nonce) + assert.Empty(t, err) + + blindedCommitment, err := blindCommitmentContext.Finish() + assert.Empty(t, err) + + return blindedCommitment +} + +func createUnblindedSignature(t *testing.T, bbsPublicKey, secretKey HandleByteBuffer, message string, index int, blindedCommitment BlindedCommitment) *Signature { + blindSignContext, err := BlindSignContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, blindSignContext) + + err = blindSignContext.SetPublicKey(bbsPublicKey) + assert.Empty(t, err) + + err = blindSignContext.SetSecretKey(secretKey) + assert.Empty(t, err) + + err = blindSignContext.AddMessage(message, index) + assert.Empty(t, err) + assert.NotEmpty(t, blindSignContext) + + err = blindSignContext.SetCommitment(HandleByteBuffer{blindedCommitment.Commitment}) + assert.Empty(t, err) + assert.NotEmpty(t, blindSignContext) + + blindedSignature, err := blindSignContext.Finish() + assert.Empty(t, err) + assert.NotEmpty(t, blindedSignature) + + unblindedSignature, err := blindedSignature.Unblind(HandleByteBuffer{blindedCommitment.BlindingFactor}) + assert.Empty(t, err) + assert.NotEmpty(t, unblindedSignature) + + return unblindedSignature +} + +func createSignature(t *testing.T, bbsPublicKey HandleByteBuffer, secretKey HandleByteBuffer, messages []string) *Signature { + signContext, err := SignContextInit() + assert.Empty(t, err) + assert.NotEmpty(t, signContext.data) + + err = signContext.SetPublicKey(bbsPublicKey) + assert.Empty(t, err) + + err = signContext.SetSecretKey(secretKey) + assert.Empty(t, err) + + err = signContext.AddMessages(messages) + assert.Empty(t, err) + assert.NotEmpty(t, signContext) + + signature, err := signContext.Finish() + assert.Empty(t, err) + assert.NotEmpty(t, signature) + + return signature +} diff --git a/pkg/libzmix/bbs/libbbs.so b/pkg/libzmix/bbs/libbbs.so new file mode 100755 index 0000000..3f6c042 Binary files /dev/null and b/pkg/libzmix/bbs/libbbs.so differ