├── .gitignore ├── ursa-wrapper-go.sh ├── CODEOWNERS ├── go.mod ├── scripts └── test.sh ├── .github ├── PULL_REQUEST_TEMPLATE.md ├── ISSUE_TEMPLATE.md ├── settings.yml ├── workflows │ ├── release.yaml │ ├── Dockerfile │ └── build.yaml └── CONTRIBUTING.md ├── Makefile ├── pkg ├── libursa │ └── ursa │ │ ├── master_secret_test.go │ │ ├── master_secret.go │ │ ├── verifier.go │ │ ├── value_builder_test.go │ │ ├── credential_definition_test.go │ │ ├── verifier_test.go │ │ ├── proof_builder_test.go │ │ ├── proof_builder.go │ │ ├── value_builder.go │ │ ├── ursa_test.go │ │ ├── ursa.go │ │ └── ursa_cl.h └── libzmix │ └── bbs │ ├── bbs_cl.h │ ├── bbs_test.go │ └── bbs.go ├── MAINTAINERS.md ├── README.md ├── go.sum └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .idea/ 3 | coverage.txt 4 | *.out 5 | .vscode/ -------------------------------------------------------------------------------- /ursa-wrapper-go.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PWD=$(pwd) 4 | export URSA_GO_ROOT=$PWD 5 | export PATH=$PWD/bin:$PATH -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | * @hyperledger/ursa-maintainers @hyperledger/ursa-wrapper-go-maintainers 4 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/hyperledger/ursa-wrapper-go 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/stretchr/testify v1.6.1 7 | github.com/pkg/errors v0.9.1 8 | ) 9 | -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | echo "" >coverage.txt 5 | 6 | for d in $(go list ./pkg/... | grep -v vendor); do 7 | go test -race -coverprofile=profile.out -covermode=atomic $d 8 | if [ -f profile.out ]; then 9 | cat profile.out >>coverage.txt 10 | rm profile.out 11 | fi 12 | done 13 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Use the following template for your PR (make sure you follow our 2 | [guidelines](CONTRIBUTING.md#pull-request): 3 | 4 | **Title:** 5 | [Descriptive but using as few words as possible] 6 | 7 | **Description:** 8 | [Link to the GitHub issue it solves (if any)] 9 | 10 | Summary: 11 | 12 | [Include a brief summary of your changes] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Use the following template for your bug report 2 | (make sure you follow our [guidelines](CONTRIBUTING.md#bug-report): 3 | 4 | **What I'm trying to do** 5 | 6 | [Clearly describe what you're trying to do.] 7 | 8 | **Expected result** 9 | 10 | [Clearly describe the result you **expect**.] 11 | 12 | **Actual result** 13 | 14 | [Clearly describe the **actual** result you get.] 15 | 16 | **Sample code / test case** 17 | 18 | [Include a code sample that illustrates the test case.] 19 | -------------------------------------------------------------------------------- /.github/settings.yml: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-License-Identifier: Apache-2.0 3 | # 4 | 5 | repository: 6 | name: ursa-wrapper-go 7 | description: Hyperledger Ursa has moved to end-of-life status. 8 | homepage: https://wiki.hyperledger.org/display/ursa 9 | default_branch: main 10 | has_downloads: true 11 | has_issues: true 12 | has_projects: false 13 | has_wiki: false 14 | archived: true 15 | private: false 16 | allow_squash_merge: true 17 | allow_merge_commit: false 18 | allow_rebase_merge: true 19 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all: test 3 | 4 | .PHONY: test 5 | test: 6 | @scripts/test.sh 7 | 8 | .PHONY: ci-images 9 | ci-images: 10 | @cd .github/workflows/build && docker build -f Dockerfile.base-ursa -t m00sey/base-ursa:latest . 11 | @docker push m00sey/base-ursa:latest 12 | @cd .github/workflows/build && docker build -f Dockerfile.ursa_0.3.4 -t m00sey/ursa_0.3.4:latest . 13 | @docker push m00sey/ursa_0.3.4:latest 14 | @cd .github/workflows/build && docker build -f Dockerfile.ursa_0.3.2 -t m00sey/ursa_0.3.2:latest . 15 | @docker push m00sey/ursa_0.3.2:latest 16 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | # Sequence of patterns matched against refs/tags 4 | tags: 5 | - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 6 | 7 | name: Create Release 8 | 9 | jobs: 10 | build: 11 | name: Create Release 12 | runs-on: ubuntu-20.04 13 | steps: 14 | - name: Checkout code 15 | uses: actions/checkout@v2 16 | - name: Create Release 17 | id: create_release 18 | uses: actions/create-release@v1 19 | env: 20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 21 | with: 22 | tag_name: ${{ github.ref }} 23 | release_name: Release ${{ github.ref }} 24 | draft: false 25 | prerelease: false 26 | -------------------------------------------------------------------------------- /pkg/libursa/ursa/master_secret_test.go: -------------------------------------------------------------------------------- 1 | package ursa 2 | 3 | import ( 4 | "encoding/json" 5 | "math/big" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestMasterSecret(t *testing.T) { 12 | t.Run("happy path", func(t *testing.T) { 13 | ms, err := NewMasterSecret() 14 | assert.NoError(t, err) 15 | 16 | js, err := ms.ToJSON() 17 | assert.NoError(t, err) 18 | 19 | m := struct { 20 | MasterSecret string `json:"ms"` 21 | }{} 22 | err = json.Unmarshal(js, &m) 23 | assert.NoError(t, err) 24 | 25 | i := new(big.Int) 26 | _, ok := i.SetString(m.MasterSecret, 10) 27 | assert.True(t, ok) 28 | 29 | ms, err = MasterSecretFromJSON(js) 30 | assert.NoError(t, err) 31 | assert.NotEmpty(t, ms) 32 | 33 | err = ms.Free() 34 | assert.NoError(t, err) 35 | }) 36 | 37 | t.Run("bad json", func(t *testing.T) { 38 | ms, err := MasterSecretFromJSON([]byte(`{"t": "123"}`)) 39 | assert.Error(t, err) 40 | assert.Empty(t, ms) 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | Maintainers 2 | =========== 3 | 4 | **Active Maintainers** 5 | 6 | | Name | GitHub | Chat | 7 | |------|--------|----------------------------| 8 | | Alexander Shcherbakov | [ashcherbakov][ashcherbakov] | alexander.shcherbakov#5576 | 9 | | Konstantin Goncharov | [kgoncharov][kgoncharov] | | 10 | 11 | **Emeritus Maintainers** 12 | 13 | | Name | GitHub | Chat | 14 | |------|--------|----------------------------| 15 | | Kevin Griffin | [m00sey][m00sey] | | 16 | | Michael Lodder | [mikelodder7][mikelodder7] | | 17 | | Philip Feairheller | [pfeairheller][pfeairheller] | | 18 | | Sergey Minaev | [jovfer][jovfer] | | 19 | 20 | [m00sey]: https://github.com/m00sey 21 | [mikelodder7]: https://github.com/mikelodder7 22 | [pfeairheller]: https://github.com/pfeairheller 23 | [jovfer]: https://github.com/jovfer 24 | [kgoncharov]: https://github.com/kgoncharov 25 | [ashcherbakov]: https://github.com/ashcherbakov 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Release](https://img.shields.io/github/release/hyperledger/ursa-wrapper-go.svg?style=flat-square)](https://github.com/hyperledger/ursa-wrapper-go/releases/latest) 2 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://raw.githubusercontent.com/hyperledger/ursa-wrapper-go/main/LICENSE) 3 | [![Godocs](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/hyperledger/ursa-wrapper-go) 4 | 5 | [![codecov](https://codecov.io/gh/hyperledger/ursa-wrapper-go/branch/main/graph/badge.svg?token=dXh8Imy2PO)](https://codecov.io/gh/hyperledger/ursa-wrapper-go) 6 | [![Go Report Card](https://goreportcard.com/badge/github.com/hyperledger/ursa-wrapper-go)](https://goreportcard.com/report/github.com/hyperledger/ursa-wrapper-go) 7 | 8 | ## ursa-wrapper-go 9 | 10 | - Ursa Wrapper Go requires the [Ursa](https://github.com/hyperledger/ursa) shared library to be installed (eg: /usr/local/lib), and `ursa-wrapper-go.sh` to be sourced. 11 | 12 | ```shell script 13 | source ursa-wrapper-go.sh 14 | ``` 15 | 16 | #### Development 17 | - `make test` to run unit tests 18 | 19 | #### Requirements 20 | - Golang >= `1.14.4` and CGO enabled. -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 4 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 5 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 6 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 7 | github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= 8 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 9 | github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= 10 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 11 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 12 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 13 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 14 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 15 | -------------------------------------------------------------------------------- /pkg/libursa/ursa/master_secret.go: -------------------------------------------------------------------------------- 1 | package ursa 2 | 3 | /* 4 | #cgo LDFLAGS: -lursa 5 | #include "ursa_cl.h" 6 | #include 7 | */ 8 | import "C" 9 | import ( 10 | "unsafe" 11 | ) 12 | 13 | type MasterSecret Handle 14 | 15 | // NewMasterSecret creates a master secret 16 | func NewMasterSecret() (*MasterSecret, error) { 17 | var ms unsafe.Pointer 18 | 19 | result := C.ursa_cl_prover_new_master_secret(&ms) 20 | if result.code != 0 { 21 | return nil, ursaError(C.GoString(result.message)) 22 | } 23 | 24 | return &MasterSecret{ms}, nil 25 | } 26 | 27 | //MasterSecretFromJson creates and returns master secret from json 28 | func MasterSecretFromJSON(jsn []byte) (*MasterSecret, error) { 29 | var handle unsafe.Pointer 30 | cjson := C.CString(string(jsn)) 31 | defer C.free(unsafe.Pointer(cjson)) 32 | 33 | result := C.ursa_cl_master_secret_from_json(cjson, &handle) 34 | if result.code != 0 { 35 | return nil, ursaError(C.GoString(result.message)) 36 | } 37 | 38 | return &MasterSecret{handle}, nil 39 | } 40 | 41 | // ToJSON returns json representation of master secret 42 | func (r *MasterSecret) ToJSON() ([]byte, error) { 43 | var d *C.char 44 | defer C.free(unsafe.Pointer(d)) 45 | 46 | result := C.ursa_cl_master_secret_to_json(r.ptr, &d) 47 | if result.code != 0 { 48 | return nil, ursaError(C.GoString(result.message)) 49 | } 50 | 51 | out := []byte(C.GoString(d)) 52 | return out, nil 53 | } 54 | 55 | // Free deallocates master secret instance 56 | func (r *MasterSecret) Free() error { 57 | result := C.ursa_cl_master_secret_free(r.ptr) 58 | if result.code != 0 { 59 | return ursaError(C.GoString(result.message)) 60 | } 61 | 62 | return nil 63 | } 64 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | *We are still working on improving these guidelines.* 4 | 5 | Thank you for taking the time to contribute to `hyperledger/ursa-wrapper-go`! 6 | 7 | Contributing: 8 | * Submit a [bug report](#bug-report) 9 | * Submit a [pull request](#pull-request) 10 | 11 | ## Bug Report 12 | 13 | Did you find a bug? Be sure to set a clear and concise title. Do your best to 14 | include a code sample that illustrates the test case. Use the 15 | [template](ISSUE_TEMPLATE.md). 16 | 17 | ## Pull Request 18 | 19 | Use the [template](PULL_REQUEST_TEMPLATE.md) and make sure: 20 | 21 | * **Required:** The build must pass. 22 | * **Required:** Adherence to the [Developer Certificate of Origin 23 | (DCO)](https://developercertificate.org/) version 1.1 (`git --signoff`). 24 | * **Required:** *squash your commits*. Yes, we know - it's nice to be able to 25 | rollback every single change you make while troubleshooting or when requested to 26 | exclude a subset or your change. The problem is the project's history tends to 27 | become polluted with useless commit messages such as "removed trailing spaces". 28 | It also makes it harder to revert specific changes when they are spread out like 29 | this. We care about preserving our project's commit history in a usable state, 30 | and as such, we politely request that you deliver your changes in a single 31 | commit. 32 | * Number of lines changed should not exceed 500. We're reasonable people - if 33 | your PR is just a *little* over the top then we might still merge it. Such cases 34 | are exceptional and are handled on a case-by-case basis. 35 | 36 | The contents of this file are heavily "borrowed" from aries-framework-go, mainly because it is are good. -------------------------------------------------------------------------------- /.github/workflows/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright contributors to Hyperledger Ursa 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | FROM ubuntu:18.04 5 | 6 | ENV PATH /root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 7 | ENV SODIUM_LIB_DIR /usr/local/lib 8 | ENV SODIUM_INCLUDE_DIR /usr/local/include 9 | ENV LD_LIBRARY_PATH /usr/local/lib 10 | ARG DEBIAN_FRONTEND=noninteractive 11 | 12 | RUN apt-get update && apt-get dist-upgrade -y 13 | 14 | # Install dependencies and required tools 15 | RUN apt-get install -y \ 16 | git \ 17 | vim \ 18 | cmake \ 19 | sudo \ 20 | autoconf \ 21 | libtool \ 22 | curl \ 23 | python3 \ 24 | pkg-config \ 25 | libssl1.0.0 \ 26 | libssl-dev \ 27 | llvm \ 28 | llvm-dev \ 29 | clang 30 | 31 | WORKDIR /root 32 | 33 | RUN cd /usr/lib/x86_64-linux-gnu \ 34 | && ln -s libssl.so.1.0.0 libssl.so.10 \ 35 | && ln -s libcrypto.so.1.0.0 libcrypto.so.10 \ 36 | && curl -fsSL https://github.com/jedisct1/libsodium/archive/1.0.18.tar.gz | tar -xz \ 37 | && cd libsodium-1.0.18 \ 38 | && ./autogen.sh \ 39 | && ./configure \ 40 | && make install \ 41 | && cd .. \ 42 | && rm -rf libsodium-1.0.18 \ 43 | && curl https://sh.rustup.rs -sSf | sh -s -- -y \ 44 | && cargo install cargo-deb 45 | 46 | RUN git clone https://github.com/hyperledger/ursa.git \ 47 | && cd ursa \ 48 | && cd libursa \ 49 | && cargo build --release \ 50 | && cp target/release/*.so /usr/local/lib/ 51 | 52 | RUN git clone https://github.com/mattrglobal/ffi-bbs-signatures.git \ 53 | && cd ffi-bbs-signatures \ 54 | && git checkout 6fe88357938f144c43f67085b1c3c31b6656f39f \ 55 | && cargo build --release \ 56 | && cp target/release/libbbs.so /usr/local/lib/ 57 | 58 | RUN ldconfig 59 | -------------------------------------------------------------------------------- /pkg/libursa/ursa/verifier.go: -------------------------------------------------------------------------------- 1 | package ursa 2 | 3 | /* 4 | #cgo LDFLAGS: -lursa 5 | #include "ursa_cl.h" 6 | #include 7 | */ 8 | import "C" 9 | 10 | import ( 11 | "errors" 12 | "unsafe" 13 | ) 14 | 15 | type ProofVerifier Handle 16 | 17 | // NewProofVerifier creates and returns proof verifier. 18 | func NewProofVerifier() (*ProofVerifier, error) { 19 | var verifier unsafe.Pointer 20 | 21 | result := C.ursa_cl_verifier_new_proof_verifier(&verifier) 22 | if result.code != 0 { 23 | return nil, ursaError(C.GoString(result.message)) 24 | } 25 | 26 | return &ProofVerifier{verifier}, nil 27 | } 28 | 29 | // Verify verifies proof and deallocates proof verifier. 30 | func (r *ProofVerifier) Verify(proof *ProofHandle, nonce *Nonce) error { 31 | var verified C.bool 32 | 33 | result := C.ursa_cl_proof_verifier_verify(r.ptr, proof.ptr, nonce.ptr, &verified) 34 | if result.code != 0 { 35 | return ursaError(C.GoString(result.message)) 36 | } 37 | 38 | out := bool(verified) 39 | if !out { 40 | return errors.New("invalid proof") 41 | } 42 | 43 | return nil 44 | } 45 | 46 | // AddCommonAttribute add a common attribute to the proof verifier 47 | func (r *ProofVerifier) AddCommonAttribute(attr string) error { 48 | cattr := C.CString(attr) 49 | defer C.free(unsafe.Pointer(cattr)) 50 | 51 | result := C.ursa_cl_proof_verifier_add_common_attribute(r.ptr, cattr) 52 | if result.code != 0 { 53 | return ursaError(C.GoString(result.message)) 54 | } 55 | 56 | return nil 57 | } 58 | 59 | // AddSubProofRequest add a sub proof request to the proof verifier 60 | func (r *ProofVerifier) AddSubProofRequest(subProof *SubProofRequestHandle, credSchema *CredentialSchemaHandle, 61 | nonCredSchema *NonCredentialSchemaHandle, pubKey *CredentialDefPubKey) error { 62 | 63 | result := C.ursa_cl_proof_verifier_add_sub_proof_request(r.ptr, subProof.ptr, credSchema.ptr, nonCredSchema.ptr, 64 | pubKey.ptr /*revoc_reg*/, nil /*witness*/, nil) 65 | if result.code != 0 { 66 | return ursaError(C.GoString(result.message)) 67 | } 68 | 69 | return nil 70 | } 71 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: [ push, pull_request ] 3 | 4 | jobs: 5 | workflow-setup: 6 | runs-on: ubuntu-latest 7 | outputs: 8 | CACHE_KEY_IMAGE: ${{ steps.cache.outputs.CACHE_KEY_IMAGE }} 9 | steps: 10 | - name: Git checkout 11 | uses: actions/checkout@v2 12 | - name: Set outputs 13 | id: cache 14 | run: | 15 | echo "::set-output name=CACHE_KEY_IMAGE::${{ hashFiles('.github/workflows/Dockerfile') }}" 16 | 17 | build-image: 18 | needs: workflow-setup 19 | runs-on: ubuntu-latest 20 | env: 21 | DOCKER_BUILDKIT: 1 22 | CACHE_KEY_IMAGE: ${{ needs.workflow-setup.outputs.CACHE_KEY_IMAGE }} 23 | steps: 24 | - name: Git checkout 25 | uses: actions/checkout@v2 26 | - name: Try load from cache. 27 | id: cache-image 28 | uses: actions/cache@v2 29 | with: 30 | path: ${GITHUB_WORKSPACE}/cache 31 | key: ${{ env.CACHE_KEY_IMAGE}} 32 | - name: If NOT found in cache, build and push image. 33 | if: steps.cache-image.outputs.cache-hit != 'true' 34 | run: | 35 | echo ${{ secrets.CR_PAT }} | docker login ghcr.io --username ${{ secrets.CR_USER }} --password-stdin 36 | docker build -f .github/workflows/Dockerfile --no-cache -t ${GITHUB_REPOSITORY}/uwg-build:${{ env.CACHE_KEY_IMAGE }} . 37 | docker tag ${GITHUB_REPOSITORY}/uwg-build:${{ env.CACHE_KEY_IMAGE }} ghcr.io/${GITHUB_REPOSITORY}/uwg-build:latest 38 | docker push ghcr.io/${GITHUB_REPOSITORY}/uwg-build:latest 39 | mkdir -p ${GITHUB_WORKSPACE}/cache 40 | touch ${GITHUB_WORKSPACE}/cache/${{ env.CACHE_KEY_IMAGE }} 41 | 42 | test: 43 | name: Test using Ursa 44 | needs: build-image 45 | runs-on: ubuntu-20.04 46 | container: 47 | image: ghcr.io/${{ github.repository }}/uwg-build 48 | strategy: 49 | matrix: 50 | go-version: [1.14, 1.15] 51 | steps: 52 | - name: Set up Go ${{ matrix.go-version }} 53 | uses: actions/setup-go@v2 54 | with: 55 | go-version: ${{ matrix.go-version }} 56 | id: go 57 | 58 | - name: Check out code into the Go module directory 59 | uses: actions/checkout@v2 60 | 61 | - name: Test using Ursa ${{ matrix.ursa-version }} 62 | run: | 63 | make test 64 | -------------------------------------------------------------------------------- /pkg/libursa/ursa/value_builder_test.go: -------------------------------------------------------------------------------- 1 | package ursa 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestNewValueBuilder(t *testing.T) { 10 | t.Run("NewValueBuilder", func(t *testing.T) { 11 | builder, err := NewValueBuilder() 12 | assert.Empty(t, err) 13 | assert.NotEmpty(t, builder) 14 | 15 | err = builder.AddDecHidden("master_secret", "122345") 16 | assert.NoError(t, err) 17 | 18 | vals, err := builder.Finalize() 19 | assert.NoError(t, err) 20 | 21 | str, err := vals.ToJSON() 22 | assert.NoError(t, err) 23 | 24 | err = vals.Free() 25 | assert.NoError(t, err) 26 | 27 | newVals, err := CredentialValuesFromJSON(str) 28 | assert.NoError(t, err) 29 | assert.NotNil(t, newVals) 30 | }) 31 | } 32 | 33 | func TestAddDecHidden(t *testing.T) { 34 | t.Run("AddDecHidden", func(t *testing.T) { 35 | builder, _ := NewValueBuilder() 36 | 37 | err := builder.AddDecHidden("master_secret", "122345") 38 | assert.Empty(t, err) 39 | }) 40 | 41 | t.Run("AddDecHidden", func(t *testing.T) { 42 | builder, _ := NewValueBuilder() 43 | 44 | err := builder.AddDecHidden("master_secret", "fail") 45 | assert.NotEmpty(t, err) 46 | }) 47 | } 48 | 49 | func TestAddDecKnown(t *testing.T) { 50 | t.Run("AddDecKnown", func(t *testing.T) { 51 | builder, _ := NewValueBuilder() 52 | 53 | err := builder.AddDecKnown("master_secret", "12a2345") 54 | assert.Empty(t, err) 55 | }) 56 | 57 | t.Run("AddDecKnown", func(t *testing.T) { 58 | builder, _ := NewValueBuilder() 59 | 60 | err := builder.AddDecKnown("master_secret", "fail") 61 | assert.NotEmpty(t, err) 62 | }) 63 | } 64 | 65 | func TestAddDecCommitment(t *testing.T) { 66 | t.Run("AddDecCommitment", func(t *testing.T) { 67 | builder, _ := NewValueBuilder() 68 | 69 | err := builder.AddDecCommitment("master_secret", "12345", "9876") 70 | assert.Empty(t, err) 71 | }) 72 | 73 | t.Run("AddDecCommitment", func(t *testing.T) { 74 | builder, _ := NewValueBuilder() 75 | 76 | err := builder.AddDecCommitment("master_secret", "fail", "9876") 77 | assert.NotEmpty(t, err) 78 | }) 79 | } 80 | 81 | func TestFinalizeBuilder(t *testing.T) { 82 | t.Run("FinalizeBuilder", func(t *testing.T) { 83 | builder, _ := NewValueBuilder() 84 | 85 | values, err := builder.Finalize() 86 | assert.Empty(t, err) 87 | assert.NotEmpty(t, values) 88 | }) 89 | } 90 | -------------------------------------------------------------------------------- /pkg/libursa/ursa/credential_definition_test.go: -------------------------------------------------------------------------------- 1 | package ursa 2 | 3 | import ( 4 | "encoding/json" 5 | "math/big" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestCredentialDefinition(t *testing.T) { 12 | t.Run("happy path", func(t *testing.T) { 13 | fields := []string{"attr1", "attr2", "attr3"} 14 | var nonfields []string 15 | 16 | credDef := createCredentialDefinition(t, fields, nonfields) 17 | 18 | pubKeyJSON, err := credDef.PubKey.ToJSON() 19 | assert.NoError(t, err) 20 | m := map[string]interface{}{} 21 | err = json.Unmarshal(pubKeyJSON, &m) 22 | assert.NoError(t, err) 23 | 24 | pkey, ok := m["p_key"].(map[string]interface{}) 25 | assert.True(t, ok) 26 | 27 | r, ok := pkey["r"].(map[string]interface{}) 28 | assert.True(t, ok) 29 | 30 | for _, field := range fields { 31 | x, ok := r[field].(string) 32 | assert.True(t, ok) 33 | i := new(big.Int) 34 | _, ok = i.SetString(x, 10) 35 | assert.True(t, ok) 36 | } 37 | 38 | privKeyJSON, err := credDef.PrivKey.ToJSON() 39 | assert.NoError(t, err) 40 | assert.NotEmpty(t, privKeyJSON) 41 | 42 | correctnessJSON, err := credDef.PubKey.ToJSON() 43 | assert.NoError(t, err) 44 | 45 | m = map[string]interface{}{} 46 | err = json.Unmarshal(correctnessJSON, &m) 47 | assert.NoError(t, err) 48 | 49 | pkey, ok = m["p_key"].(map[string]interface{}) 50 | assert.True(t, ok) 51 | 52 | r, ok = pkey["r"].(map[string]interface{}) 53 | assert.True(t, ok) 54 | 55 | for _, field := range fields { 56 | x, ok := r[field].(string) 57 | assert.True(t, ok) 58 | i := new(big.Int) 59 | _, ok = i.SetString(x, 10) 60 | assert.True(t, ok) 61 | } 62 | 63 | err = credDef.PubKey.Free() 64 | assert.NoError(t, err) 65 | 66 | err = credDef.PrivKey.Free() 67 | assert.NoError(t, err) 68 | 69 | err = credDef.KeyCorrectnessProof.Free() 70 | assert.NoError(t, err) 71 | }) 72 | } 73 | 74 | func createCredentialDefinition(t *testing.T, fields, nonfields []string) *CredentialDef { 75 | 76 | fields = append(fields, "master_secret") 77 | 78 | schema := createSchema(t, fields) 79 | 80 | nonschema := createNonSchema(t, nonfields) 81 | 82 | credDef, err := NewCredentialDef(schema, nonschema, false) 83 | assert.NoError(t, err) 84 | 85 | return credDef 86 | } 87 | 88 | func createSchema(t *testing.T, fields []string) *CredentialSchemaHandle { 89 | schemaBuilder, err := NewCredentialSchemaBuilder() 90 | assert.NoError(t, err) 91 | 92 | for _, field := range fields { 93 | err = schemaBuilder.AddAttr(field) 94 | assert.NoError(t, err) 95 | } 96 | 97 | schema, err := schemaBuilder.Finalize() 98 | assert.NoError(t, err) 99 | 100 | return schema 101 | } 102 | 103 | func createNonSchema(t *testing.T, fields []string) *NonCredentialSchemaHandle { 104 | nonSchemaBuilder, err := NewNonCredentialSchemaBuilder() 105 | assert.NoError(t, err) 106 | 107 | for _, field := range fields { 108 | err = nonSchemaBuilder.AddAttr(field) 109 | assert.NoError(t, err) 110 | } 111 | 112 | nonSchema, err := nonSchemaBuilder.Finalize() 113 | assert.NoError(t, err) 114 | 115 | return nonSchema 116 | } 117 | 118 | func createValues(t *testing.T, values map[string]interface{}) *CredentialValues { 119 | builder, err := NewValueBuilder() 120 | assert.NoError(t, err) 121 | 122 | for k, v := range values { 123 | _, enc := EncodeValue(v) 124 | err = builder.AddDecKnown(k, enc) 125 | assert.NoError(t, err) 126 | } 127 | 128 | value, err := builder.Finalize() 129 | assert.NoError(t, err) 130 | 131 | return value 132 | } 133 | -------------------------------------------------------------------------------- /pkg/libursa/ursa/verifier_test.go: -------------------------------------------------------------------------------- 1 | package ursa 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestVerifierVerify(t *testing.T) { 11 | t.Run("happy path from existing proof", func(t *testing.T) { 12 | schemaBuilder, err := NewCredentialSchemaBuilder() 13 | assert.NoError(t, err) 14 | err = schemaBuilder.AddAttr("sex") 15 | assert.NoError(t, err) 16 | schema, err := schemaBuilder.Finalize() 17 | assert.NoError(t, err) 18 | 19 | nonSchemaBuilder, err := NewNonCredentialSchemaBuilder() 20 | assert.NoError(t, err) 21 | err = nonSchemaBuilder.AddAttr("master_secret") 22 | assert.NoError(t, err) 23 | nonSchema, err := nonSchemaBuilder.Finalize() 24 | 25 | credDef, err := NewCredentialDef(schema, nonSchema, false) 26 | assert.NoError(t, err) 27 | assert.NotNil(t, credDef) 28 | 29 | masterSecret, err := NewMasterSecret() 30 | assert.NoError(t, err) 31 | js, err := masterSecret.ToJSON() 32 | assert.NoError(t, err) 33 | m := struct { 34 | MS string `json:"ms"` 35 | }{} 36 | err = json.Unmarshal(js, &m) 37 | assert.NoError(t, err) 38 | 39 | valuesBuilder, err := NewValueBuilder() 40 | assert.NoError(t, err) 41 | err = valuesBuilder.AddDecHidden("master_secret", m.MS) 42 | assert.NoError(t, err) 43 | err = valuesBuilder.AddDecKnown("sex", "5944657099558967239210949258394887428692050081607692519917050011144233115103") 44 | assert.NoError(t, err) 45 | 46 | values, err := valuesBuilder.Finalize() 47 | assert.NoError(t, err) 48 | 49 | credentialNonce, err := NewNonce() 50 | assert.NoError(t, err) 51 | 52 | blindedSecrets, err := BlindCredentialSecrets(credDef.PubKey, credDef.KeyCorrectnessProof, credentialNonce, values) 53 | assert.NoError(t, err) 54 | 55 | credentialIssuanceNonce, err := NewNonce() 56 | assert.NoError(t, err) 57 | 58 | p := SignatureParams{ 59 | ProverID: "CnEDk9HrMnmiHXEV1WFgbVCRteYnPqsJwrTdcZaNhFVW", 60 | BlindedCredentialSecrets: blindedSecrets.Handle, 61 | BlindedCredentialSecretsCorrectnessProof: blindedSecrets.CorrectnessProof, 62 | CredentialIssuanceNonce: credentialIssuanceNonce, 63 | CredentialNonce: credentialNonce, 64 | CredentialValues: values, 65 | CredentialPubKey: credDef.PubKey, 66 | CredentialPrivKey: credDef.PrivKey, 67 | } 68 | 69 | credSig, credSigKP, err := p.SignCredential() 70 | assert.NoError(t, err) 71 | 72 | err = credSig.ProcessCredentialSignature(values, credSigKP, blindedSecrets.BlindingFactor, credDef.PubKey, credentialIssuanceNonce) 73 | assert.NoError(t, err) 74 | 75 | subProofBuilder, err := NewSubProofRequestBuilder() 76 | assert.NoError(t, err) 77 | err = subProofBuilder.AddRevealedAttr("sex") 78 | assert.NoError(t, err) 79 | subProofRequest, err := subProofBuilder.Finalize() 80 | assert.NoError(t, err) 81 | 82 | proofBuilder, err := NewProofBuilder() 83 | assert.NoError(t, err) 84 | err = proofBuilder.AddCommonAttribute("master_secret") 85 | assert.NoError(t, err) 86 | err = proofBuilder.AddSubProofRequest(subProofRequest, schema, nonSchema, credSig, values, credDef.PubKey) 87 | assert.NoError(t, err) 88 | 89 | proofRequestNonce, err := NewNonce() 90 | assert.NoError(t, err) 91 | 92 | proof, err := proofBuilder.Finalize(proofRequestNonce) 93 | assert.NoError(t, err) 94 | 95 | verifier, err := NewProofVerifier() 96 | assert.NoError(t, err) 97 | 98 | err = verifier.AddSubProofRequest(subProofRequest, schema, nonSchema, credDef.PubKey) 99 | assert.NoError(t, err) 100 | 101 | err = verifier.Verify(proof, proofRequestNonce) 102 | assert.NoError(t, err) 103 | }) 104 | } 105 | -------------------------------------------------------------------------------- /pkg/libursa/ursa/proof_builder_test.go: -------------------------------------------------------------------------------- 1 | package ursa 2 | 3 | import ( 4 | "encoding/json" 5 | "math/big" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestProofBuilder(t *testing.T) { 12 | t.Run("basic proof builder", func(t *testing.T) { 13 | pb, err := NewProofBuilder() 14 | assert.NoError(t, err) 15 | 16 | err = pb.AddCommonAttribute("master_secret") 17 | assert.NoError(t, err) 18 | 19 | nonce, err := NewNonce() 20 | assert.NoError(t, err) 21 | 22 | proof, err := pb.Finalize(nonce) 23 | assert.NoError(t, err) 24 | 25 | str, err := proof.ToJSON() 26 | assert.NoError(t, err) 27 | 28 | err = nonce.Free() 29 | assert.NoError(t, err) 30 | 31 | err = proof.Free() 32 | assert.NoError(t, err) 33 | 34 | newProof, err := ProofFromJSON(str) 35 | assert.NoError(t, err) 36 | assert.NotNil(t, newProof) 37 | 38 | }) 39 | 40 | t.Run("with sub proof request", func(t *testing.T) { 41 | fields := []string{"attr1", "attr2", "attr3"} 42 | vals := map[string]interface{}{ 43 | "attr1": "val1", 44 | "attr2": "val2", 45 | "attr3": "val3", 46 | } 47 | 48 | pb, err := NewProofBuilder() 49 | assert.NoError(t, err) 50 | 51 | err = pb.AddCommonAttribute("attr1") 52 | assert.NoError(t, err) 53 | 54 | subProofBuilder, err := NewSubProofRequestBuilder() 55 | assert.NoError(t, err) 56 | 57 | for _, field := range fields { 58 | err = subProofBuilder.AddRevealedAttr(field) 59 | assert.NoError(t, err) 60 | } 61 | 62 | subProof, err := subProofBuilder.Finalize() 63 | 64 | schema := createSchema(t, fields) 65 | 66 | var nonSchemaFields []string 67 | nonSchema := createNonSchema(t, nonSchemaFields) 68 | 69 | credDef, err := NewCredentialDef(schema, nonSchema, false) 70 | assert.NoError(t, err) 71 | 72 | values := createValues(t, vals) 73 | sig, _ := createSignature(t, fields, vals) 74 | 75 | err = pb.AddSubProofRequest(subProof, schema, nonSchema, sig, values, credDef.PubKey) 76 | assert.NoError(t, err) 77 | 78 | nonce, err := NewNonce() 79 | assert.NoError(t, err) 80 | 81 | proof, err := pb.Finalize(nonce) 82 | assert.NoError(t, err) 83 | 84 | str, err := proof.ToJSON() 85 | assert.NoError(t, err) 86 | 87 | result := map[string]interface{}{} 88 | err = json.Unmarshal(str, &result) 89 | assert.NoError(t, err) 90 | 91 | proofs, ok := result["proofs"].([]interface{}) 92 | assert.True(t, ok) 93 | 94 | pp, ok := proofs[0].(map[string]interface{}) 95 | assert.True(t, ok) 96 | 97 | primary, ok := pp["primary_proof"].(map[string]interface{}) 98 | assert.True(t, ok) 99 | 100 | eq, ok := primary["eq_proof"].(map[string]interface{}) 101 | assert.True(t, ok) 102 | 103 | revealed, ok := eq["revealed_attrs"].(map[string]interface{}) 104 | assert.True(t, ok) 105 | 106 | for _, field := range fields { 107 | x, ok := revealed[field].(string) 108 | assert.True(t, ok) 109 | i := new(big.Int) 110 | _, ok = i.SetString(x, 10) 111 | assert.True(t, ok) 112 | } 113 | 114 | err = nonce.Free() 115 | assert.NoError(t, err) 116 | 117 | err = subProof.Free() 118 | assert.NoError(t, err) 119 | 120 | newProof, err := ProofFromJSON(str) 121 | assert.NoError(t, err) 122 | assert.NotNil(t, newProof) 123 | 124 | err = values.Free() 125 | assert.NoError(t, err) 126 | 127 | }) 128 | } 129 | 130 | func TestSubProofRequest(t *testing.T) { 131 | t.Run("basic subproof", func(t *testing.T) { 132 | builder, err := NewSubProofRequestBuilder() 133 | assert.NoError(t, err) 134 | 135 | err = builder.AddRevealedAttr("name") 136 | assert.NoError(t, err) 137 | 138 | proof, err := builder.Finalize() 139 | assert.NoError(t, err) 140 | assert.NotNil(t, proof) 141 | 142 | err = proof.Free() 143 | assert.NoError(t, err) 144 | }) 145 | } 146 | -------------------------------------------------------------------------------- /pkg/libursa/ursa/proof_builder.go: -------------------------------------------------------------------------------- 1 | package ursa 2 | 3 | /* 4 | #cgo LDFLAGS: -lursa 5 | #include "ursa_cl.h" 6 | #include 7 | */ 8 | import "C" 9 | import ( 10 | "unsafe" 11 | ) 12 | 13 | type ProofBuilder Handle 14 | type ProofHandle Handle 15 | 16 | // NewProofBuilder 17 | func NewProofBuilder() (*ProofBuilder, error) { 18 | var builder unsafe.Pointer 19 | 20 | result := C.ursa_cl_prover_new_proof_builder(&builder) 21 | if result.code != 0 { 22 | return nil, ursaError(C.GoString(result.message)) 23 | } 24 | 25 | return &ProofBuilder{builder}, nil 26 | } 27 | 28 | // ProofFromJSON creates and returns proof from JSON 29 | func ProofFromJSON(jsn []byte) (*ProofHandle, error) { 30 | var builder unsafe.Pointer 31 | cjson := C.CString(string(jsn)) 32 | defer C.free(unsafe.Pointer(cjson)) 33 | 34 | result := C.ursa_cl_proof_from_json(cjson, &builder) 35 | if result.code != 0 { 36 | return nil, ursaError(C.GoString(result.message)) 37 | } 38 | 39 | return &ProofHandle{builder}, nil 40 | } 41 | 42 | // AddCommonAttribute add a common attribute to the proof builder 43 | func (r *ProofBuilder) AddCommonAttribute(attr string) error { 44 | cattr := C.CString(attr) 45 | defer C.free(unsafe.Pointer(cattr)) 46 | 47 | result := C.ursa_cl_proof_builder_add_common_attribute(r.ptr, cattr) 48 | if result.code != 0 { 49 | return ursaError(C.GoString(result.message)) 50 | } 51 | 52 | return nil 53 | } 54 | 55 | // AddSubProofRequest add a sub proof request to the proof builder 56 | func (r *ProofBuilder) AddSubProofRequest(subProof *SubProofRequestHandle, credSchema *CredentialSchemaHandle, 57 | nonCredSchema *NonCredentialSchemaHandle, signature *CredentialSignature, values *CredentialValues, pubKey *CredentialDefPubKey) error { 58 | 59 | result := C.ursa_cl_proof_builder_add_sub_proof_request(r.ptr, subProof.ptr, credSchema.ptr, nonCredSchema.ptr, 60 | signature.ptr, values.ptr, pubKey.ptr /*revoc_reg*/, nil /*witness*/, nil) 61 | if result.code != 0 { 62 | return ursaError(C.GoString(result.message)) 63 | } 64 | 65 | return nil 66 | } 67 | 68 | // Finalize finalize the proof 69 | func (r *ProofBuilder) Finalize(nonce *Nonce) (*ProofHandle, error) { 70 | var proof unsafe.Pointer 71 | 72 | result := C.ursa_cl_proof_builder_finalize(r.ptr, nonce.ptr, &proof) 73 | if result.code != 0 { 74 | return nil, ursaError(C.GoString(result.message)) 75 | } 76 | 77 | return &ProofHandle{proof}, nil 78 | } 79 | 80 | // ToJSON returns JSON representation of proof 81 | func (r *ProofHandle) ToJSON() ([]byte, error) { 82 | var d *C.char 83 | defer C.free(unsafe.Pointer(d)) 84 | 85 | result := C.ursa_cl_proof_to_json(r.ptr, &d) 86 | if result.code != 0 { 87 | return nil, ursaError(C.GoString(result.message)) 88 | } 89 | 90 | return []byte(C.GoString(d)), nil 91 | } 92 | 93 | // Free deallocates proof instance 94 | func (r *ProofHandle) Free() error { 95 | result := C.ursa_cl_proof_free(r.ptr) 96 | if result.code != 0 { 97 | return ursaError(C.GoString(result.message)) 98 | } 99 | 100 | return nil 101 | } 102 | 103 | type SubProofRequestBuilder Handle 104 | type SubProofRequestHandle Handle 105 | 106 | // NewSubProofRequestBuilder creates and returns sub proof request entity builder 107 | func NewSubProofRequestBuilder() (*SubProofRequestBuilder, error) { 108 | var builder unsafe.Pointer 109 | 110 | result := C.ursa_cl_sub_proof_request_builder_new(&builder) 111 | if result.code != 0 { 112 | return nil, ursaError(C.GoString(result.message)) 113 | } 114 | 115 | return &SubProofRequestBuilder{builder}, nil 116 | 117 | } 118 | 119 | // AddPredicate adds predicate to sub proof request 120 | func (r *SubProofRequestBuilder) AddPredicate(attr, ptype string, value int32) error { 121 | cattr := C.CString(attr) 122 | defer C.free(unsafe.Pointer(cattr)) 123 | cptype := C.CString(ptype) 124 | defer C.free(unsafe.Pointer(cptype)) 125 | 126 | result := C.ursa_cl_sub_proof_request_builder_add_predicate(r.ptr, cattr, cptype, C.int32_t(value)) 127 | if result.code != 0 { 128 | return ursaError(C.GoString(result.message)) 129 | } 130 | 131 | return nil 132 | } 133 | 134 | // AddRevealedAttr adds new revealed attribute to sub proof request. 135 | func (r *SubProofRequestBuilder) AddRevealedAttr(attr string) error { 136 | cattr := C.CString(attr) 137 | defer C.free(unsafe.Pointer(cattr)) 138 | 139 | result := C.ursa_cl_sub_proof_request_builder_add_revealed_attr(r.ptr, cattr) 140 | if result.code != 0 { 141 | return ursaError(C.GoString(result.message)) 142 | } 143 | 144 | return nil 145 | } 146 | 147 | // Finalize deallocates sub proof request builder and returns sub proof request entity instead. 148 | func (r *SubProofRequestBuilder) Finalize() (*SubProofRequestHandle, error) { 149 | var proof unsafe.Pointer 150 | 151 | result := C.ursa_cl_sub_proof_request_builder_finalize(r.ptr, &proof) 152 | if result.code != 0 { 153 | return nil, ursaError(C.GoString(result.message)) 154 | } 155 | 156 | return &SubProofRequestHandle{proof}, nil 157 | } 158 | 159 | // Free deallocates sub proof request instance 160 | func (r *SubProofRequestHandle) Free() error { 161 | result := C.ursa_cl_sub_proof_request_free(r.ptr) 162 | if result.code != 0 { 163 | return ursaError(C.GoString(result.message)) 164 | } 165 | 166 | return nil 167 | } 168 | -------------------------------------------------------------------------------- /pkg/libursa/ursa/value_builder.go: -------------------------------------------------------------------------------- 1 | package ursa 2 | 3 | /* 4 | #cgo LDFLAGS: -lursa 5 | #include "ursa_cl.h" 6 | #include 7 | */ 8 | import "C" 9 | import ( 10 | "crypto/sha256" 11 | "fmt" 12 | "math" 13 | "math/big" 14 | "strconv" 15 | "unsafe" 16 | ) 17 | 18 | type CredentialValuesBuilder Handle 19 | type CredentialValues Handle 20 | 21 | // NewValueBuilder creates and returns credentials values entity builder 22 | func NewValueBuilder() (*CredentialValuesBuilder, error) { 23 | var builder unsafe.Pointer 24 | 25 | result := C.ursa_cl_credential_values_builder_new(&builder) 26 | if result.code != 0 { 27 | return nil, ursaError(C.GoString(result.message)) 28 | } 29 | 30 | return &CredentialValuesBuilder{builder}, nil 31 | } 32 | 33 | // CredentialValuesFromJSON creates and returns credential values from JSON 34 | func CredentialValuesFromJSON(jsn []byte) (*CredentialValues, error) { 35 | var ptr unsafe.Pointer 36 | cjson := C.CString(string(jsn)) 37 | defer C.free(unsafe.Pointer(cjson)) 38 | 39 | result := C.ursa_cl_credential_values_from_json(cjson, &ptr) 40 | if result.code != 0 { 41 | return nil, ursaError(C.GoString(result.message)) 42 | } 43 | 44 | return &CredentialValues{ptr}, nil 45 | } 46 | 47 | // AddDecHidden adds new hidden attribute dec_value to credential values map 48 | func (r *CredentialValuesBuilder) AddDecHidden(attr, decValue string) error { 49 | cattr := C.CString(attr) 50 | defer C.free(unsafe.Pointer(cattr)) 51 | 52 | cval := C.CString(decValue) 53 | defer C.free(unsafe.Pointer(cval)) 54 | 55 | result := C.ursa_cl_credential_values_builder_add_dec_hidden(r.ptr, cattr, cval) 56 | if result.code != 0 { 57 | return ursaError(C.GoString(result.message)) 58 | } 59 | 60 | return nil 61 | } 62 | 63 | // AddDecKnown adds new known attribute dec_value to credential values map 64 | func (r *CredentialValuesBuilder) AddDecKnown(attr, decValue string) error { 65 | cattr := C.CString(attr) 66 | defer C.free(unsafe.Pointer(cattr)) 67 | 68 | cval := C.CString(decValue) 69 | defer C.free(unsafe.Pointer(cval)) 70 | 71 | result := C.ursa_cl_credential_values_builder_add_dec_known(r.ptr, cattr, cval) 72 | if result.code != 0 { 73 | return ursaError(C.GoString(result.message)) 74 | } 75 | 76 | return nil 77 | } 78 | 79 | // AddDecCommitment adds new hidden attribute dec_value to credential values map 80 | func (r *CredentialValuesBuilder) AddDecCommitment(attr, decValue, decBlindingFactor string) error { 81 | cattr := C.CString(attr) 82 | defer C.free(unsafe.Pointer(cattr)) 83 | cval := C.CString(decValue) 84 | defer C.free(unsafe.Pointer(cval)) 85 | cfac := C.CString(decBlindingFactor) 86 | defer C.free(unsafe.Pointer(cfac)) 87 | 88 | result := C.ursa_cl_credential_values_builder_add_dec_commitment(r.ptr, cattr, cval, cfac) 89 | if result.code != 0 { 90 | return ursaError(C.GoString(result.message)) 91 | } 92 | 93 | return nil 94 | } 95 | 96 | // Finalize deallocates credential values builder and returns credential values entity instead 97 | func (r *CredentialValuesBuilder) Finalize() (*CredentialValues, error) { 98 | var values unsafe.Pointer 99 | result := C.ursa_cl_credential_values_builder_finalize(r.ptr, &values) 100 | if result.code != 0 { 101 | return nil, ursaError(C.GoString(result.message)) 102 | } 103 | 104 | return &CredentialValues{values}, nil 105 | } 106 | 107 | // Free deallocates credential values instance 108 | func (r *CredentialValues) Free() error { 109 | result := C.ursa_cl_credential_values_free(r.ptr) 110 | if result.code != 0 { 111 | return ursaError(C.GoString(result.message)) 112 | } 113 | 114 | return nil 115 | } 116 | 117 | // ToJSON returns JSON representation of credential values 118 | func (r *CredentialValues) ToJSON() ([]byte, error) { 119 | var d *C.char 120 | defer C.free(unsafe.Pointer(d)) 121 | 122 | result := C.ursa_cl_credential_values_to_json(r.ptr, &d) 123 | if result.code != 0 { 124 | return nil, ursaError(C.GoString(result.message)) 125 | } 126 | 127 | return []byte(C.GoString(d)), nil 128 | } 129 | 130 | // EncodeValue encodes any value into decimal representation 131 | func EncodeValue(val interface{}) (string, string) { 132 | var raw, enc string 133 | 134 | switch v := val.(type) { 135 | case nil: 136 | raw = "None" 137 | enc = ToEncodedNumber(raw) 138 | case string: 139 | raw = v 140 | i, err := strconv.Atoi(v) 141 | if err == nil && (i <= math.MaxInt32 && i >= math.MinInt32) { 142 | enc = v 143 | } else { 144 | enc = ToEncodedNumber(v) 145 | } 146 | case bool: 147 | if v { 148 | raw = "True" 149 | enc = "1" 150 | } else { 151 | raw = "Fase" 152 | enc = "0" 153 | } 154 | case int32: 155 | raw = strconv.Itoa(int(v)) 156 | enc = raw 157 | case int64: 158 | if v <= math.MaxInt32 && v >= math.MinInt32 { 159 | raw = strconv.Itoa(int(v)) 160 | enc = raw 161 | } else { 162 | raw = strconv.Itoa(int(v)) 163 | enc = ToEncodedNumber(raw) 164 | } 165 | case int: 166 | if v <= math.MaxInt32 && v >= math.MinInt32 { 167 | raw = strconv.Itoa(v) 168 | enc = raw 169 | } else { 170 | raw = strconv.Itoa(v) 171 | enc = ToEncodedNumber(raw) 172 | } 173 | case float64: 174 | if v == 0 { 175 | raw = "0.0" 176 | enc = ToEncodedNumber(raw) 177 | } else { 178 | raw = fmt.Sprintf("%f", v) 179 | enc = ToEncodedNumber(raw) 180 | } 181 | default: 182 | //Not sure what to do with Go and unknown types... this works for now 183 | raw = fmt.Sprintf("%v", v) 184 | enc = ToEncodedNumber(raw) 185 | } 186 | 187 | return raw, enc 188 | } 189 | 190 | // ToEncodedNumber encodes string to decimal encoded value 191 | func ToEncodedNumber(raw string) string { 192 | b := []byte(raw) 193 | hasher := sha256.New() 194 | hasher.Write(b) 195 | 196 | sh := hasher.Sum(nil) 197 | i := new(big.Int) 198 | i.SetBytes(sh) 199 | 200 | return i.String() 201 | } 202 | -------------------------------------------------------------------------------- /pkg/libzmix/bbs/bbs_cl.h: -------------------------------------------------------------------------------- 1 | #ifndef __bbs__plus__included__ 2 | #define __bbs__plus__included__ 3 | 4 | #include 5 | 6 | /* Used for receiving a ByteBuffer from C that was allocated by either C or Rust. 7 | * If Rust allocated, then the outgoing struct is `ffi_support::ByteBuffer` 8 | * Caller is responsible for calling free where applicable. 9 | */ 10 | typedef struct { 11 | int64_t len; 12 | uint8_t *data; 13 | } ByteBuffer; 14 | 15 | typedef struct { 16 | int32_t code; 17 | char* message; /* note: nullable */ 18 | } ExternError; 19 | 20 | typedef enum { 21 | Revealed = 1, 22 | HiddenProofSpecificBlinding = 2, 23 | HiddenExternalBlinding = 3, 24 | } proof_message_t; 25 | 26 | typedef enum { 27 | /* The proof verified */ 28 | Success = 200, 29 | /* The proof failed because the signature proof of knowledge failed */ 30 | BadSignature = 400, 31 | /* The proof failed because a hidden message was invalid when the proof was created */ 32 | BadHiddenMessage = 401, 33 | /* The proof failed because a revealed message was invalid */ 34 | BadRevealedMessage = 402, 35 | } signature_proof_status; 36 | 37 | #ifdef __cplusplus 38 | extern "C" { 39 | #endif 40 | 41 | void bbs_string_free(char* string); 42 | void bbs_byte_buffer_free(ByteBuffer data); 43 | 44 | uint64_t bbs_blind_commitment_context_init(ExternError *err); 45 | 46 | int32_t bbs_blind_commitment_context_finish(uint64_t handle, 47 | ByteBuffer *commitment, 48 | ByteBuffer *out_context, 49 | ByteBuffer *blinding_factor, 50 | ExternError *err); 51 | 52 | int32_t bbs_blind_commitment_context_add_message_bytes(uint64_t handle, 53 | uint32_t index, 54 | ByteBuffer message, 55 | ExternError *err); 56 | 57 | int32_t bbs_blind_commitment_context_set_public_key(uint64_t handle, 58 | ByteBuffer public_key, 59 | ExternError *err); 60 | 61 | int32_t bbs_blind_commitment_context_set_nonce_bytes(uint64_t handle, 62 | ByteBuffer message, 63 | ExternError *err); 64 | 65 | 66 | int32_t bbs_blind_sign_context_finish(uint64_t handle, 67 | ByteBuffer *blinded_signature, 68 | ExternError *err); 69 | 70 | int32_t bbs_blind_sign_context_add_message_bytes(uint64_t handle, 71 | uint32_t index, 72 | ByteBuffer message, 73 | ExternError *err); 74 | 75 | int32_t bbs_blind_sign_context_set_secret_key(uint64_t handle, 76 | ByteBuffer secret_key, 77 | ExternError *err); 78 | 79 | int32_t bbs_blind_sign_context_set_public_key(uint64_t handle, 80 | ByteBuffer public_key, 81 | ExternError *err); 82 | 83 | int32_t bbs_blind_sign_context_set_commitment(uint64_t handle, 84 | ByteBuffer commitment, 85 | ExternError *err); 86 | 87 | uint64_t bbs_blind_sign_context_init(ExternError *err); 88 | 89 | int32_t bbs_blind_signature_size(void); 90 | 91 | int32_t bbs_unblind_signature(ByteBuffer blind_signature, 92 | ByteBuffer blinding_factor, 93 | ByteBuffer *unblind_signature, 94 | ExternError *err); 95 | 96 | int32_t bbs_create_proof_context_finish(uint64_t handle, ByteBuffer *proof, ExternError *err); 97 | 98 | int32_t bbs_create_proof_context_set_public_key(uint64_t handle, 99 | ByteBuffer public_key, 100 | ExternError *err); 101 | 102 | int32_t bbs_create_proof_context_set_signature(uint64_t handle, 103 | ByteBuffer signature , 104 | ExternError *err); 105 | 106 | int32_t bbs_create_proof_context_set_nonce_bytes(uint64_t handle, 107 | ByteBuffer message, 108 | ExternError *err); 109 | 110 | int32_t bbs_create_proof_context_add_proof_message_bytes(uint64_t handle, 111 | ByteBuffer message, 112 | proof_message_t xtype, 113 | ByteBuffer blinding_factor, 114 | ExternError *err); 115 | 116 | uint64_t bbs_create_proof_context_init(ExternError *err); 117 | 118 | int32_t bbs_sign_context_add_message_bytes(uint64_t handle, 119 | ByteBuffer message, 120 | ExternError *err); 121 | 122 | int32_t bbs_sign_context_set_secret_key(uint64_t handle, 123 | ByteBuffer secret_key, 124 | ExternError *err); 125 | 126 | int32_t bbs_sign_context_set_public_key(uint64_t handle, 127 | ByteBuffer public_key, 128 | ExternError *err); 129 | 130 | int32_t bbs_sign_context_finish(uint64_t handle, ByteBuffer *signature, ExternError *err); 131 | 132 | uint64_t bbs_sign_context_init(ExternError *err); 133 | 134 | int32_t bbs_signature_size(void); 135 | 136 | int32_t bbs_verify_context_add_message_bytes(uint64_t handle, 137 | ByteBuffer message, 138 | ExternError *err); 139 | 140 | int32_t bbs_verify_context_set_public_key(uint64_t handle, 141 | ByteBuffer public_key, 142 | ExternError *err); 143 | int32_t bbs_verify_context_set_signature(uint64_t handle, 144 | ByteBuffer signature, 145 | ExternError *err); 146 | 147 | int32_t bbs_verify_context_finish(uint64_t handle, ExternError *err); 148 | 149 | uint64_t bbs_verify_context_init(ExternError *err); 150 | 151 | int32_t bbs_verify_blind_commitment_context_add_blinded(uint64_t handle, 152 | uint32_t index, 153 | ExternError *err); 154 | 155 | int32_t bbs_verify_blind_commitment_context_set_public_key(uint64_t handle, 156 | ByteBuffer public_key, 157 | ExternError *err); 158 | 159 | int32_t bbs_verify_blind_commitment_context_set_nonce_bytes(uint64_t handle, 160 | ByteBuffer message, 161 | ExternError *err); 162 | 163 | int32_t bbs_verify_blind_commitment_context_set_proof(uint64_t handle, 164 | ByteBuffer proof, 165 | ExternError *err); 166 | 167 | uint64_t bbs_verify_blind_commitment_context_init(ExternError *err); 168 | 169 | int32_t bbs_verify_blind_commitment_context_finish(uint64_t handle, ExternError *err); 170 | 171 | int32_t bbs_verify_proof_context_finish(uint64_t handle, ExternError *err); 172 | 173 | 174 | int32_t bbs_verify_proof_context_set_proof(uint64_t handle, 175 | ByteBuffer proof, 176 | ExternError *err); 177 | 178 | int32_t bbs_verify_proof_context_set_public_key(uint64_t handle, 179 | ByteBuffer public_key, 180 | ExternError *err); 181 | 182 | int32_t bbs_verify_proof_context_set_nonce_bytes(uint64_t handle, 183 | ByteBuffer message, 184 | ExternError *err); 185 | 186 | int32_t bbs_verify_proof_context_add_message_bytes(uint64_t handle, 187 | uint32_t index, 188 | ByteBuffer message, 189 | ExternError *err); 190 | 191 | uint64_t bbs_verify_proof_context_init(ExternError *err); 192 | 193 | int32_t bls_generate_key(ByteBuffer seed, 194 | ByteBuffer *public_key, 195 | ByteBuffer *secret_key, 196 | ExternError *err); 197 | 198 | int32_t bls_public_key_size(void); 199 | 200 | int32_t bls_public_key_to_bbs_key(ByteBuffer d_public_key, 201 | uint32_t message_count, 202 | ByteBuffer *public_key, 203 | ExternError *err); 204 | 205 | int32_t bls_secret_key_size(void); 206 | 207 | #ifdef __cplusplus 208 | } // extern "C" 209 | #endif 210 | 211 | #endif 212 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /pkg/libursa/ursa/ursa_test.go: -------------------------------------------------------------------------------- 1 | package ursa 2 | 3 | import ( 4 | "encoding/json" 5 | "math/big" 6 | "testing" 7 | "unsafe" 8 | 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func TestNewNonce(t *testing.T) { 13 | t.Run("NewNonce", func(t *testing.T) { 14 | n, err := NewNonce() 15 | assert.Empty(t, err) 16 | 17 | jsn, err := n.ToJSON() 18 | assert.NoError(t, err) 19 | 20 | var str string 21 | err = json.Unmarshal(jsn, &str) 22 | 23 | i := new(big.Int) 24 | _, ok := i.SetString(str, 10) 25 | assert.True(t, ok) 26 | }) 27 | } 28 | 29 | func TestNonceFromJSON(t *testing.T) { 30 | t.Run("NonceFromJSON", func(t *testing.T) { 31 | n, err := NonceFromJSON("\"123456\"") 32 | assert.NoError(t, err) 33 | 34 | jsn, err := n.ToJSON() 35 | assert.NoError(t, err) 36 | 37 | var str string 38 | err = json.Unmarshal(jsn, &str) 39 | 40 | i := new(big.Int) 41 | _, ok := i.SetString(str, 10) 42 | assert.True(t, ok) 43 | assert.Equal(t, i.Int64(), int64(123456)) 44 | }) 45 | 46 | t.Run("NonceFromJSON", func(t *testing.T) { 47 | n, err := NonceFromJSON("should_error") 48 | assert.Empty(t, n) 49 | assert.NotEmpty(t, err) 50 | }) 51 | 52 | } 53 | 54 | func TestCredentialKeyCorrectnessProofFromJSON(t *testing.T) { 55 | t.Run("CredentialKeyCorrectnessProofFromJSON", func(t *testing.T) { 56 | correctnessProof, err := CredentialKeyCorrectnessProofFromJSON([]byte("bad string")) 57 | assert.NotEmpty(t, err) 58 | assert.Empty(t, correctnessProof) 59 | }) 60 | } 61 | 62 | func TestBlindedCredentialSecretsCorrectnessProofFromJSON(t *testing.T) { 63 | t.Run("BlindedCredentialSecretsCorrectnessProofFromJSON", func(t *testing.T) { 64 | correctnessProof, err := BlindedCredentialSecretsCorrectnessProofFromJSON([]byte("should error")) 65 | assert.NotEmpty(t, err) 66 | assert.Empty(t, correctnessProof) 67 | }) 68 | } 69 | 70 | func TestBlindedCredentialSecretsFromJSON(t *testing.T) { 71 | t.Run("BlindedCredentialSecretsFromJSON", func(t *testing.T) { 72 | credentialSecrets, err := BlindedCredentialSecretsFromJSON([]byte("should error")) 73 | assert.NotEmpty(t, err) 74 | assert.Empty(t, credentialSecrets) 75 | }) 76 | } 77 | 78 | func TestCredentialPrivateKeyFromJSON(t *testing.T) { 79 | t.Run("CredentialPrivateKeyFromJSON", func(t *testing.T) { 80 | credPK, err := CredentialPrivateKeyFromJSON([]byte("should error")) 81 | assert.NotEmpty(t, err) 82 | assert.Empty(t, credPK) 83 | }) 84 | // will test positive test case once C.ursa_cl_issuer_new_credential_def is wrapped 85 | } 86 | 87 | func TestCredentialPublicKeyFromJSON(t *testing.T) { 88 | t.Run("CredentialPublicKeyFromJSON", func(t *testing.T) { 89 | credPubKey, err := CredentialPublicKeyFromJSON([]byte("should error")) 90 | assert.NotEmpty(t, err) 91 | assert.Empty(t, credPubKey) 92 | }) 93 | 94 | t.Run("CredentialPublicKeyFromJSON", func(t *testing.T) { 95 | pk := `{"p_key": { 96 | "n": "108287889148300316626207730473335975931381324770775735724645123874260779372777494543407220823048855445706004029402240305856251416054433860231719270542455705533418503864596477511689337265606061482998569248816790582038383855525596069960821098360339043275867694682045423106821679023415276389807495664971622700038260706565018120484352261089938901024746861378694644736601450050486664386916355187017673076865314433572241059639163419427190442503909674145463092588722760454270616655228968404252436637310638323412590436524098308580854590913165383965421820813874509017896664526032381339226802962064709736184622643907804090340357", 97 | "r": { 98 | "ceeb": "20187037038427668859914876203573209361055050430543444514189897832293506755778175238171346732256410660100164427320346983366644011273508446347766938097512341439339801377711122888979184202166064198990644750071583994880717380113745002075173408907569196490245503964512718413558797577455402983421934395793123088886338080252819423491372092929720757027143947058668545481180816863687434778797493481926889624856203925427810550479749406355290923530850693823090429945291638109840097783744756643195303817525789900712008914865982622260156780333440676277105441319664551043142634888404564280113769011889304107088264261596546604853783", 99 | "city": "75721634893128516019874384521710264076257554056482231219845048775294501394535663394315517369318019283554208413855886846702058879010557649927062438399401912819267105394698349580305876788350449331677575377869570743178883377168894567563208441081524838062622368969056035630920467088780508647171666726376203961004973560206064554347233512519243541264321415467709892557678741280989858441508817695832849498295991383316309019072095529025299229188420195413502931973485505684925129239969212759907033917569528679087729349023391030714920047691476612293842841285065066749888501718324250850592015706115863271522046562058415842664188", 100 | "master_secret": "59509207097961110769904652324626973711895675792231709051606613858625146236089339814348014664396537436931694815568883540779897467160706196540764640530014192458351428717414379944857314852750501577475384443552530787595014501319013582440534346624712470531715631090453277546765271947070393250596983735599062856318814920219769097925462821596785686255078451082436429220623189066826112107057018636139035583402083323736153871588592345121241167480635423847275541782633103120309138686685381258862632578260630288315993821956700671688810892481451806627650891319064774560174566381756585190914442016883220038857602723910907777528413", 101 | "name": "37487641042866037327783302640799310609560155554202790862766982441729780051213662051932809950449327384215373607307848769930061359934113979804139620772902042093048430184886088289779612860379524151389319370084993718103373930504993038961822431592818846435137818187158297397206328785139569442708679457456335940786806384899117219320862153528246334140046582079212129751440754276987860969427795918783408840622986542654715435701511902419638241978840760160632322150499515780084305895351132481944623369140522304365467238079439012428502574624554957822553627244625240821700021341399776217363779004116830915551593059133800985535292", 102 | "state": "91853954573878257428192680426088470663679064473337471150508634642323148880724645060071348970033116392445671384996477023579407640022067361366263568390166041424806433521077479220761654801282879094143425615861895472709508356121910071872463520871506109134938144823078750446955714255318412387151451435804423314259149768327418351366283872897373978070345705698217696096440510430170818547168836244768632354954627219639879021973013845638242203717262851861461751862210213642918436136847839582868204748190928181293378222191284844462458296312186802215975043444399709700503881869487091860524246104034505689064241031832583381981583", 103 | "zipcode": "1912208481027416363267299795543551165428328603097258416224622086657103833593065312336974724803707958890587683917668221981010329626605079893269539204454671594522800659016594772774662058444986757118628166453620869516613080609101157743544773926003627306224792508122772366528425188167980126148649595212538168212157206995151497446907476768209247072868624465809558678725919334546146797180729864520171986346164336332635214849754726726851351476003580113861976925414257050438360379265035501412949777315900174716705800824766495814664984486816203081377917447714103786605077813523036355905791236630296613138859633589988463507189" 104 | }, 105 | "rctxt": "606768556708691809250672294385129018912202920222168202044067737366226124519897036026241977790555511135296405588478049972896742351328134520808089923326200414631110373746775342978567952317393152101047693373793278225940807002175053977370223791086116317607828560721446403350558127959472569586758392955515924063873602951411511203111669710199454855673505481764547966685909569286943617580671647678446868159163787373186692932196419482223607150968026310968943702818287766441436945275273491907308864158077773058441973984577892107079569600797736927564105420312519896351073484117925496105199037411817626733069759505371834303290", 106 | "s": "46261171605295513523803359785260334852446466312916919654639907313035103391130249443050540969502735772108881166051311637694979351486074353077939101575388108609669653374286164399799788341850404139313666443148220167928573249678483705369785257925662138521335549557623498675759251597834680880291558103863247352789208688294060341315253223807442229803348459803338560837810036696552830086740534298298956133125311392537317922993986415230956657201261953495189059237711346890353141640403761571566184300391649130708067706709298573519713933784336416228737618227843620960146645123224729811068230585683116466037429170959835577669594", 107 | "z": "100575037796435700243943691767872077762220112870934582186886823285537691795467980464322681869583831432429347665667669133975628879262197248692545502086905748743995423632304369059689360454495382116638924389628546799896130668008079968423260749200925480431816778140444021097581135874096358823480704937431566913834271434378080880035702614465478985394549003527450740078010127638438842673809610113073564005959985169980061587662978274329234309998049948570801136494284842377726062084047642911007177430311933493884504451650733829453945961303725494919989506887915817649687007832321207466673596927594919855686300600431103249988571" 108 | }}` 109 | 110 | credPubKey, err := CredentialPublicKeyFromJSON([]byte(pk)) 111 | assert.Empty(t, err) 112 | assert.NotEmpty(t, credPubKey) 113 | }) 114 | } 115 | 116 | func TestSignCredential(t *testing.T) { 117 | fields := []string{"attr1", "attr2", "attr3"} 118 | vals := map[string]interface{}{ 119 | "attr1": "val1", 120 | "attr2": "val2", 121 | "attr3": "val3", 122 | } 123 | 124 | sig, sigCorrectnessProof := createSignature(t, fields, vals) 125 | 126 | js, err := sig.ToJSON() 127 | assert.NoError(t, err) 128 | 129 | newSig, err := CredentialSignatureFromJSON(js) 130 | assert.NoError(t, err) 131 | assert.NotEmpty(t, newSig) 132 | 133 | err = sig.Free() 134 | assert.NoError(t, err) 135 | 136 | js, err = sigCorrectnessProof.ToJSON() 137 | assert.NoError(t, err) 138 | 139 | newCP, err := CredentialSignatureCorrectnessProofFromJSON(js) 140 | assert.NoError(t, err) 141 | assert.NotEmpty(t, newCP) 142 | 143 | err = sigCorrectnessProof.Free() 144 | assert.NoError(t, err) 145 | } 146 | 147 | func TestCorrectnessProofToJSON(t *testing.T) { 148 | var emptyProof unsafe.Pointer 149 | proof, err := CorrectnessProofToJSON(emptyProof) 150 | assert.NotEmpty(t, err) 151 | assert.Empty(t, proof) 152 | } 153 | 154 | func TestNewNonCredentialSchemaBuilder(t *testing.T) { 155 | t.Run("NewNonCredentialSchemaBuilder", func(t *testing.T) { 156 | nonBuilder, err := NewNonCredentialSchemaBuilder() 157 | assert.Empty(t, err) 158 | assert.NotEmpty(t, nonBuilder) 159 | }) 160 | } 161 | 162 | func TestNonCredentialSchemaBuilderFinalize(t *testing.T) { 163 | t.Run("NonCredentialSchemaBuilderFinalize", func(t *testing.T) { 164 | nonBuilder, _ := NewNonCredentialSchemaBuilder() 165 | err := nonBuilder.AddAttr("master_secret") 166 | assert.NoError(t, err) 167 | 168 | nonSchema, err := nonBuilder.Finalize() 169 | assert.Empty(t, err) 170 | assert.NotEmpty(t, nonSchema) 171 | 172 | err = nonSchema.Free() 173 | assert.NoError(t, err) 174 | }) 175 | } 176 | 177 | func TestCredentialSchemaBuilderNew(t *testing.T) { 178 | t.Run("CredentialSchemaBuilderNew", func(t *testing.T) { 179 | schemaBuilder, err := NewCredentialSchemaBuilder() 180 | assert.Empty(t, err) 181 | assert.NotEmpty(t, schemaBuilder) 182 | }) 183 | } 184 | 185 | func TestCredentialSchemaBuilderFinalize(t *testing.T) { 186 | t.Run("CredentialSchemaBuilderFinalize", func(t *testing.T) { 187 | builder, _ := NewCredentialSchemaBuilder() 188 | err := builder.AddAttr("master_secret") 189 | assert.NoError(t, err) 190 | 191 | schema, err := builder.Finalize() 192 | assert.Empty(t, err) 193 | assert.NotEmpty(t, schema) 194 | 195 | err = schema.Free() 196 | assert.NoError(t, err) 197 | }) 198 | } 199 | 200 | func TestBlindCredentialSecrets(t *testing.T) { 201 | t.Run("happy path", func(t *testing.T) { 202 | var nonfields []string 203 | 204 | fields := []string{"attr1", "attr2", "attr3"} 205 | vals := map[string]interface{}{ 206 | "attr1": "val1", 207 | "attr2": "val2", 208 | "attr3": "val3", 209 | } 210 | 211 | nonce, err := NewNonce() 212 | assert.NoError(t, err) 213 | 214 | credDef := createCredentialDefinition(t, fields, nonfields) 215 | blindedSecrets := createBlindedSecrets(t, credDef, nonce, vals) 216 | 217 | jsn, err := blindedSecrets.Handle.ToJSON() 218 | assert.NoError(t, err) 219 | 220 | m := map[string]interface{}{} 221 | err = json.Unmarshal(jsn, &m) 222 | assert.NoError(t, err) 223 | 224 | x, ok := m["u"].(string) 225 | assert.True(t, ok) 226 | 227 | i := new(big.Int) 228 | _, ok = i.SetString(x, 10) 229 | assert.True(t, ok) 230 | 231 | err = blindedSecrets.Handle.Free() 232 | assert.NoError(t, err) 233 | 234 | jsn, err = blindedSecrets.BlindingFactor.ToJSON() 235 | assert.NoError(t, err) 236 | 237 | m = map[string]interface{}{} 238 | err = json.Unmarshal(jsn, &m) 239 | assert.NoError(t, err) 240 | 241 | x, ok = m["v_prime"].(string) 242 | assert.True(t, ok) 243 | 244 | i = new(big.Int) 245 | _, ok = i.SetString(x, 10) 246 | assert.True(t, ok) 247 | 248 | err = blindedSecrets.BlindingFactor.Free() 249 | assert.NoError(t, err) 250 | 251 | jsn, err = blindedSecrets.CorrectnessProof.ToJSON() 252 | assert.NoError(t, err) 253 | 254 | err = blindedSecrets.CorrectnessProof.Free() 255 | assert.NoError(t, err) 256 | 257 | m = map[string]interface{}{} 258 | err = json.Unmarshal(jsn, &m) 259 | assert.NoError(t, err) 260 | 261 | x, ok = m["c"].(string) 262 | assert.True(t, ok) 263 | 264 | i = new(big.Int) 265 | _, ok = i.SetString(x, 10) 266 | assert.True(t, ok) 267 | 268 | }) 269 | } 270 | 271 | func TestBlindedSecrets(t *testing.T) { 272 | t.Run("round trip", func(t *testing.T) { 273 | fields := []string{"attr1"} 274 | nonfields := []string{"non-schema-attr1"} 275 | vals := map[string]interface{}{ 276 | "attr1": "val1", 277 | "non-schema-attr1": "val2", 278 | } 279 | 280 | nonce, err := NewNonce() 281 | assert.NoError(t, err) 282 | 283 | credDef := createCredentialDefinition(t, fields, nonfields) 284 | js, err := credDef.KeyCorrectnessProof.ToJSON() 285 | assert.NoError(t, err) 286 | assert.Contains(t, string(js), "\"attr1\"") 287 | assert.Contains(t, string(js), "\"non-schema-attr1\"") 288 | 289 | blindedSecrets := createBlindedSecrets(t, credDef, nonce, vals) 290 | 291 | js, err = blindedSecrets.BlindingFactor.ToJSON() 292 | assert.NoError(t, err) 293 | 294 | assert.Contains(t, string(js), "\"v_prime\"") 295 | 296 | bf, err := CredentialSecretsBlindingFactorsFromJSON(js) 297 | assert.NoError(t, err) 298 | assert.NotNil(t, bf) 299 | 300 | }) 301 | } 302 | 303 | func createBlindedSecrets(t *testing.T, credDef *CredentialDef, nonce *Nonce, vals map[string]interface{}) *BlindedCredentialSecrets { 304 | 305 | values := createValues(t, vals) 306 | 307 | blindedSecrets, err := BlindCredentialSecrets(credDef.PubKey, credDef.KeyCorrectnessProof, nonce, values) 308 | assert.NoError(t, err) 309 | 310 | return blindedSecrets 311 | } 312 | 313 | func createSignature(t *testing.T, fields []string, vals map[string]interface{}) (*CredentialSignature, *CredentialSignatureCorrectnessProof) { 314 | var nonfields []string 315 | var err error 316 | 317 | ms, err := NewMasterSecret() 318 | assert.NoError(t, err) 319 | js, err := ms.ToJSON() 320 | assert.NoError(t, err) 321 | m := struct { 322 | MasterSecret string `json:"ms"` 323 | }{} 324 | err = json.Unmarshal(js, &m) 325 | assert.NoError(t, err) 326 | 327 | vals["master_secret"] = m.MasterSecret 328 | 329 | nonce, err := NewNonce() 330 | assert.NoError(t, err) 331 | 332 | credDef := createCredentialDefinition(t, fields, nonfields) 333 | blindedSecrets := createBlindedSecrets(t, credDef, nonce, vals) 334 | values := createValues(t, vals) 335 | 336 | signParams := NewSignatureParams() 337 | signParams.ProverID = "did:sov:example1" 338 | signParams.CredentialPubKey = credDef.PubKey 339 | signParams.CredentialPrivKey = credDef.PrivKey 340 | signParams.BlindedCredentialSecrets = blindedSecrets.Handle 341 | signParams.BlindedCredentialSecretsCorrectnessProof = blindedSecrets.CorrectnessProof 342 | signParams.CredentialNonce = nonce 343 | signParams.CredentialValues = values 344 | 345 | signParams.CredentialIssuanceNonce, err = NewNonce() 346 | assert.NoError(t, err) 347 | 348 | sig, sigCorrectnessProof, err := signParams.SignCredential() 349 | assert.NoError(t, err) 350 | 351 | err = values.Free() 352 | assert.NoError(t, err) 353 | 354 | return sig, sigCorrectnessProof 355 | } 356 | -------------------------------------------------------------------------------- /pkg/libzmix/bbs/bbs_test.go: -------------------------------------------------------------------------------- 1 | package bbs 2 | 3 | import ( 4 | "math/rand" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | 9 | "github.com/hyperledger/ursa-wrapper-go/pkg/libursa/ursa" 10 | ) 11 | 12 | func TestGenerateKey(t *testing.T) { 13 | t.Run("GenerateKey", func(t *testing.T) { 14 | data := make([]byte, 4) 15 | rand.Read(data) 16 | kp, err := GenerateBlsKey(nil) 17 | 18 | assert.Empty(t, err) 19 | assert.NotEmpty(t, kp) 20 | assert.NotEmpty(t, kp.PublicKey) 21 | assert.NotEmpty(t, kp.SecretKey) 22 | 23 | kp.FreePublicKey() 24 | kp.FreeSecretKey() 25 | }) 26 | } 27 | 28 | func TestBlsKeyPair(t *testing.T) { 29 | data := make([]byte, 4) 30 | rand.Read(data) 31 | blskp, err := GenerateBlsKey(data) 32 | assert.Empty(t, err) 33 | t.Run("BlsPublicKeyToBBSKey", func(t *testing.T) { 34 | bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(5) 35 | assert.Empty(t, err) 36 | assert.NotEmpty(t, bbsPublicKey) 37 | 38 | bbsPublicKey.Free() 39 | }) 40 | 41 | blskp.FreeSecretKey() 42 | blskp.FreePublicKey() 43 | } 44 | 45 | func TestSignContextInit(t *testing.T) { 46 | t.Run("SignContextInit", func(t *testing.T) { 47 | handle, err := SignContextInit() 48 | assert.Empty(t, err) 49 | assert.NotEmpty(t, handle.data) 50 | }) 51 | } 52 | 53 | func TestSignContext(t *testing.T) { 54 | 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, 55 | 9, 10, 31, 32} 56 | t.Run("SetPublicKey", func(t *testing.T) { 57 | signContext, err := SignContextInit() 58 | assert.Empty(t, err) 59 | assert.NotEmpty(t, signContext.data) 60 | 61 | blskp, err := GenerateBlsKey(data) 62 | assert.Empty(t, err) 63 | 64 | bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(5) 65 | assert.Empty(t, err) 66 | 67 | err = signContext.SetPublicKey(*bbsPublicKey) 68 | assert.Empty(t, err) 69 | }) 70 | 71 | t.Run("SetSecretKey", func(t *testing.T) { 72 | signContext, err := SignContextInit() 73 | assert.Empty(t, err) 74 | assert.NotEmpty(t, signContext.data) 75 | 76 | blskp, err := GenerateBlsKey(data) 77 | assert.Empty(t, err) 78 | 79 | err = signContext.SetSecretKey(HandleByteBuffer{ 80 | Buffer: blskp.SecretKey, 81 | }) 82 | assert.Empty(t, err) 83 | }) 84 | 85 | t.Run("AddMessageBytes", func(t *testing.T) { 86 | signContext, err := SignContextInit() 87 | assert.Empty(t, err) 88 | assert.NotEmpty(t, signContext.data) 89 | 90 | err = signContext.AddMessages([]string{"a message", "another message", "the last message"}) 91 | assert.Empty(t, err) 92 | assert.NotEmpty(t, signContext) 93 | }) 94 | 95 | t.Run("Finish full SignContext", func(t *testing.T) { 96 | signContext, err := SignContextInit() 97 | assert.Empty(t, err) 98 | assert.NotEmpty(t, signContext.data) 99 | 100 | blskp, err := GenerateBlsKey(data) 101 | assert.Empty(t, err) 102 | bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(2) 103 | assert.Empty(t, err) 104 | 105 | err = signContext.SetPublicKey(*bbsPublicKey) 106 | assert.Empty(t, err) 107 | 108 | err = signContext.SetSecretKey(HandleByteBuffer{ 109 | Buffer: blskp.SecretKey, 110 | }) 111 | assert.Empty(t, err) 112 | 113 | err = signContext.AddMessages([]string{"a message", "one more message"}) 114 | assert.Empty(t, err) 115 | assert.NotEmpty(t, signContext) 116 | 117 | signature, err := signContext.Finish() 118 | assert.Empty(t, err) 119 | assert.NotEmpty(t, signature) 120 | signature.Free() 121 | }) 122 | 123 | t.Run("Should error if public key isn't set", func(t *testing.T) { 124 | signContext, err := SignContextInit() 125 | assert.Empty(t, err) 126 | assert.NotEmpty(t, signContext.data) 127 | 128 | blskp, err := GenerateBlsKey(data) 129 | assert.Empty(t, err) 130 | 131 | err = signContext.SetSecretKey(HandleByteBuffer{ 132 | Buffer: blskp.SecretKey, 133 | }) 134 | assert.Empty(t, err) 135 | 136 | err = signContext.AddMessages([]string{"a message"}) 137 | assert.Empty(t, err) 138 | assert.NotEmpty(t, signContext) 139 | 140 | signature, err := signContext.Finish() 141 | assert.Error(t, err) 142 | assert.Contains(t, err.Error(), "Public Key must be set") 143 | assert.Empty(t, signature) 144 | }) 145 | 146 | t.Run("Should error if secret key isn't set", func(t *testing.T) { 147 | signContext, err := SignContextInit() 148 | assert.Empty(t, err) 149 | assert.NotEmpty(t, signContext.data) 150 | 151 | blskp, err := GenerateBlsKey(data) 152 | assert.Empty(t, err) 153 | bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(1) 154 | assert.Empty(t, err) 155 | 156 | err = signContext.SetPublicKey(*bbsPublicKey) 157 | assert.Empty(t, err) 158 | 159 | err = signContext.AddMessages([]string{"a message"}) 160 | assert.Empty(t, err) 161 | assert.NotEmpty(t, signContext) 162 | 163 | signature, err := signContext.Finish() 164 | assert.Error(t, err) 165 | assert.Contains(t, err.Error(), "Secret Key must be set") 166 | assert.Empty(t, signature) 167 | }) 168 | 169 | t.Run("Should error if messages aren't set", func(t *testing.T) { 170 | signContext, err := SignContextInit() 171 | assert.Empty(t, err) 172 | assert.NotEmpty(t, signContext.data) 173 | 174 | blskp, err := GenerateBlsKey(data) 175 | assert.Empty(t, err) 176 | bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(5) 177 | assert.Empty(t, err) 178 | 179 | err = signContext.SetPublicKey(*bbsPublicKey) 180 | assert.Empty(t, err) 181 | 182 | err = signContext.SetSecretKey(HandleByteBuffer{ 183 | Buffer: blskp.SecretKey, 184 | }) 185 | assert.Empty(t, err) 186 | 187 | signature, err := signContext.Finish() 188 | assert.Error(t, err) 189 | assert.Contains(t, err.Error(), "Messages cannot be empty") 190 | assert.Empty(t, signature) 191 | }) 192 | } 193 | 194 | func TestBlindCommitmentContextInit(t *testing.T) { 195 | t.Run("BlindCommitmentContextInit", func(t *testing.T) { 196 | handle, err := BlindCommitmentContextInit() 197 | assert.Empty(t, err) 198 | assert.NotEmpty(t, handle.data) 199 | }) 200 | } 201 | 202 | func TestBlindCommitmentContext(t *testing.T) { 203 | 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, 204 | 9, 10, 31, 32} 205 | 206 | t.Run("Finish full BlindCommitmentContext", func(t *testing.T) { 207 | blindCommitmentContext, err := BlindCommitmentContextInit() 208 | assert.Empty(t, err) 209 | assert.NotEmpty(t, blindCommitmentContext.data) 210 | 211 | blskp, err := GenerateBlsKey(data) 212 | assert.Empty(t, err) 213 | bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(3) 214 | assert.Empty(t, err) 215 | 216 | err = blindCommitmentContext.SetPublicKey(*bbsPublicKey) 217 | assert.Empty(t, err) 218 | 219 | nonce, err := ursa.NewNonce() 220 | assert.Empty(t, err) 221 | nonceBytes, err := nonce.ToJSON() 222 | assert.Empty(t, err) 223 | err = blindCommitmentContext.SetNonce(nonceBytes) 224 | assert.Empty(t, err) 225 | 226 | err = blindCommitmentContext.AddMessage("a message", 0) 227 | assert.Empty(t, err) 228 | assert.NotEmpty(t, blindCommitmentContext) 229 | 230 | blindedCommitment, err := blindCommitmentContext.Finish() 231 | assert.Empty(t, err) 232 | assert.NotEmpty(t, blindedCommitment) 233 | assert.NotEmpty(t, blindedCommitment.BlindingFactor) 234 | assert.NotEmpty(t, blindedCommitment.Commitment) 235 | assert.NotEmpty(t, blindedCommitment.Context) 236 | blindedCommitment.Free() 237 | }) 238 | } 239 | 240 | func TestVerifyBlindCommitmentContextInit(t *testing.T) { 241 | t.Run("VerifyBlindCommitmentContextInit", func(t *testing.T) { 242 | handle, err := VerifyBlindCommitmentContextInit() 243 | assert.Empty(t, err) 244 | assert.NotEmpty(t, handle.data) 245 | }) 246 | } 247 | 248 | func TestVerifyBlindCommitmentContext(t *testing.T) { 249 | 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, 250 | 9, 10, 31, 32} 251 | 252 | t.Run("SetPublicKey", func(t *testing.T) { 253 | verifyBlindCommitmentContext, err := VerifyBlindCommitmentContextInit() 254 | assert.Empty(t, err) 255 | assert.NotEmpty(t, verifyBlindCommitmentContext.data) 256 | 257 | blskp, err := GenerateBlsKey(data) 258 | assert.Empty(t, err) 259 | bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(5) 260 | assert.Empty(t, err) 261 | 262 | err = verifyBlindCommitmentContext.SetPublicKey(*bbsPublicKey) 263 | assert.Empty(t, err) 264 | }) 265 | t.Run("SetNonceBytes", func(t *testing.T) { 266 | verifyBlindCommitmentContext, err := VerifyBlindCommitmentContextInit() 267 | assert.Empty(t, err) 268 | assert.NotEmpty(t, verifyBlindCommitmentContext.data) 269 | 270 | nonce, err := ursa.NewNonce() 271 | assert.Empty(t, err) 272 | nonceBytes, err := nonce.ToJSON() 273 | assert.Empty(t, err) 274 | err = verifyBlindCommitmentContext.SetNonce(nonceBytes) 275 | assert.Empty(t, err) 276 | }) 277 | 278 | t.Run("Finish", func(t *testing.T) { 279 | verifyBlindCommitmentContext, err := VerifyBlindCommitmentContextInit() 280 | assert.Empty(t, err) 281 | assert.NotEmpty(t, verifyBlindCommitmentContext.data) 282 | 283 | blskp, err := GenerateBlsKey(data) 284 | assert.Empty(t, err) 285 | bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(5) 286 | assert.Empty(t, err) 287 | err = verifyBlindCommitmentContext.SetPublicKey(*bbsPublicKey) 288 | assert.Empty(t, err) 289 | 290 | nonce, err := ursa.NewNonce() 291 | assert.Empty(t, err) 292 | nonceBytes, err := nonce.ToJSON() 293 | assert.Empty(t, err) 294 | err = verifyBlindCommitmentContext.SetNonce(nonceBytes) 295 | assert.Empty(t, err) 296 | 297 | err = verifyBlindCommitmentContext.AddBlinded(0) 298 | assert.Empty(t, err) 299 | 300 | blindedCommitment := createBlindedCommitment(t, *bbsPublicKey, nonceBytes, []string{"a message"}) 301 | 302 | err = verifyBlindCommitmentContext.SetProof(HandleByteBuffer{Buffer: blindedCommitment.Context}) 303 | assert.Empty(t, err) 304 | 305 | err = verifyBlindCommitmentContext.Finish() 306 | assert.Empty(t, err) 307 | blindedCommitment.Free() 308 | }) 309 | } 310 | 311 | func TestBlindSignContext(t *testing.T) { 312 | 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, 313 | 9, 10, 31, 32} 314 | 315 | t.Run("full run", func(t *testing.T) { 316 | messages := []string{"a message", "another message", "one more message"} 317 | blindSignContext, err := BlindSignContextInit() 318 | assert.Empty(t, err) 319 | assert.NotEmpty(t, blindSignContext) 320 | 321 | blskp, err := GenerateBlsKey(data) 322 | assert.Empty(t, err) 323 | bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(3) 324 | assert.Empty(t, err) 325 | 326 | err = blindSignContext.SetPublicKey(*bbsPublicKey) 327 | assert.Empty(t, err) 328 | 329 | err = blindSignContext.SetSecretKey(HandleByteBuffer{ 330 | Buffer: blskp.SecretKey, 331 | }) 332 | assert.Empty(t, err) 333 | 334 | err = blindSignContext.AddMessage(messages[0], 0) 335 | assert.Empty(t, err) 336 | assert.NotEmpty(t, blindSignContext) 337 | 338 | nonce, err := ursa.NewNonce() 339 | assert.Empty(t, err) 340 | assert.NotEmpty(t, nonce) 341 | 342 | nonceBytes, err := nonce.ToJSON() 343 | assert.Empty(t, err) 344 | assert.NotEmpty(t, nonceBytes) 345 | 346 | blindedCommitment := createBlindedCommitment(t, *bbsPublicKey, nonceBytes, messages) 347 | assert.NotEmpty(t, blindedCommitment) 348 | 349 | err = blindSignContext.SetCommitment(HandleByteBuffer{blindedCommitment.Commitment}) 350 | assert.Empty(t, err) 351 | assert.NotEmpty(t, blindSignContext) 352 | 353 | blindedSignature, err := blindSignContext.Finish() 354 | assert.Empty(t, err) 355 | assert.NotEmpty(t, blindedSignature) 356 | 357 | unblindedSignature, err := blindedSignature.Unblind(HandleByteBuffer{blindedCommitment.BlindingFactor}) 358 | assert.Empty(t, err) 359 | assert.NotEmpty(t, unblindedSignature) 360 | blindedCommitment.Free() 361 | }) 362 | } 363 | 364 | func TestVerifyContext(t *testing.T) { 365 | 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, 366 | 9, 10, 31, 32} 367 | 368 | t.Run("verify unblinded signature", func(t *testing.T) { 369 | messages := []string{"a message", "another message", "one more message"} 370 | blindSignContext, err := BlindSignContextInit() 371 | assert.Empty(t, err) 372 | assert.NotEmpty(t, blindSignContext) 373 | 374 | blskp, err := GenerateBlsKey(data) 375 | assert.Empty(t, err) 376 | bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(3) 377 | assert.Empty(t, err) 378 | 379 | nonce, err := ursa.NewNonce() 380 | assert.Empty(t, err) 381 | assert.NotEmpty(t, nonce) 382 | 383 | nonceBytes, err := nonce.ToJSON() 384 | assert.Empty(t, err) 385 | assert.NotEmpty(t, nonceBytes) 386 | 387 | blindedCommitment := createBlindedCommitment(t, *bbsPublicKey, nonceBytes, messages) 388 | 389 | unblindedSignature := createUnblindedSignature(t, *bbsPublicKey, HandleByteBuffer{blskp.SecretKey}, messages[0], 0, *blindedCommitment) 390 | 391 | verifyContext, err := VerifyContextInit() 392 | assert.Empty(t, err) 393 | assert.NotEmpty(t, verifyContext) 394 | 395 | err = verifyContext.SetPublicKey(*bbsPublicKey) 396 | assert.Empty(t, err) 397 | 398 | err = verifyContext.SetSignature(unblindedSignature) 399 | assert.Empty(t, err) 400 | 401 | err = verifyContext.AddMessages([]string{"a message", "another message", "one more message"}) 402 | assert.Empty(t, err) 403 | 404 | result, err := verifyContext.Finish() 405 | assert.True(t, result) 406 | assert.Empty(t, err) 407 | }) 408 | 409 | t.Run("verify signature", func(t *testing.T) { 410 | messages := []string{"a message", "another message", "one more message"} 411 | blindSignContext, err := BlindSignContextInit() 412 | assert.Empty(t, err) 413 | assert.NotEmpty(t, blindSignContext) 414 | 415 | blskp, err := GenerateBlsKey(data) 416 | assert.Empty(t, err) 417 | bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(3) 418 | assert.Empty(t, err) 419 | 420 | signature := createSignature(t, *bbsPublicKey, HandleByteBuffer{blskp.SecretKey}, messages) 421 | 422 | verifyContext, err := VerifyContextInit() 423 | assert.Empty(t, err) 424 | assert.NotEmpty(t, verifyContext) 425 | 426 | err = verifyContext.SetPublicKey(*bbsPublicKey) 427 | assert.Empty(t, err) 428 | 429 | err = verifyContext.SetSignature(signature) 430 | assert.Empty(t, err) 431 | 432 | err = verifyContext.AddMessages(messages) 433 | assert.Empty(t, err) 434 | 435 | result, err := verifyContext.Finish() 436 | assert.True(t, result) 437 | assert.Empty(t, err) 438 | }) 439 | } 440 | 441 | func TestProofContext(t *testing.T) { 442 | t.Run("ProofContextInit", func(t *testing.T) { 443 | handle, err := ProofContextInit() 444 | assert.Empty(t, err) 445 | assert.NotEmpty(t, handle.data) 446 | }) 447 | 448 | t.Run("Full run of ProofContext", func(t *testing.T) { 449 | 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, 450 | 9, 10, 31, 32} 451 | messages := []string{"a message", "another message", "the third message", "the fourth message", "the last message"} 452 | 453 | blskp, err := GenerateBlsKey(data) 454 | assert.Empty(t, err) 455 | bbsPublicKey, err := blskp.BlsPublicKeyToBBSKey(5) 456 | assert.Empty(t, err) 457 | 458 | signContext, err := SignContextInit() 459 | assert.Empty(t, err) 460 | assert.NotEmpty(t, signContext) 461 | 462 | err = signContext.SetPublicKey(*bbsPublicKey) 463 | assert.Empty(t, err) 464 | 465 | err = signContext.SetSecretKey(HandleByteBuffer{blskp.SecretKey}) 466 | assert.Empty(t, err) 467 | 468 | err = signContext.AddMessages(messages) 469 | assert.Empty(t, err) 470 | 471 | signature, err := signContext.Finish() 472 | assert.Empty(t, err) 473 | assert.NotEmpty(t, signature) 474 | 475 | nonce, err := ursa.NewNonce() 476 | assert.Empty(t, err) 477 | assert.NotEmpty(t, nonce) 478 | 479 | nonceBytes, err := nonce.ToJSON() 480 | assert.Empty(t, err) 481 | assert.NotEmpty(t, nonceBytes) 482 | 483 | blindCommitmentContext, err := BlindCommitmentContextInit() 484 | assert.Empty(t, err) 485 | assert.NotEmpty(t, blindCommitmentContext.data) 486 | 487 | err = blindCommitmentContext.AddMessage(messages[0], 0) 488 | assert.Empty(t, err) 489 | assert.NotEmpty(t, blindCommitmentContext) 490 | 491 | err = blindCommitmentContext.SetPublicKey(*bbsPublicKey) 492 | assert.Empty(t, err) 493 | 494 | err = blindCommitmentContext.SetNonce(nonceBytes) 495 | assert.Empty(t, err) 496 | 497 | blindedCommitment, err := blindCommitmentContext.Finish() 498 | assert.Empty(t, err) 499 | 500 | verifyContext, err := VerifyBlindCommitmentContextInit() 501 | assert.Empty(t, err) 502 | assert.NotEmpty(t, verifyContext) 503 | 504 | err = verifyContext.AddBlinded(0) 505 | assert.Empty(t, err) 506 | 507 | err = verifyContext.SetPublicKey(*bbsPublicKey) 508 | assert.Empty(t, err) 509 | 510 | err = verifyContext.SetNonce(nonceBytes) 511 | assert.NoError(t, err) 512 | 513 | err = verifyContext.SetProof(HandleByteBuffer{blindedCommitment.Context}) 514 | assert.Empty(t, err) 515 | 516 | err = verifyContext.Finish() 517 | assert.NoError(t, err) 518 | 519 | blindSignCtx, err := BlindSignContextInit() 520 | assert.NoError(t, err) 521 | 522 | for i, message := range messages[1:] { 523 | err := blindSignCtx.AddMessage(message, i+1) 524 | assert.NoError(t, err) 525 | } 526 | 527 | err = blindSignCtx.SetPublicKey(*bbsPublicKey) 528 | assert.NoError(t, err) 529 | 530 | err = blindSignCtx.SetSecretKey(HandleByteBuffer{blskp.SecretKey}) 531 | assert.NoError(t, err) 532 | 533 | err = blindSignCtx.SetCommitment(HandleByteBuffer{blindedCommitment.Commitment}) 534 | assert.NoError(t, err) 535 | 536 | blindedSignature, err := blindSignCtx.Finish() 537 | assert.NoError(t, err) 538 | 539 | unblindedSignature, err := blindedSignature.Unblind(HandleByteBuffer{blindedCommitment.BlindingFactor}) 540 | assert.NoError(t, err) 541 | 542 | proofContext, err := ProofContextInit() 543 | assert.Empty(t, err) 544 | assert.NotEmpty(t, proofContext.data) 545 | 546 | err = proofContext.AddProofMessages(messages[0:2], Revealed, HandleByteBuffer{blindedCommitment.BlindingFactor}) 547 | assert.Empty(t, err) 548 | 549 | err = proofContext.AddProofMessages(messages[2:], HiddenProofSpecificBlinding, HandleByteBuffer{blindedCommitment.BlindingFactor}) 550 | assert.Empty(t, err) 551 | 552 | err = proofContext.SetSignature(unblindedSignature) 553 | assert.Empty(t, err) 554 | 555 | err = proofContext.SetPublicKey(*bbsPublicKey) 556 | assert.Empty(t, err) 557 | 558 | err = proofContext.SetNonce(nonceBytes) 559 | assert.NoError(t, err) 560 | 561 | proof, err := proofContext.Finish() 562 | assert.NoError(t, err) 563 | assert.NotEmpty(t, proof) 564 | 565 | verifyProofContext, err := VerifyProofContextInit() 566 | assert.Empty(t, err) 567 | assert.NotEmpty(t, verifyProofContext) 568 | 569 | err = verifyProofContext.AddMessage(messages[0], 0) 570 | assert.Empty(t, err) 571 | 572 | err = verifyProofContext.AddMessage(messages[1], 1) 573 | assert.Empty(t, err) 574 | 575 | err = verifyProofContext.SetNonce(nonceBytes) 576 | assert.Empty(t, err) 577 | 578 | err = verifyProofContext.SetPublicKey(*bbsPublicKey) 579 | assert.Empty(t, err) 580 | 581 | err = verifyProofContext.SetProof(HandleByteBuffer{Buffer: proof.Buffer}) 582 | assert.Empty(t, err) 583 | 584 | err = verifyProofContext.Finish() 585 | assert.Empty(t, err) 586 | 587 | }) 588 | } 589 | 590 | func createBlindedCommitment(t *testing.T, bbsPublicKey HandleByteBuffer, nonce []byte, messages []string) *BlindedCommitment { 591 | blindCommitmentContext, err := BlindCommitmentContextInit() 592 | assert.Empty(t, err) 593 | assert.NotEmpty(t, blindCommitmentContext.data) 594 | 595 | err = blindCommitmentContext.AddMessage(messages[0], 0) 596 | assert.Empty(t, err) 597 | assert.NotEmpty(t, blindCommitmentContext) 598 | 599 | err = blindCommitmentContext.SetPublicKey(bbsPublicKey) 600 | assert.Empty(t, err) 601 | 602 | err = blindCommitmentContext.SetNonce(nonce) 603 | assert.Empty(t, err) 604 | 605 | blindedCommitment, err := blindCommitmentContext.Finish() 606 | assert.Empty(t, err) 607 | 608 | return blindedCommitment 609 | } 610 | 611 | func createUnblindedSignature(t *testing.T, bbsPublicKey, secretKey HandleByteBuffer, message string, index int, blindedCommitment BlindedCommitment) *Signature { 612 | blindSignContext, err := BlindSignContextInit() 613 | assert.Empty(t, err) 614 | assert.NotEmpty(t, blindSignContext) 615 | 616 | err = blindSignContext.SetPublicKey(bbsPublicKey) 617 | assert.Empty(t, err) 618 | 619 | err = blindSignContext.SetSecretKey(secretKey) 620 | assert.Empty(t, err) 621 | 622 | err = blindSignContext.AddMessage(message, index) 623 | assert.Empty(t, err) 624 | assert.NotEmpty(t, blindSignContext) 625 | 626 | err = blindSignContext.SetCommitment(HandleByteBuffer{blindedCommitment.Commitment}) 627 | assert.Empty(t, err) 628 | assert.NotEmpty(t, blindSignContext) 629 | 630 | blindedSignature, err := blindSignContext.Finish() 631 | assert.Empty(t, err) 632 | assert.NotEmpty(t, blindedSignature) 633 | 634 | unblindedSignature, err := blindedSignature.Unblind(HandleByteBuffer{blindedCommitment.BlindingFactor}) 635 | assert.Empty(t, err) 636 | assert.NotEmpty(t, unblindedSignature) 637 | 638 | return unblindedSignature 639 | } 640 | 641 | func createSignature(t *testing.T, bbsPublicKey HandleByteBuffer, secretKey HandleByteBuffer, messages []string) *Signature { 642 | signContext, err := SignContextInit() 643 | assert.Empty(t, err) 644 | assert.NotEmpty(t, signContext.data) 645 | 646 | err = signContext.SetPublicKey(bbsPublicKey) 647 | assert.Empty(t, err) 648 | 649 | err = signContext.SetSecretKey(secretKey) 650 | assert.Empty(t, err) 651 | 652 | err = signContext.AddMessages(messages) 653 | assert.Empty(t, err) 654 | assert.NotEmpty(t, signContext) 655 | 656 | signature, err := signContext.Finish() 657 | assert.Empty(t, err) 658 | assert.NotEmpty(t, signature) 659 | 660 | return signature 661 | } 662 | -------------------------------------------------------------------------------- /pkg/libursa/ursa/ursa.go: -------------------------------------------------------------------------------- 1 | package ursa 2 | 3 | /* 4 | #cgo LDFLAGS: -lursa 5 | #include "ursa_cl.h" 6 | #include 7 | */ 8 | import "C" 9 | import ( 10 | "encoding/json" 11 | "unsafe" 12 | 13 | "github.com/pkg/errors" 14 | ) 15 | 16 | type Handle struct { 17 | ptr unsafe.Pointer 18 | } 19 | 20 | type Nonce Handle 21 | 22 | // NewNonce creates a random nonce 23 | func NewNonce() (*Nonce, error) { 24 | var nonce unsafe.Pointer 25 | 26 | result := C.ursa_cl_new_nonce(&nonce) 27 | if result.code != 0 { 28 | return nil, ursaError(C.GoString(result.message)) 29 | } 30 | 31 | return &Nonce{nonce}, nil 32 | } 33 | 34 | // NonceFromJSON creates and returns nonce from json 35 | func NonceFromJSON(jsn string) (*Nonce, error) { 36 | var handle unsafe.Pointer 37 | cjson := C.CString(jsn) 38 | defer C.free(unsafe.Pointer(cjson)) 39 | 40 | result := C.ursa_cl_nonce_from_json(cjson, &handle) 41 | if result.code != 0 { 42 | return nil, ursaError(C.GoString(result.message)) 43 | } 44 | 45 | return &Nonce{handle}, nil 46 | } 47 | 48 | // ToJSON returns JSON representation of nonce 49 | func (r *Nonce) ToJSON() ([]byte, error) { 50 | var d *C.char 51 | defer C.free(unsafe.Pointer(d)) 52 | 53 | result := C.ursa_cl_nonce_to_json(r.ptr, &d) 54 | if result.code != 0 { 55 | return nil, ursaError(C.GoString(result.message)) 56 | } 57 | 58 | out := []byte(C.GoString(d)) 59 | return out, nil 60 | } 61 | 62 | // Free deallocates the nonce 63 | func (r *Nonce) Free() error { 64 | result := C.ursa_cl_nonce_free(r.ptr) 65 | if result.code != 0 { 66 | return ursaError(C.GoString(result.message)) 67 | } 68 | 69 | return nil 70 | } 71 | 72 | // BlindedCredentialSecretsCorrectnessProofFromJSON creates and returns blinded credential secrets correctness proof json. 73 | func BlindedCredentialSecretsCorrectnessProofFromJSON(jsn []byte) (*BlindedCredentialSecretsCorrectnessProof, error) { 74 | var handle unsafe.Pointer 75 | cjson := C.CString(string(jsn)) 76 | defer C.free(unsafe.Pointer(cjson)) 77 | 78 | result := C.ursa_cl_blinded_credential_secrets_correctness_proof_from_json(cjson, &handle) 79 | if result.code != 0 { 80 | return nil, ursaError(C.GoString(result.message)) 81 | } 82 | 83 | return &BlindedCredentialSecretsCorrectnessProof{handle}, nil 84 | } 85 | 86 | // CredentialKeyCorrectnessProofFromJSON creates and returns credential key correctness proof from json 87 | func CredentialKeyCorrectnessProofFromJSON(jsn []byte) (*CredentialDefKeyCorrectnessProof, error) { 88 | var handle unsafe.Pointer 89 | cjson := C.CString(string(jsn)) 90 | defer C.free(unsafe.Pointer(cjson)) 91 | 92 | result := C.ursa_cl_credential_key_correctness_proof_from_json(cjson, &handle) 93 | if result.code != 0 { 94 | return nil, ursaError(C.GoString(result.message)) 95 | } 96 | 97 | return &CredentialDefKeyCorrectnessProof{handle}, nil 98 | } 99 | 100 | // BlindedCredentialSecretsFromJSON creates and returns blinded credential secrets from json 101 | func BlindedCredentialSecretsFromJSON(jsn []byte) (*BlindedCredentialSecretsHandle, error) { 102 | var handle unsafe.Pointer 103 | cjson := C.CString(string(jsn)) 104 | defer C.free(unsafe.Pointer(cjson)) 105 | 106 | result := C.ursa_cl_blinded_credential_secrets_from_json(cjson, &handle) 107 | if result.code != 0 { 108 | return nil, ursaError(C.GoString(result.message)) 109 | } 110 | 111 | return &BlindedCredentialSecretsHandle{handle}, nil 112 | } 113 | 114 | // CredentialPrivateKeyFromJSON creates and returns credential private key from json 115 | func CredentialPrivateKeyFromJSON(jsn []byte) (*CredentialDefPrivKey, error) { 116 | var handle unsafe.Pointer 117 | cjson := C.CString(string(jsn)) 118 | defer C.free(unsafe.Pointer(cjson)) 119 | 120 | result := C.ursa_cl_credential_private_key_from_json(cjson, &handle) 121 | if result.code != 0 { 122 | return nil, ursaError(C.GoString(result.message)) 123 | } 124 | 125 | return &CredentialDefPrivKey{handle}, nil 126 | } 127 | 128 | // CredentialPublicKeyFromJSON creates and returns credential public key from json 129 | func CredentialPublicKeyFromJSON(jsn []byte) (*CredentialDefPubKey, error) { 130 | var handle unsafe.Pointer 131 | cjson := C.CString(string(jsn)) 132 | defer C.free(unsafe.Pointer(cjson)) 133 | 134 | result := C.ursa_cl_credential_public_key_from_json(cjson, &handle) 135 | if result.code != 0 { 136 | return nil, ursaError(C.GoString(result.message)) 137 | } 138 | 139 | return &CredentialDefPubKey{handle}, nil 140 | } 141 | 142 | type NonCredentialSchemaBuilder Handle 143 | type NonCredentialSchemaHandle Handle 144 | 145 | // NewNonCredentialSchemaBuilder creates and returns non credential schema builder 146 | func NewNonCredentialSchemaBuilder() (*NonCredentialSchemaBuilder, error) { 147 | var nonBuilder unsafe.Pointer 148 | 149 | result := C.ursa_cl_non_credential_schema_builder_new(&nonBuilder) 150 | if result.code != 0 { 151 | return nil, ursaError(C.GoString(result.message)) 152 | } 153 | 154 | return &NonCredentialSchemaBuilder{nonBuilder}, nil 155 | } 156 | 157 | // AddAttr adds new attribute to non credential schema 158 | func (r *NonCredentialSchemaBuilder) AddAttr(attr string) error { 159 | cAttr := C.CString(attr) 160 | defer C.free(unsafe.Pointer(cAttr)) 161 | 162 | result := C.ursa_cl_non_credential_schema_builder_add_attr(r.ptr, cAttr) 163 | if result.code != 0 { 164 | return ursaError(C.GoString(result.message)) 165 | } 166 | 167 | return nil 168 | } 169 | 170 | // Finalize deallocates non_credential schema builder and returns non credential schema entity instead 171 | func (r *NonCredentialSchemaBuilder) Finalize() (*NonCredentialSchemaHandle, error) { 172 | var nonSchema unsafe.Pointer 173 | 174 | result := C.ursa_cl_non_credential_schema_builder_finalize(r.ptr, &nonSchema) 175 | if result.code != 0 { 176 | return nil, ursaError(C.GoString(result.message)) 177 | } 178 | 179 | return &NonCredentialSchemaHandle{nonSchema}, nil 180 | } 181 | 182 | // Free deallocates credential schema instance 183 | func (r *NonCredentialSchemaHandle) Free() error { 184 | result := C.ursa_cl_non_credential_schema_free(r.ptr) 185 | if result.code != 0 { 186 | return ursaError(C.GoString(result.message)) 187 | } 188 | 189 | return nil 190 | } 191 | 192 | type CredentialSchemaBuilder Handle 193 | type CredentialSchemaHandle Handle 194 | 195 | // NewCredentialSchemaBuilder creates and return credential schema entity builder 196 | func NewCredentialSchemaBuilder() (*CredentialSchemaBuilder, error) { 197 | var builder unsafe.Pointer 198 | result := C.ursa_cl_credential_schema_builder_new(&builder) 199 | if result.code != 0 { 200 | return nil, ursaError(C.GoString(result.message)) 201 | } 202 | 203 | return &CredentialSchemaBuilder{builder}, nil 204 | } 205 | 206 | // AddAttr adds new attribute to credential schema 207 | func (r *CredentialSchemaBuilder) AddAttr(field string) error { 208 | cfield := C.CString(field) 209 | result := C.ursa_cl_credential_schema_builder_add_attr(r.ptr, cfield) 210 | C.free(unsafe.Pointer(cfield)) 211 | if result.code != 0 { 212 | return ursaError(C.GoString(result.message)) 213 | } 214 | 215 | return nil 216 | } 217 | 218 | // Finalize deallocates credential schema builder and return credential schema entity instead 219 | func (r *CredentialSchemaBuilder) Finalize() (*CredentialSchemaHandle, error) { 220 | var schema unsafe.Pointer 221 | 222 | result := C.ursa_cl_credential_schema_builder_finalize(r.ptr, &schema) 223 | if result.code != 0 { 224 | return nil, ursaError(C.GoString(result.message)) 225 | } 226 | 227 | return &CredentialSchemaHandle{schema}, nil 228 | } 229 | 230 | // Free deallocates credential schema instance 231 | func (r *CredentialSchemaHandle) Free() error { 232 | result := C.ursa_cl_credential_schema_free(r.ptr) 233 | if result.code != 0 { 234 | return ursaError(C.GoString(result.message)) 235 | } 236 | 237 | return nil 238 | } 239 | 240 | type CredentialDefPubKey Handle 241 | type CredentialDefPrivKey Handle 242 | type CredentialDefKeyCorrectnessProof Handle 243 | 244 | // ToJSON creates and returns JSON representation of credential definition public key 245 | func (r *CredentialDefPubKey) ToJSON() ([]byte, error) { 246 | var jsn *C.char 247 | 248 | result := C.ursa_cl_credential_public_key_to_json(r.ptr, &jsn) 249 | defer C.free(unsafe.Pointer(jsn)) 250 | if result.code != 0 { 251 | return nil, ursaError(C.GoString(result.message)) 252 | } 253 | 254 | return []byte(C.GoString(jsn)), nil 255 | } 256 | 257 | // Free deallocates credential definition public key instance 258 | func (r *CredentialDefPubKey) Free() error { 259 | result := C.ursa_cl_credential_public_key_free(r.ptr) 260 | if result.code != 0 { 261 | return ursaError(C.GoString(result.message)) 262 | } 263 | 264 | return nil 265 | } 266 | 267 | // ToJSON creates and returns JSON representation of credential definition private key 268 | func (r *CredentialDefPrivKey) ToJSON() ([]byte, error) { 269 | var jsn *C.char 270 | 271 | result := C.ursa_cl_credential_private_key_to_json(r.ptr, &jsn) 272 | defer C.free(unsafe.Pointer(jsn)) 273 | if result.code != 0 { 274 | return nil, ursaError(C.GoString(result.message)) 275 | } 276 | 277 | return []byte(C.GoString(jsn)), nil 278 | } 279 | 280 | // Free deallocates credential definition private key instance 281 | func (r *CredentialDefPrivKey) Free() error { 282 | result := C.ursa_cl_credential_private_key_free(r.ptr) 283 | if result.code != 0 { 284 | return ursaError(C.GoString(result.message)) 285 | } 286 | 287 | return nil 288 | } 289 | 290 | // ToJSON creates and returns JSON representation of credential definition key correctness proof 291 | func (r *CredentialDefKeyCorrectnessProof) ToJSON() ([]byte, error) { 292 | var jsn *C.char 293 | 294 | result := C.ursa_cl_credential_key_correctness_proof_to_json(r.ptr, &jsn) 295 | defer C.free(unsafe.Pointer(jsn)) 296 | if result.code != 0 { 297 | return nil, ursaError(C.GoString(result.message)) 298 | } 299 | 300 | return []byte(C.GoString(jsn)), nil 301 | } 302 | 303 | // Free deallocates credential definition key correctness proof instance 304 | func (r *CredentialDefKeyCorrectnessProof) Free() error { 305 | result := C.ursa_cl_credential_key_correctness_proof_free(r.ptr) 306 | if result.code != 0 { 307 | return ursaError(C.GoString(result.message)) 308 | } 309 | 310 | return nil 311 | } 312 | 313 | type CredentialDef struct { 314 | PubKey *CredentialDefPubKey 315 | PrivKey *CredentialDefPrivKey 316 | KeyCorrectnessProof *CredentialDefKeyCorrectnessProof 317 | } 318 | 319 | // NewCredentialDef creates and returns credential definition (public and private keys, correctness proof) entities 320 | func NewCredentialDef(schema *CredentialSchemaHandle, nonSchema *NonCredentialSchemaHandle, revocation bool) (*CredentialDef, error) { 321 | var credpub, credpriv, credproof unsafe.Pointer 322 | 323 | result := C.ursa_cl_issuer_new_credential_def(schema.ptr, nonSchema.ptr, C.bool(revocation), &credpub, &credpriv, &credproof) 324 | if result.code != 0 { 325 | return nil, ursaError(C.GoString(result.message)) 326 | } 327 | 328 | credDef := &CredentialDef{ 329 | PubKey: &CredentialDefPubKey{credpub}, 330 | PrivKey: &CredentialDefPrivKey{credpriv}, 331 | KeyCorrectnessProof: &CredentialDefKeyCorrectnessProof{credproof}, 332 | } 333 | 334 | return credDef, nil 335 | } 336 | 337 | // CorrectnessProofToJSON creates and returns JSON representation of credential signature correctness proof 338 | func CorrectnessProofToJSON(credSignatureCorrectnessProof unsafe.Pointer) ([]byte, error) { 339 | var proofOut *C.char 340 | 341 | result := C.ursa_cl_signature_correctness_proof_to_json(credSignatureCorrectnessProof, &proofOut) 342 | defer C.free(unsafe.Pointer(proofOut)) 343 | if result.code != 0 { 344 | return nil, ursaError(C.GoString(result.message)) 345 | } 346 | 347 | return []byte(C.GoString(proofOut)), nil 348 | } 349 | 350 | type SignatureParams struct { 351 | ProverID string 352 | BlindedCredentialSecrets *BlindedCredentialSecretsHandle 353 | BlindedCredentialSecretsCorrectnessProof *BlindedCredentialSecretsCorrectnessProof 354 | CredentialIssuanceNonce *Nonce 355 | CredentialNonce *Nonce 356 | CredentialValues *CredentialValues 357 | CredentialPubKey *CredentialDefPubKey 358 | CredentialPrivKey *CredentialDefPrivKey 359 | } 360 | 361 | // NewSignatureParams creates an empty instance of SignatureParams 362 | func NewSignatureParams() *SignatureParams { 363 | return &SignatureParams{} 364 | } 365 | 366 | type CredentialSignature Handle 367 | type CredentialSignatureCorrectnessProof Handle 368 | 369 | // CredentialSignatureFromJSON creates and returns credential signature from json 370 | func CredentialSignatureFromJSON(jsn []byte) (*CredentialSignature, error) { 371 | var handle unsafe.Pointer 372 | cjson := C.CString(string(jsn)) 373 | defer C.free(unsafe.Pointer(cjson)) 374 | 375 | result := C.ursa_cl_credential_signature_from_json(cjson, &handle) 376 | if result.code != 0 { 377 | return nil, ursaError(C.GoString(result.message)) 378 | } 379 | 380 | return &CredentialSignature{handle}, nil 381 | } 382 | 383 | // CredentialSignatureCorrectnessProofFromJSON creates and returns credential signature correctness proof from json 384 | func CredentialSignatureCorrectnessProofFromJSON(jsn []byte) (*CredentialSignatureCorrectnessProof, error) { 385 | var handle unsafe.Pointer 386 | cjson := C.CString(string(jsn)) 387 | defer C.free(unsafe.Pointer(cjson)) 388 | 389 | result := C.ursa_cl_signature_correctness_proof_from_json(cjson, &handle) 390 | if result.code != 0 { 391 | return nil, ursaError(C.GoString(result.message)) 392 | } 393 | 394 | return &CredentialSignatureCorrectnessProof{handle}, nil 395 | } 396 | 397 | // SignCredential signs credential values with primary keys only 398 | func (r *SignatureParams) SignCredential() (*CredentialSignature, *CredentialSignatureCorrectnessProof, error) { 399 | var credSignature, credSignatureCorrectnessProof unsafe.Pointer 400 | 401 | did := C.CString(r.ProverID) 402 | 403 | result := C.ursa_cl_issuer_sign_credential( 404 | did, 405 | r.BlindedCredentialSecrets.ptr, 406 | r.BlindedCredentialSecretsCorrectnessProof.ptr, 407 | r.CredentialNonce.ptr, 408 | r.CredentialIssuanceNonce.ptr, 409 | r.CredentialValues.ptr, 410 | r.CredentialPubKey.ptr, 411 | r.CredentialPrivKey.ptr, 412 | &credSignature, 413 | &credSignatureCorrectnessProof) 414 | if result.code != 0 { 415 | return nil, nil, ursaError(C.GoString(result.message)) 416 | } 417 | 418 | return &CredentialSignature{credSignature}, &CredentialSignatureCorrectnessProof{credSignatureCorrectnessProof}, nil 419 | } 420 | 421 | // ProcessCredentialSignature updates the credential signature by a credential secrets blinding factors. 422 | func (r *CredentialSignature) ProcessCredentialSignature(values *CredentialValues, sigKP *CredentialSignatureCorrectnessProof, 423 | credentialSecretsBF *CredentialSecretsBlindingFactors, credPubKey *CredentialDefPubKey, issuanceNonce *Nonce) error { 424 | 425 | result := C.ursa_cl_prover_process_credential_signature( 426 | r.ptr, 427 | values.ptr, 428 | sigKP.ptr, 429 | credentialSecretsBF.ptr, 430 | credPubKey.ptr, 431 | issuanceNonce.ptr, 432 | nil, /* rev_key_pub */ 433 | nil, /* rev_reg */ 434 | nil, /* witness */ 435 | ) 436 | 437 | if result.code != 0 { 438 | return ursaError(C.GoString(result.message)) 439 | } 440 | return nil 441 | } 442 | 443 | // Free deallocates credential signature instance 444 | func (r *CredentialSignature) Free() error { 445 | result := C.ursa_cl_credential_signature_free(r.ptr) 446 | if result.code != 0 { 447 | return ursaError(C.GoString(result.message)) 448 | } 449 | 450 | return nil 451 | } 452 | 453 | // ToJSON creates and returns JSON representation of credential signature 454 | func (r *CredentialSignature) ToJSON() ([]byte, error) { 455 | var jsn *C.char 456 | 457 | result := C.ursa_cl_credential_signature_to_json(r.ptr, &jsn) 458 | defer C.free(unsafe.Pointer(jsn)) 459 | if result.code != 0 { 460 | return nil, ursaError(C.GoString(result.message)) 461 | } 462 | 463 | return []byte(C.GoString(jsn)), nil 464 | } 465 | 466 | // Free deallocates credential signature correctness proof instance 467 | func (r *CredentialSignatureCorrectnessProof) Free() error { 468 | result := C.ursa_cl_signature_correctness_proof_free(r.ptr) 469 | if result.code != 0 { 470 | return ursaError(C.GoString(result.message)) 471 | } 472 | 473 | return nil 474 | } 475 | 476 | // ToJSON creates and returns JSON representation of credential signature correctness proof 477 | func (r *CredentialSignatureCorrectnessProof) ToJSON() ([]byte, error) { 478 | var jsn *C.char 479 | 480 | result := C.ursa_cl_signature_correctness_proof_to_json(r.ptr, &jsn) 481 | defer C.free(unsafe.Pointer(jsn)) 482 | if result.code != 0 { 483 | return nil, ursaError(C.GoString(result.message)) 484 | } 485 | 486 | return []byte(C.GoString(jsn)), nil 487 | } 488 | 489 | type BlindedCredentialSecretsHandle Handle 490 | type CredentialSecretsBlindingFactors Handle 491 | type BlindedCredentialSecretsCorrectnessProof Handle 492 | 493 | // CredentialSecretsBlindingFactorsFromJSON creates and returns credential secrets blinding factors from json 494 | func CredentialSecretsBlindingFactorsFromJSON(jsn []byte) (*CredentialSecretsBlindingFactors, error) { 495 | var handle unsafe.Pointer 496 | cjson := C.CString(string(jsn)) 497 | defer C.free(unsafe.Pointer(cjson)) 498 | 499 | result := C.ursa_cl_credential_secrets_blinding_factors_from_json(cjson, &handle) 500 | if result.code != 0 { 501 | return nil, ursaError(C.GoString(result.message)) 502 | } 503 | 504 | return &CredentialSecretsBlindingFactors{handle}, nil 505 | } 506 | 507 | // ToJSON creates and returns JSON representation of blinded credental secrets 508 | func (r *BlindedCredentialSecretsHandle) ToJSON() ([]byte, error) { 509 | var jsn *C.char 510 | 511 | result := C.ursa_cl_blinded_credential_secrets_to_json(r.ptr, &jsn) 512 | defer C.free(unsafe.Pointer(jsn)) 513 | if result.code != 0 { 514 | return nil, ursaError(C.GoString(result.message)) 515 | } 516 | 517 | return []byte(C.GoString(jsn)), nil 518 | } 519 | 520 | // Free deallocates blinded credential secrets instance 521 | func (r *BlindedCredentialSecretsHandle) Free() error { 522 | result := C.ursa_cl_blinded_credential_secrets_free(r.ptr) 523 | if result.code != 0 { 524 | return ursaError(C.GoString(result.message)) 525 | } 526 | 527 | return nil 528 | } 529 | 530 | // ToJSON creates and returns JSON representation of credential secrets blinding factors 531 | func (r *CredentialSecretsBlindingFactors) ToJSON() ([]byte, error) { 532 | var jsn *C.char 533 | 534 | result := C.ursa_cl_credential_secrets_blinding_factors_to_json(r.ptr, &jsn) 535 | defer C.free(unsafe.Pointer(jsn)) 536 | if result.code != 0 { 537 | return nil, ursaError(C.GoString(result.message)) 538 | } 539 | 540 | return []byte(C.GoString(jsn)), nil 541 | } 542 | 543 | // Free deallocates credential secrets blinding factors instance 544 | func (r *CredentialSecretsBlindingFactors) Free() error { 545 | result := C.ursa_cl_credential_secrets_blinding_factors_free(r.ptr) 546 | if result.code != 0 { 547 | return ursaError(C.GoString(result.message)) 548 | } 549 | 550 | return nil 551 | } 552 | 553 | // ToJSON creates and returns JSON representation of blinded credential secrets correctness proof 554 | func (r *BlindedCredentialSecretsCorrectnessProof) ToJSON() ([]byte, error) { 555 | var jsn *C.char 556 | 557 | result := C.ursa_cl_blinded_credential_secrets_correctness_proof_to_json(r.ptr, &jsn) 558 | defer C.free(unsafe.Pointer(jsn)) 559 | if result.code != 0 { 560 | return nil, ursaError(C.GoString(result.message)) 561 | } 562 | 563 | return []byte(C.GoString(jsn)), nil 564 | } 565 | 566 | // Free deallocates blinded credential secrets correctness proof instance 567 | func (r *BlindedCredentialSecretsCorrectnessProof) Free() error { 568 | result := C.ursa_cl_blinded_credential_secrets_correctness_proof_free(r.ptr) 569 | if result.code != 0 { 570 | return ursaError(C.GoString(result.message)) 571 | } 572 | 573 | return nil 574 | } 575 | 576 | type BlindedCredentialSecrets struct { 577 | Handle *BlindedCredentialSecretsHandle 578 | BlindingFactor *CredentialSecretsBlindingFactors 579 | CorrectnessProof *BlindedCredentialSecretsCorrectnessProof 580 | } 581 | 582 | // BlindCredentialSecrets creates blinded credential secrets for given issuer key and master secret 583 | func BlindCredentialSecrets(credentialPubKey *CredentialDefPubKey, keyCorrectnessProof *CredentialDefKeyCorrectnessProof, nonce *Nonce, 584 | values *CredentialValues) (*BlindedCredentialSecrets, error) { 585 | 586 | var blindedCredentialSecrets, blindedCredentialSecretsCorrectnessProof, credentialSecretsBlindingFactors unsafe.Pointer 587 | 588 | result := C.ursa_cl_prover_blind_credential_secrets( 589 | credentialPubKey.ptr, 590 | keyCorrectnessProof.ptr, 591 | values.ptr, 592 | nonce.ptr, 593 | &blindedCredentialSecrets, 594 | &credentialSecretsBlindingFactors, 595 | &blindedCredentialSecretsCorrectnessProof) 596 | if result.code != 0 { 597 | return nil, ursaError(C.GoString(result.message)) 598 | } 599 | 600 | return &BlindedCredentialSecrets{ 601 | Handle: &BlindedCredentialSecretsHandle{blindedCredentialSecrets}, 602 | BlindingFactor: &CredentialSecretsBlindingFactors{credentialSecretsBlindingFactors}, 603 | CorrectnessProof: &BlindedCredentialSecretsCorrectnessProof{blindedCredentialSecretsCorrectnessProof}, 604 | }, nil 605 | 606 | } 607 | 608 | type UrsaError struct { 609 | Backtrace string 610 | Message string 611 | } 612 | 613 | func ursaError(msg string) error { 614 | var cMsg *C.char 615 | defer C.free(unsafe.Pointer(cMsg)) 616 | 617 | C.ursa_get_current_error(&cMsg) 618 | var ursaError UrsaError 619 | json.Unmarshal([]byte(C.GoString(cMsg)), &ursaError) 620 | 621 | return errors.Errorf("error from URSA: %s", ursaError.Message) 622 | } 623 | -------------------------------------------------------------------------------- /pkg/libzmix/bbs/bbs.go: -------------------------------------------------------------------------------- 1 | package bbs 2 | 3 | /* 4 | #cgo LDFLAGS: -lbbs 5 | #include "bbs_cl.h" 6 | #include 7 | */ 8 | import "C" 9 | import ( 10 | "unsafe" 11 | 12 | "github.com/pkg/errors" 13 | ) 14 | 15 | type BlsKeyPair struct { 16 | PublicKey C.ByteBuffer 17 | SecretKey C.ByteBuffer 18 | } 19 | 20 | type HandleByteBuffer struct { 21 | Buffer C.ByteBuffer 22 | } 23 | 24 | func (r HandleByteBuffer) Free() { 25 | C.bbs_byte_buffer_free(r.Buffer) 26 | } 27 | 28 | //GenerateKey generates a bls key pair 29 | func GenerateBlsKey(data []byte) (*BlsKeyPair, error) { 30 | var seed C.ByteBuffer 31 | defer C.bbs_byte_buffer_free(seed) 32 | var publicKey C.ByteBuffer 33 | var secretKey C.ByteBuffer 34 | var err C.ExternError 35 | 36 | seed.len = (C.long)(len(data)) 37 | if len(data) > 0 { 38 | seed.data = (*C.uchar)(unsafe.Pointer(&data)) 39 | } 40 | 41 | code := C.bls_generate_key(seed, &publicKey, &secretKey, &err) 42 | if code != 0 { 43 | return nil, errors.Errorf("err occurred generating BLS key pair: %s", C.GoString(err.message)) 44 | } 45 | 46 | pkSize := C.bls_public_key_size() 47 | skSize := C.bls_secret_key_size() 48 | if publicKey.len != (C.long)(pkSize) || secretKey.len != (C.long)(skSize) { 49 | return nil, errors.Errorf("key pair lengths are invalid") 50 | } 51 | 52 | return &BlsKeyPair{ 53 | PublicKey: publicKey, 54 | SecretKey: secretKey, 55 | }, nil 56 | } 57 | 58 | //FreeSecretKey deallocates the secret key instance 59 | func (r *BlsKeyPair) FreeSecretKey() { 60 | C.bbs_byte_buffer_free(r.SecretKey) 61 | } 62 | 63 | //FreeSecretKey deallocates the public key instance 64 | func (r *BlsKeyPair) FreePublicKey() { 65 | C.bbs_byte_buffer_free(r.PublicKey) 66 | } 67 | 68 | //BlsPublicKeyToBBSKey converts a bls public key to a BBS public key 69 | func (r *BlsKeyPair) BlsPublicKeyToBBSKey(messageCount int) (*HandleByteBuffer, error) { 70 | var bbsPublicKey C.ByteBuffer 71 | var err C.ExternError 72 | 73 | count := (C.uint)(messageCount) 74 | 75 | code := C.bls_public_key_to_bbs_key(r.PublicKey, count, &bbsPublicKey, &err) 76 | if code != 0 { 77 | return nil, errors.Errorf("error occurred converting BLS public key to BBS public key: %s", C.GoString(err.message)) 78 | } 79 | 80 | return &HandleByteBuffer{Buffer: bbsPublicKey}, nil 81 | } 82 | 83 | type Handle struct { 84 | data C.ulong 85 | } 86 | 87 | type BlindSignContext Handle 88 | 89 | //BlindSignContext initializes a blind sign context 90 | func BlindSignContextInit() (*BlindSignContext, error) { 91 | var err C.ExternError 92 | 93 | handle := C.bbs_blind_sign_context_init(&err) 94 | if err.code != 0 { 95 | return nil, errors.Errorf("error occurred initializing BBS sign context: %s", C.GoString(err.message)) 96 | } 97 | 98 | return &BlindSignContext{handle}, nil 99 | } 100 | 101 | //SetPublicKey sets the bbs public key on the BlindSignContext 102 | func (r *BlindSignContext) SetPublicKey(publicKey HandleByteBuffer) error { 103 | var err C.ExternError 104 | 105 | code := C.bbs_blind_sign_context_set_public_key(r.data, publicKey.Buffer, &err) 106 | if code != 0 { 107 | return errors.Errorf("error occurred setting secret key to BBS sign context: %s", C.GoString(err.message)) 108 | } 109 | 110 | return nil 111 | } 112 | 113 | //SetSecretKey sets the bls secret key on the BlindSignContext 114 | func (r *BlindSignContext) SetSecretKey(secretKey HandleByteBuffer) error { 115 | var err C.ExternError 116 | 117 | code := C.bbs_blind_sign_context_set_secret_key(r.data, secretKey.Buffer, &err) 118 | if code != 0 { 119 | return errors.Errorf("error occurred setting secret key to BBS sign context: %s", C.GoString(err.message)) 120 | } 121 | 122 | return nil 123 | } 124 | 125 | //SetCommitment sets the commitment on the BlindSignContext 126 | func (r *BlindSignContext) SetCommitment(blindCommitment HandleByteBuffer) error { 127 | var err C.ExternError 128 | 129 | code := C.bbs_blind_sign_context_set_commitment(r.data, blindCommitment.Buffer, &err) 130 | if code != 0 { 131 | return errors.Errorf("error occurred setting blind commitment to BBS blind sign context: %s", C.GoString(err.message)) 132 | } 133 | 134 | return nil 135 | } 136 | 137 | //AddMessage adds the message and associated index to BlindSignContext 138 | func (r *BlindSignContext) AddMessage(message string, index int) error { 139 | var err C.ExternError 140 | var cMessage C.ByteBuffer 141 | 142 | cm := C.CString(message) 143 | cMessage.len = (C.long)(len(message)) 144 | cMessage.data = (*C.uchar)(unsafe.Pointer(cm)) 145 | code := C.bbs_blind_sign_context_add_message_bytes(r.data, (C.uint)(index), cMessage, &err) 146 | if code != 0 { 147 | return errors.Errorf("error occurred adding message bytes to BBS sign context: %s", C.GoString(err.message)) 148 | } 149 | 150 | return nil 151 | } 152 | 153 | type BlindedSignature HandleByteBuffer 154 | 155 | //Finish generates a BlindedSignature from a BlindSignContext 156 | func (r *BlindSignContext) Finish() (*BlindedSignature, error) { 157 | var err C.ExternError 158 | var blindedSignature C.ByteBuffer 159 | 160 | code := C.bbs_blind_sign_context_finish(r.data, &blindedSignature, &err) 161 | if code != 0 { 162 | return nil, errors.Errorf("error occurred finishing BBS sign context: %s", C.GoString(err.message)) 163 | } 164 | 165 | sigSize := C.bbs_blind_signature_size() 166 | if blindedSignature.len != (C.long)(sigSize) { 167 | return nil, errors.Errorf("signature is incorrect size") 168 | } 169 | 170 | return &BlindedSignature{Buffer: blindedSignature}, nil 171 | } 172 | 173 | //Unblind returns the Signature from the BlindedSignature 174 | func (r *BlindedSignature) Unblind(blindingFactor HandleByteBuffer) (*Signature, error) { 175 | var unblindSignature C.ByteBuffer 176 | var err C.ExternError 177 | 178 | code := C.bbs_unblind_signature(r.Buffer, blindingFactor.Buffer, &unblindSignature, &err) 179 | if code != 0 { 180 | return nil, errors.Errorf("error occurred unblinding signature: %s", C.GoString(err.message)) 181 | } 182 | 183 | sigSize := C.bbs_signature_size() 184 | if unblindSignature.len != (C.long)(sigSize) { 185 | return nil, errors.Errorf("signature is incorrect size") 186 | } 187 | 188 | return &Signature{unblindSignature}, nil 189 | } 190 | 191 | type SignContext Handle 192 | 193 | //SignContextInit initializes a sign context 194 | func SignContextInit() (*SignContext, error) { 195 | var err C.ExternError 196 | 197 | handle := C.bbs_sign_context_init(&err) 198 | if err.code != 0 { 199 | return nil, errors.Errorf("error occurred initializing BBS sign context: %s", C.GoString(err.message)) 200 | } 201 | 202 | return &SignContext{handle}, nil 203 | } 204 | 205 | //SetPublicKey sets the public key on the SignContext 206 | func (r *SignContext) SetPublicKey(publicKey HandleByteBuffer) error { 207 | var err C.ExternError 208 | 209 | code := C.bbs_sign_context_set_public_key(r.data, publicKey.Buffer, &err) 210 | if code != 0 { 211 | return errors.Errorf("error occurred setting secret key to BBS sign context: %s", C.GoString(err.message)) 212 | } 213 | 214 | return nil 215 | } 216 | 217 | //SetSecretKey sets the bls secret key on teh SignContext 218 | func (r *SignContext) SetSecretKey(secretKey HandleByteBuffer) error { 219 | var err C.ExternError 220 | 221 | code := C.bbs_sign_context_set_secret_key(r.data, secretKey.Buffer, &err) 222 | if code != 0 { 223 | return errors.Errorf("error occurred setting secret key to BBS sign context: %s", C.GoString(err.message)) 224 | } 225 | 226 | return nil 227 | } 228 | 229 | //AddMessages adds messages to the SignContext 230 | func (r *SignContext) AddMessages(messages []string) error { 231 | var err C.ExternError 232 | var message C.ByteBuffer 233 | defer C.bbs_byte_buffer_free(message) 234 | 235 | for _, m := range messages { 236 | message.len = (C.long)(len(m)) 237 | cm := C.CString(m) 238 | message.data = (*C.uchar)(unsafe.Pointer(&cm)) 239 | code := C.bbs_sign_context_add_message_bytes(r.data, message, &err) 240 | if code != 0 { 241 | return errors.Errorf("error occurred adding message bytes to BBS sign context: %s", C.GoString(err.message)) 242 | } 243 | } 244 | 245 | return nil 246 | } 247 | 248 | type Signature HandleByteBuffer 249 | 250 | //Finish generates a Signature from the SignContext 251 | func (r *SignContext) Finish() (*Signature, error) { 252 | var err C.ExternError 253 | var signature C.ByteBuffer 254 | 255 | code := C.bbs_sign_context_finish(r.data, &signature, &err) 256 | if code != 0 { 257 | return nil, errors.Errorf("error occurred finishing BBS sign context: %s", C.GoString(err.message)) 258 | } 259 | 260 | sigSize := C.bbs_signature_size() 261 | if signature.len != (C.long)(sigSize) { 262 | return nil, errors.Errorf("signature is incorrect size") 263 | } 264 | 265 | return &Signature{Buffer: signature}, nil 266 | } 267 | 268 | //Free deallocates the Signature instance 269 | func (r *Signature) Free() { 270 | C.bbs_byte_buffer_free(r.Buffer) 271 | } 272 | 273 | type BlindCommitmentContext Handle 274 | 275 | //BlindCommitmentContextInit initializes a BlindCommitmentContext 276 | func BlindCommitmentContextInit() (*BlindCommitmentContext, error) { 277 | var err C.ExternError 278 | 279 | handle := C.bbs_blind_commitment_context_init(&err) 280 | if err.code != 0 { 281 | return nil, errors.Errorf("error occurred initializing BBS blind commitment context: %s", C.GoString(err.message)) 282 | } 283 | 284 | return &BlindCommitmentContext{handle}, nil 285 | } 286 | 287 | //SetPublicKey sets the bbs public key on the BlindCommitmentContext 288 | func (r *BlindCommitmentContext) SetPublicKey(publicKey HandleByteBuffer) error { 289 | var err C.ExternError 290 | 291 | code := C.bbs_blind_commitment_context_set_public_key(r.data, publicKey.Buffer, &err) 292 | if code != 0 { 293 | return errors.Errorf("error occurred setting secret key to BBS sign context: %s", C.GoString(err.message)) 294 | } 295 | 296 | return nil 297 | } 298 | 299 | //AddMessage adds a message and its associated index to the BlindCommitmentContext 300 | func (r *BlindCommitmentContext) AddMessage(message string, index int) error { 301 | var err C.ExternError 302 | var cMessage C.ByteBuffer 303 | defer C.bbs_byte_buffer_free(cMessage) 304 | 305 | cMessage.len = (C.long)(len(message)) 306 | cm := C.CString(message) 307 | cMessage.data = (*C.uchar)(unsafe.Pointer(cm)) 308 | code := C.bbs_blind_commitment_context_add_message_bytes(r.data, (C.uint)(index), cMessage, &err) 309 | if code != 0 { 310 | return errors.Errorf("error occurred adding message bytes to BBS blind commitment context: %s", C.GoString(err.message)) 311 | } 312 | 313 | return nil 314 | } 315 | 316 | //SetNonce sets the nonce on the BlindedCommitmentContext 317 | func (r *BlindCommitmentContext) SetNonce(nonce []byte) error { 318 | var err C.ExternError 319 | var nonceBuffer C.ByteBuffer 320 | defer C.bbs_byte_buffer_free(nonceBuffer) 321 | 322 | nonceBuffer.len = (C.long)(len(nonce)) 323 | nonceBuffer.data = (*C.uchar)(unsafe.Pointer(&nonce)) 324 | 325 | code := C.bbs_blind_commitment_context_set_nonce_bytes(r.data, nonceBuffer, &err) 326 | if code != 0 { 327 | return errors.Errorf("error occurred setting nonce bytes on BBS blind commitment context: %s", C.GoString(err.message)) 328 | } 329 | 330 | return nil 331 | } 332 | 333 | type BlindedCommitment struct { 334 | Commitment C.ByteBuffer 335 | Context C.ByteBuffer 336 | BlindingFactor C.ByteBuffer 337 | } 338 | 339 | //Finish generates a commitment, context, and blinding factor from the BlindCommitmentContext 340 | func (r *BlindCommitmentContext) Finish() (*BlindedCommitment, error) { 341 | var err C.ExternError 342 | var commitment C.ByteBuffer 343 | var outContext C.ByteBuffer 344 | var blindingFactor C.ByteBuffer 345 | 346 | code := C.bbs_blind_commitment_context_finish(r.data, &commitment, &outContext, &blindingFactor, &err) 347 | if code > 0 { 348 | return nil, errors.Errorf("error occurred finishing BBS sign context: %s", C.GoString(err.message)) 349 | } 350 | 351 | return &BlindedCommitment{ 352 | Commitment: commitment, 353 | Context: outContext, 354 | BlindingFactor: blindingFactor, 355 | }, nil 356 | } 357 | 358 | //FreeCommitment deallocates the Commitment, Context, and BlindingFactor instances from the BlindedCommitment 359 | func (r *BlindedCommitment) Free() { 360 | C.bbs_byte_buffer_free(r.Commitment) 361 | C.bbs_byte_buffer_free(r.Context) 362 | C.bbs_byte_buffer_free(r.BlindingFactor) 363 | } 364 | 365 | type VerifyBlindCommitmentContext Handle 366 | 367 | //VerifyBlindCommitmentContextInit initializes a VerifyBlindCommitmentContext 368 | func VerifyBlindCommitmentContextInit() (*VerifyBlindCommitmentContext, error) { 369 | var err C.ExternError 370 | 371 | handle := C.bbs_verify_blind_commitment_context_init(&err) 372 | if err.code != 0 { 373 | return nil, errors.Errorf("error occurred initializing BBS verify blinded commitment context: %s", C.GoString(err.message)) 374 | } 375 | 376 | return &VerifyBlindCommitmentContext{data: handle}, nil 377 | } 378 | 379 | //SetPublicKey sets the bbs public key on the VerifyBlindCommitmentContext 380 | func (r *VerifyBlindCommitmentContext) SetPublicKey(publicKey HandleByteBuffer) error { 381 | var err C.ExternError 382 | 383 | code := C.bbs_verify_blind_commitment_context_set_public_key(r.data, publicKey.Buffer, &err) 384 | if code != 0 { 385 | return errors.Errorf("error occurred setting secret key to BBS sign context: %s", C.GoString(err.message)) 386 | } 387 | 388 | return nil 389 | } 390 | 391 | //SetNonce sets the nonce on the VerifyBlindCommitmentContext 392 | func (r *VerifyBlindCommitmentContext) SetNonce(nonce []byte) error { 393 | var err C.ExternError 394 | var nonceBuffer C.ByteBuffer 395 | defer C.bbs_byte_buffer_free(nonceBuffer) 396 | 397 | nonceBuffer.len = (C.long)(len(nonce)) 398 | nonceBuffer.data = (*C.uchar)(unsafe.Pointer(&nonce)) 399 | 400 | code := C.bbs_verify_blind_commitment_context_set_nonce_bytes(r.data, nonceBuffer, &err) 401 | if code != 0 { 402 | return errors.Errorf("error occurred setting nonce bytes on BBS verify blind commitment context: %s", C.GoString(err.message)) 403 | } 404 | 405 | return nil 406 | } 407 | 408 | //AddBlinded adds the index of the blinded message to the VerifyBlindCommitmentContext 409 | func (r *VerifyBlindCommitmentContext) AddBlinded(index int) error { 410 | var err C.ExternError 411 | 412 | code := C.bbs_verify_blind_commitment_context_add_blinded(r.data, (C.uint)(index), &err) 413 | if code != 0 { 414 | return errors.Errorf("error occurred setting blinded index on BBS verify blind commitment context: %s", C.GoString(err.message)) 415 | } 416 | 417 | return nil 418 | } 419 | 420 | //SetProof sets the context from the BlindCommitmentContext on the VerifyBlindCommitmentContext 421 | func (r *VerifyBlindCommitmentContext) SetProof(proof HandleByteBuffer) error { 422 | var err C.ExternError 423 | 424 | code := C.bbs_verify_blind_commitment_context_set_proof(r.data, proof.Buffer, &err) 425 | if code != 0 { 426 | return errors.Errorf("error occurred setting proof on BBS verify blind commitment context: %s", C.GoString(err.message)) 427 | } 428 | 429 | return nil 430 | } 431 | 432 | //Finish verifies the BlindCommitmentContext 433 | func (r *VerifyBlindCommitmentContext) Finish() error { 434 | var err C.ExternError 435 | 436 | code := C.bbs_verify_blind_commitment_context_finish(r.data, &err) 437 | if err.code != 0 { 438 | return errors.Errorf("error occurred finishing BBS verify proof context: %s", C.GoString(err.message)) 439 | } 440 | 441 | if code != 200 { 442 | if ProofStatus[code] != "" { 443 | return errors.Errorf("failed to verify proof: %s", ProofStatus[code]) 444 | } 445 | return errors.Errorf("unknown error occurred verifying proof: %d", code) 446 | } 447 | 448 | return nil 449 | } 450 | 451 | type VerifyContext Handle 452 | 453 | //VerifyContextInit initializes a VerifyContext 454 | func VerifyContextInit() (*VerifyContext, error) { 455 | var err C.ExternError 456 | 457 | handle := C.bbs_verify_context_init(&err) 458 | if err.code != 0 { 459 | return nil, errors.Errorf("error occurred initializing BBS verify context: %s", C.GoString(err.message)) 460 | } 461 | 462 | return &VerifyContext{data: handle}, nil 463 | } 464 | 465 | //AddMessages adds the messages to the VerifyContext 466 | func (r *VerifyContext) AddMessages(messages []string) error { 467 | var err C.ExternError 468 | var message C.ByteBuffer 469 | 470 | for _, m := range messages { 471 | message.len = (C.long)(len(m)) 472 | cm := C.CString(m) 473 | message.data = (*C.uchar)(unsafe.Pointer(cm)) 474 | code := C.bbs_verify_context_add_message_bytes(r.data, message, &err) 475 | if code != 0 { 476 | return errors.Errorf("error occurred adding message bytes to BBS verify context: %s", C.GoString(err.message)) 477 | } 478 | } 479 | 480 | return nil 481 | } 482 | 483 | //SetPublicKey sets the bbs public key on the VerifyContext 484 | func (r *VerifyContext) SetPublicKey(publicKey HandleByteBuffer) error { 485 | var err C.ExternError 486 | 487 | code := C.bbs_verify_context_set_public_key(r.data, publicKey.Buffer, &err) 488 | if code != 0 { 489 | return errors.Errorf("error occurred setting secret key to BBS verify context: %s", C.GoString(err.message)) 490 | } 491 | 492 | return nil 493 | } 494 | 495 | //SetSignature sets the signature on the VerifyContext 496 | func (r *VerifyContext) SetSignature(signature *Signature) error { 497 | var err C.ExternError 498 | 499 | code := C.bbs_verify_context_set_signature(r.data, signature.Buffer, &err) 500 | if code != 0 { 501 | return errors.Errorf("error occurred setting signature to BBS verify context: %s", C.GoString(err.message)) 502 | } 503 | 504 | return nil 505 | } 506 | 507 | //Finish verifies a BBS+ signature for a set of messages with a BBS public key 508 | func (r *VerifyContext) Finish() (bool, error) { 509 | var err C.ExternError 510 | code := C.bbs_verify_context_finish(r.data, &err) 511 | if err.code != 0 { 512 | return code == 0, errors.Errorf("error occurred finishing VerifyContext: %s", C.GoString(err.message)) 513 | } 514 | return code == 0, nil 515 | } 516 | 517 | type ProofContext Handle 518 | 519 | //ProofContextInit creates the proof asynchronous 520 | func ProofContextInit() (*ProofContext, error) { 521 | var err C.ExternError 522 | 523 | handle := C.bbs_create_proof_context_init(&err) 524 | if err.code != 0 { 525 | return nil, errors.Errorf("error occurred initializing BBS create proof context: %s", C.GoString(err.message)) 526 | } 527 | 528 | return &ProofContext{data: handle}, nil 529 | } 530 | 531 | type ProofMessageType int 532 | 533 | const ( 534 | Revealed ProofMessageType = 1 535 | HiddenProofSpecificBlinding ProofMessageType = 2 536 | HiddenExternalBlinding ProofMessageType = 3 537 | ) 538 | 539 | //AddProofMessage adds a proof message to the proof context 540 | func (r *ProofContext) AddProofMessages(messages []string, messageType ProofMessageType, blindingFactor HandleByteBuffer) error { 541 | var err C.ExternError 542 | var proofMessageType C.proof_message_t 543 | 544 | switch messageType { 545 | case 1: 546 | proofMessageType = C.Revealed 547 | case 2: 548 | proofMessageType = C.HiddenProofSpecificBlinding 549 | case 3: 550 | proofMessageType = C.HiddenExternalBlinding 551 | } 552 | 553 | for _, m := range messages { 554 | var message C.ByteBuffer 555 | message.len = (C.long)(len(m)) 556 | cm := C.CString(m) 557 | message.data = (*C.uchar)(unsafe.Pointer(cm)) 558 | code := C.bbs_create_proof_context_add_proof_message_bytes(r.data, message, proofMessageType, blindingFactor.Buffer, &err) 559 | if code != 0 { 560 | return errors.Errorf("error occurred adding message bytes to BBS create proof context: %s", C.GoString(err.message)) 561 | } 562 | } 563 | 564 | return nil 565 | } 566 | 567 | //SetSignature sets the signature on the ProofContext 568 | func (r *ProofContext) SetSignature(signature *Signature) error { 569 | var err C.ExternError 570 | 571 | code := C.bbs_create_proof_context_set_signature(r.data, signature.Buffer, &err) 572 | if code != 0 { 573 | return errors.Errorf("error occurred setting signature to BBS create proof context: %s", C.GoString(err.message)) 574 | } 575 | 576 | return nil 577 | } 578 | 579 | //SetPublicKey sets the bbs public key on the ProofContext 580 | func (r *ProofContext) SetPublicKey(publicKey HandleByteBuffer) error { 581 | var err C.ExternError 582 | 583 | code := C.bbs_create_proof_context_set_public_key(r.data, publicKey.Buffer, &err) 584 | if code != 0 { 585 | return errors.Errorf("error occurred setting secret key to BBS create proof context: %s", C.GoString(err.message)) 586 | } 587 | 588 | return nil 589 | } 590 | 591 | //SetNonce sets the nonce on the ProofContext 592 | func (r *ProofContext) SetNonce(nonce []byte) error { 593 | var err C.ExternError 594 | var nonceBuffer C.ByteBuffer 595 | 596 | nonceBuffer.len = (C.long)(len(nonce)) 597 | nonceBuffer.data = (*C.uchar)(unsafe.Pointer(&nonce)) 598 | 599 | code := C.bbs_create_proof_context_set_nonce_bytes(r.data, nonceBuffer, &err) 600 | if code != 0 { 601 | return errors.Errorf("error occurred setting nonce bytes on BBS create proof context: %s", C.GoString(err.message)) 602 | } 603 | 604 | return nil 605 | } 606 | 607 | type Proof HandleByteBuffer 608 | 609 | //Finish generates a proof from the ProofContext 610 | func (r *ProofContext) Finish() (*Proof, error) { 611 | var proof C.ByteBuffer 612 | var err C.ExternError 613 | 614 | code := C.bbs_create_proof_context_finish(r.data, &proof, &err) 615 | if code != 0 { 616 | return nil, errors.Errorf("error occurred finishing BBS create proof context: %s", C.GoString(err.message)) 617 | } 618 | 619 | return &Proof{Buffer: proof}, nil 620 | } 621 | 622 | //Free deallocates the proof instance 623 | func (r *Proof) Free() { 624 | C.bbs_byte_buffer_free(r.Buffer) 625 | } 626 | 627 | type VerifyProofContext Handle 628 | 629 | //VerifyProofContextInit initializes a VerifyProofContext 630 | func VerifyProofContextInit() (*VerifyProofContext, error) { 631 | var err C.ExternError 632 | 633 | handle := C.bbs_verify_proof_context_init(&err) 634 | if err.code != 0 { 635 | return nil, errors.Errorf("error occurred initializing BBS verify proof context: %s", C.GoString(err.message)) 636 | } 637 | 638 | return &VerifyProofContext{data: handle}, nil 639 | } 640 | 641 | //AddMessages adds the message and the associated index to the VerifyProofContext 642 | func (r *VerifyProofContext) AddMessage(message string, index int) error { 643 | var err C.ExternError 644 | var cMessage C.ByteBuffer 645 | 646 | cMessage.len = (C.long)(len(message)) 647 | cm := C.CString(message) 648 | cMessage.data = (*C.uchar)(unsafe.Pointer(cm)) 649 | code := C.bbs_verify_proof_context_add_message_bytes(r.data, (C.uint)(index), cMessage, &err) 650 | if code != 0 { 651 | return errors.Errorf("error occurred adding message bytes to BBS verify proof context: %s", C.GoString(err.message)) 652 | } 653 | 654 | return nil 655 | } 656 | 657 | //SetProof sets the proof on the VerifyProofContext 658 | func (r *VerifyProofContext) SetProof(proof HandleByteBuffer) error { 659 | var err C.ExternError 660 | 661 | code := C.bbs_verify_proof_context_set_proof(r.data, proof.Buffer, &err) 662 | if code != 0 { 663 | return errors.Errorf("error occurred setting proof to BBS verify proof context: %s", C.GoString(err.message)) 664 | } 665 | 666 | return nil 667 | } 668 | 669 | //SetPublicKey sets the bbs public key on the VerifyProofContext 670 | func (r *VerifyProofContext) SetPublicKey(publicKey HandleByteBuffer) error { 671 | var err C.ExternError 672 | 673 | code := C.bbs_verify_proof_context_set_public_key(r.data, publicKey.Buffer, &err) 674 | if code != 0 { 675 | return errors.Errorf("error occurred setting secret key to BBS create proof context: %s", C.GoString(err.message)) 676 | } 677 | 678 | return nil 679 | } 680 | 681 | //SetNonce sets the nonce on the VerifyProofContext 682 | func (r *VerifyProofContext) SetNonce(nonce []byte) error { 683 | var err C.ExternError 684 | var nonceBuffer C.ByteBuffer 685 | 686 | nonceBuffer.len = (C.long)(len(nonce)) 687 | nonceBuffer.data = (*C.uchar)(unsafe.Pointer(&nonce)) 688 | 689 | code := C.bbs_verify_proof_context_set_nonce_bytes(r.data, nonceBuffer, &err) 690 | if code != 0 { 691 | return errors.Errorf("error occurred setting nonce bytes on BBS create proof context: %s", C.GoString(err.message)) 692 | } 693 | 694 | return nil 695 | } 696 | 697 | //Finish verifies a proof 698 | func (r *VerifyProofContext) Finish() error { 699 | var err C.ExternError 700 | 701 | code := C.bbs_verify_proof_context_finish(r.data, &err) 702 | if err.code != 0 { 703 | return errors.Errorf("error occurred finishing BBS verify proof context: %s", C.GoString(err.message)) 704 | } 705 | 706 | if code != 200 { 707 | if ProofStatus[code] != "" { 708 | return errors.Errorf("failed to verify proof: %s", ProofStatus[code]) 709 | } 710 | return errors.Errorf("unknown error occurred verifying proof: %d", code) 711 | } 712 | 713 | return nil 714 | } 715 | 716 | var ProofStatus = map[C.int]string{ 717 | 400: "The proof failed because the signature proof of knowledge failed", 718 | 401: "The proof failed because a hidden message was invalid when the proof was created", 719 | 402: "The proof failed because a revealed message was invalid", 720 | } 721 | -------------------------------------------------------------------------------- /pkg/libursa/ursa/ursa_cl.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef enum { 5 | Success = 0, 6 | CommonInvalidParam1 = 100, 7 | CommonInvalidParam2 = 101, 8 | CommonInvalidParam3 = 102, 9 | CommonInvalidParam4 = 103, 10 | CommonInvalidParam5 = 104, 11 | CommonInvalidParam6 = 105, 12 | CommonInvalidParam7 = 106, 13 | CommonInvalidParam8 = 107, 14 | CommonInvalidParam9 = 108, 15 | CommonInvalidParam10 = 109, 16 | CommonInvalidParam11 = 110, 17 | CommonInvalidParam12 = 111, 18 | CommonInvalidState = 112, 19 | CommonInvalidStructure = 113, 20 | CommonIOError = 114, 21 | AnoncredsRevocationAccumulatorIsFull = 115, 22 | AnoncredsInvalidRevocationAccumulatorIndex = 116, 23 | AnoncredsCredentialRevoked = 117, 24 | AnoncredsProofRejected = 118, 25 | } ursa_error_t; 26 | 27 | struct ExternError { 28 | ursa_error_t code; 29 | char* message; /* note: nullable */ 30 | }; 31 | 32 | typedef uintptr_t ErrorCode; 33 | 34 | //mod 35 | 36 | /** 37 | * Get details for last occurred error. 38 | * 39 | * NOTE: Error is stored until the next one occurs. 40 | * Returning pointer has the same lifetime. 41 | * 42 | * #Params 43 | * * `error_json_p` - Reference that will contain error details (if any error has occurred before) 44 | * in the format: 45 | * { 46 | * "backtrace": Optional - error backtrace. 47 | * Collecting of backtrace can be enabled by setting environment variable `RUST_BACKTRACE=1` 48 | * "message": str - human-readable error description 49 | * } 50 | * 51 | */ 52 | extern void ursa_get_current_error(const char** error_json_p); 53 | 54 | /** 55 | * Creates random nonce. 56 | * 57 | * Note that nonce deallocation must be performed by calling ursa_cl_nonce_free. 58 | * 59 | * # Arguments 60 | * * `nonce_p` - Reference that will contain nonce instance pointer. 61 | */ 62 | struct ExternError ursa_cl_new_nonce(void** nonce_p); 63 | 64 | /** 65 | * Returns json representation of nonce. 66 | * 67 | * # Arguments 68 | * * `nonce` - Reference that contains nonce instance pointer. 69 | * * `nonce_json_p` - Reference that will contain nonce json. 70 | */ 71 | struct ExternError ursa_cl_nonce_to_json(void* nonce, const char** nonce_json_p); 72 | 73 | /** 74 | * Deallocates nonce instance. 75 | * 76 | * # Arguments 77 | * * `nonce` - Reference that contains nonce instance pointer. 78 | */ 79 | struct ExternError ursa_cl_nonce_free(const void *nonce); 80 | 81 | 82 | /** 83 | * Creates and returns nonce json. 84 | * 85 | * Note: Nonce instance deallocation must be performed by calling ursa_cl_nonce_free. 86 | * 87 | * # Arguments 88 | * * `nonce_json` - Reference that contains nonce json. 89 | * * `nonce_p` - Reference that will contain nonce instance pointer. 90 | */ 91 | struct ExternError ursa_cl_nonce_from_json(const char *nonce_json, const void **nonce_p); 92 | 93 | /** 94 | * Creates and returns credential key correctness proof from json. 95 | * 96 | * Note: Credential key correctness proof instance deallocation must be performed 97 | * by calling ursa_cl_credential_key_correctness_proof_free 98 | * 99 | * # Arguments 100 | * * `credential_key_correctness_proof_json` - Reference that contains credential key correctness proof json. 101 | * * `credential_key_correctness_proof_p` - Reference that will contain credential key correctness proof instance pointer. 102 | */ 103 | struct ExternError ursa_cl_credential_key_correctness_proof_from_json(const char *credential_key_correctness_proof_json, 104 | const void **credential_key_correctness_proof_p); 105 | 106 | /** 107 | * Creates and returns blinded credential secrets correctness proof json. 108 | * 109 | * Note: Blinded credential secrets correctness proof instance deallocation must be performed 110 | * by calling ursa_cl_blinded_credential_secrets_correctness_proof_free. 111 | * 112 | * # Arguments 113 | * * `blinded_credential_secrets_correctness_proof_json` - Reference that contains blinded credential secrets correctness proof json. 114 | * * `blinded_credential_secrets_correctness_proof_p` - Reference that will contain blinded credential secret correctness proof instance pointer. 115 | */ 116 | struct ExternError ursa_cl_blinded_credential_secrets_correctness_proof_from_json(const char *blinded_credential_secrets_correctness_proof_json, 117 | const void **blinded_credential_secrets_correctness_proof_p); 118 | 119 | /** 120 | * Creates and returns blinded credential secrets from json. 121 | * 122 | * Note: Blinded credential secrets instance deallocation must be performed 123 | * by calling ursa_cl_blinded_credential_secrets_free 124 | * 125 | * # Arguments 126 | * * `blinded_credential_secrets_json` - Reference that contains blinded credential secret json. 127 | * * `blinded_credential_secrets_p` - Reference that will contain blinded credential secret instance pointer. 128 | */ 129 | struct ExternError ursa_cl_blinded_credential_secrets_from_json(const char *blinded_credential_secrets_json, 130 | const void **blinded_credential_secrets_p); 131 | 132 | /** 133 | * Creates and returns credential private key from json. 134 | * 135 | * Note: Credential private key instance deallocation must be performed 136 | * by calling ursa_cl_credential_private_key_free 137 | * 138 | * # Arguments 139 | * * `credential_priv_key_json` - Reference that contains credential private key json. 140 | * * `credential_priv_key_p` - Reference that will contain credential private key instance pointer. 141 | */ 142 | struct ExternError ursa_cl_credential_private_key_from_json(const char *credential_priv_key_json, 143 | const void **credential_priv_key_p); 144 | /** 145 | * Returns json representation of credential private key. 146 | * 147 | * # Arguments 148 | * * `credential_priv_key` - Reference that contains credential private key instance pointer. 149 | * * `credential_pub_key_p` - Reference that will contain credential private key json. 150 | */ 151 | struct ExternError ursa_cl_credential_private_key_to_json(const void *credential_priv_key, 152 | const char **credential_priv_key_json_p); 153 | 154 | /** 155 | * Creates and returns credential public key from json. 156 | * 157 | * Note: Credential public key instance deallocation must be performed 158 | * by calling ursa_cl_credential_public_key_free 159 | * 160 | * # Arguments 161 | * * `credential_pub_key_json` - Reference that contains credential public key json. 162 | * * `credential_pub_key_p` - Reference that will contain credential public key instance pointer. 163 | */ 164 | struct ExternError ursa_cl_credential_public_key_from_json(const char *credential_pub_key_json, 165 | const void **credential_pub_key_p); 166 | /** 167 | * Returns json representation of credential public key. 168 | * 169 | * # Arguments 170 | * * `credential_pub_key` - Reference that contains credential public key instance pointer. 171 | * * `credential_pub_key_p` - Reference that will contain credential public key json. 172 | */ 173 | struct ExternError ursa_cl_credential_public_key_to_json(const void *credential_pub_key, 174 | const char **credential_pub_key_json_p); 175 | 176 | /** 177 | * Returns json representation of credential signature. 178 | * 179 | * # Arguments 180 | * * `credential_signature` - Reference that contains credential signature pointer. 181 | * * `credential_signature_json_p` - Reference that will contain credential signature json. 182 | */ 183 | struct ExternError ursa_cl_credential_signature_to_json(const void *credential_signature, 184 | const char **credential_signature_json_p); 185 | 186 | 187 | /** 188 | * Creates and returns credential signature from json. 189 | * 190 | * Note: Credential signature instance deallocation must be performed 191 | * by calling ursa_cl_credential_signature_free 192 | * 193 | * # Arguments 194 | * * `credential_signature_json` - Reference that contains credential signature json. 195 | * * `credential_signature_p` - Reference that will contain credential signature instance pointer. 196 | */ 197 | struct ExternError ursa_cl_credential_signature_from_json(const char *credential_signature_json, 198 | const void **credential_signature_p); 199 | 200 | /** 201 | * Deallocates credential signature signature instance. 202 | * 203 | * # Arguments 204 | * * `credential_signature` - Reference that contains credential signature instance pointer. 205 | */ 206 | struct ExternError ursa_cl_credential_signature_free(const void *credential_signature); 207 | 208 | /** 209 | * Signs credential values with primary keys only. 210 | * 211 | * Note that credential signature instances deallocation must be performed by 212 | * calling ursa_cl_credential_signature_free. 213 | * 214 | * Note that credential signature correctness proof instances deallocation must be performed by 215 | * calling ursa_cl_signature_correctness_proof_free. 216 | * 217 | * # Arguments 218 | * * `prover_id` - Prover identifier. 219 | * * `blinded_credential_secrets` - Blinded master secret instance pointer generated by Prover. 220 | * * `blinded_credential_secrets_correctness_proof` - Blinded master secret correctness proof instance pointer. 221 | * * `credential_nonce` - Nonce instance pointer used for verification of blinded_credential_secrets_correctness_proof. 222 | * * `credential_issuance_nonce` - Nonce instance pointer used for creation of signature_correctness_proof. 223 | * * `credential_values` - Credential values to be signed instance pointer. 224 | * * `credential_pub_key` - Credential public key instance pointer. 225 | * * `credential_priv_key` - Credential private key instance pointer. 226 | * * `credential_signature_p` - Reference that will contain credential signature instance pointer. 227 | * * `credential_signature_correctness_proof_p` - Reference that will contain credential signature correctness proof instance pointer. 228 | */ 229 | struct ExternError ursa_cl_issuer_sign_credential(const char *prover_id, 230 | const void *blinded_credential_secrets, 231 | const void *blinded_credential_secrets_correctness_proof, 232 | const void *credential_nonce, 233 | const void *credential_issuance_nonce, 234 | const void *credential_values, 235 | const void *credential_pub_key, 236 | const void *credential_priv_key, 237 | const void **credential_signature_p, 238 | const void **credential_signature_correctness_proof_p); 239 | 240 | /** 241 | * Returns json representation of signature correctness proof. 242 | * 243 | * # Arguments 244 | * * `signature_correctness_proof` - Reference that contains signature correctness proof instance pointer. 245 | * * `signature_correctness_proof_json_p` - Reference that will contain signature correctness proof json. 246 | */ 247 | struct ExternError ursa_cl_signature_correctness_proof_to_json(const void *signature_correctness_proof, 248 | const char **signature_correctness_proof_json_p); 249 | 250 | /** 251 | * Creates and returns signature correctness proof from json. 252 | * 253 | * Note: Signature correctness proof instance deallocation must be performed 254 | * by calling ursa_cl_signature_correctness_proof_free 255 | * 256 | * # Arguments 257 | * * `signature_correctness_proof_json` - Reference that contains signature correctness proof json. 258 | * * `signature_correctness_proof_p` - Reference that will contain signature correctness proof instance pointer. 259 | */ 260 | struct ExternError ursa_cl_signature_correctness_proof_from_json(const char *signature_correctness_proof_json, 261 | const void **signature_correctness_proof_p); 262 | 263 | /** 264 | * Deallocates signature correctness proof instance. 265 | * 266 | * # Arguments 267 | * * `signature_correctness_proof` - Reference that contains signature correctness proof instance pointer. 268 | */ 269 | struct ExternError ursa_cl_signature_correctness_proof_free(const void *signature_correctness_proof); 270 | 271 | 272 | 273 | /** 274 | * Deallocates blinded credential secrets correctness proof instance. 275 | * 276 | * # Arguments 277 | * * `blinded_credential_secrets_correctness_proof` - Reference that contains blinded credential secrets correctness proof instance pointer. 278 | */ 279 | struct ExternError ursa_cl_blinded_credential_secrets_correctness_proof_free(const void *blinded_credential_secrets_correctness_proof); 280 | 281 | /** 282 | * Adds new attribute to non credential schema. 283 | * 284 | * # Arguments 285 | * * `non_credential_schema_builder` - Reference that contains non credential schema builder instance pointer. 286 | * * `attr` - Attribute to add as null terminated string. 287 | */ 288 | struct ExternError ursa_cl_non_credential_schema_builder_add_attr(const void *non_credential_schema_builder, 289 | const char *attr); 290 | 291 | /** 292 | * Deallocates non_credential schema builder and returns non credential schema entity instead. 293 | * 294 | * Note: Non credential schema instance deallocation must be performed by 295 | * calling ursa_cl_non_credential_schema_free. 296 | * 297 | * # Arguments 298 | * * `non_credential_schema_builder` - Reference that contains non credential schema builder instance pointer 299 | * * `non_credential_schema_p` - Reference that will contain non credentials schema instance pointer. 300 | */ 301 | struct ExternError ursa_cl_non_credential_schema_builder_finalize(const void *non_credential_schema_builder, 302 | const void **non_credential_schema_p); 303 | 304 | /** 305 | * Creates and returns non credential schema builder. 306 | * 307 | * The purpose of non credential schema builder is building of non credential schema that 308 | * represents non credential schema attributes set. These are attributes added to schemas that are not on the ledger 309 | * 310 | * Note: Non credential schema builder instance deallocation must be performed by 311 | * calling ursa_cl_non_credential_schema_builder_finalize. 312 | * 313 | * # Arguments 314 | * * `credential_schema_builder_p` - Reference that will contain credentials attributes builder instance pointer. 315 | */ 316 | struct ExternError ursa_cl_non_credential_schema_builder_new(const void **non_credential_schema_builder_p); 317 | 318 | /** 319 | * Creates and returns credential schema entity builder. 320 | * 321 | * The purpose of credential schema builder is building of credential schema entity that 322 | * represents credential schema attributes set. 323 | * 324 | * Note: Credential schema builder instance deallocation must be performed by 325 | * calling ursa_cl_credential_schema_builder_finalize. 326 | * 327 | * # Arguments 328 | * * `credential_schema_builder_p` - Reference that will contain credentials attributes builder instance pointer. 329 | */ 330 | struct ExternError ursa_cl_credential_schema_builder_new(const void **credential_schema_builder_p); 331 | 332 | /** 333 | * Adds new attribute to credential schema. 334 | * 335 | * # Arguments 336 | * * `credential_schema_builder` - Reference that contains credential schema builder instance pointer. 337 | * * `attr` - Attribute to add as null terminated string. 338 | */ 339 | struct ExternError ursa_cl_credential_schema_builder_add_attr(const void *credential_schema_builder, 340 | const char *attr); 341 | 342 | /** 343 | * Deallocates credential schema builder and returns credential schema entity instead. 344 | * 345 | * Note: Credentials schema instance deallocation must be performed by 346 | * calling ursa_cl_credential_schema_free. 347 | * 348 | * # Arguments 349 | * * `credential_schema_builder` - Reference that contains credential schema builder instance pointer 350 | * * `credential_schema_p` - Reference that will contain credentials schema instance pointer. 351 | */ 352 | struct ExternError ursa_cl_credential_schema_builder_finalize(const void *credential_schema_builder, 353 | const void **credential_schema_p); 354 | 355 | /** 356 | * Adds new hidden attribute dec_value to credential values map. 357 | * 358 | * # Arguments 359 | * * `credential_values_builder` - Reference that contains credential values builder instance pointer. 360 | * * `attr` - Credential attr to add as null terminated string. 361 | * * `dec_value` - Credential attr dec_value. Decimal BigNum representation as null terminated string. 362 | * * `dec_blinding_factor` - Credential blinding factor. Decimal BigNum representation as null terminated string 363 | */ 364 | struct ExternError ursa_cl_credential_values_builder_add_dec_commitment(const void *credential_values_builder, 365 | const char *attr, 366 | const char *dec_value, 367 | const char *dec_blinding_factor); 368 | 369 | /** 370 | * Adds new hidden attribute dec_value to credential values map. 371 | * 372 | * # Arguments 373 | * * `credential_values_builder` - Reference that contains credential values builder instance pointer. 374 | * * `attr` - Credential attr to add as null terminated string. 375 | * * `dec_value` - Credential attr dec_value. Decimal BigNum representation as null terminated string. 376 | */ 377 | struct ExternError ursa_cl_credential_values_builder_add_dec_hidden(const void *credential_values_builder, 378 | const char *attr, 379 | const char *dec_value); 380 | 381 | /** 382 | * Adds new known attribute dec_value to credential values map. 383 | * 384 | * # Arguments 385 | * * `credential_values_builder` - Reference that contains credential values builder instance pointer. 386 | * * `attr` - Credential attr to add as null terminated string. 387 | * * `dec_value` - Credential attr dec_value. Decimal BigNum representation as null terminated string. 388 | */ 389 | struct ExternError ursa_cl_credential_values_builder_add_dec_known(const void *credential_values_builder, 390 | const char *attr, 391 | const char *dec_value); 392 | 393 | /** 394 | * Deallocates credential values builder and returns credential values entity instead. 395 | * 396 | * Note: Credentials values instance deallocation must be performed by 397 | * calling ursa_cl_credential_values_free. 398 | * 399 | * # Arguments 400 | * * `credential_values_builder` - Reference that contains credential attribute builder instance pointer. 401 | * * `credential_values_p` - Reference that will contain credentials values instance pointer. 402 | */ 403 | struct ExternError ursa_cl_credential_values_builder_finalize(const void *credential_values_builder, 404 | const void **credential_values_p); 405 | 406 | /** 407 | * Creates and returns credentials values entity builder. 408 | * 409 | * The purpose of credential values builder is building of credential values entity that 410 | * represents credential attributes values map. 411 | * 412 | * Note: Credentials values builder instance deallocation must be performed by 413 | * calling ursa_cl_credential_values_builder_finalize. 414 | * 415 | * # Arguments 416 | * * `credential_values_builder_p` - Reference that will contain credentials values builder instance pointer. 417 | */ 418 | struct ExternError ursa_cl_credential_values_builder_new(const void **credential_values_builder_p); 419 | 420 | /** 421 | * Creates and returns credential values json. 422 | * 423 | * Note: Credential values instance deallocation must be performed by calling ursa_cl_credential_values_free. 424 | * 425 | * # Arguments 426 | * * `credential_values_json` - Reference that contains credential values json. 427 | * * `credential_values_p` - Reference that will contain credential values instance pointer. 428 | */ 429 | struct ExternError ursa_cl_credential_values_from_json(const char *credential_values_json, const void **credential_values_p); 430 | 431 | /** 432 | * Returns json representation of credential values. 433 | * 434 | * # Arguments 435 | * * `credential_values` - Reference that contains credential values instance pointer. 436 | * * `credential_values_json_p` - Reference that will contain credential values json. 437 | */ 438 | struct ExternError ursa_cl_credential_values_to_json(const void *credential_values, const char **credential_values_json_p); 439 | 440 | /** 441 | * Deallocates credential values instance. 442 | * 443 | * # Arguments 444 | * * `credential_values` - Credential values instance pointer 445 | */ 446 | struct ExternError ursa_cl_credential_values_free(const void *credential_values); 447 | 448 | /** 449 | * Creates and returns credential definition (public and private keys, correctness proof) entities. 450 | * 451 | * Note that credential public key instances deallocation must be performed by 452 | * calling ursa_cl_credential_public_key_free. 453 | * 454 | * Note that credential private key instances deallocation must be performed by 455 | * calling ursa_cl_credential_private_key_free. 456 | * 457 | * Note that credential key correctness proof instances deallocation must be performed by 458 | * calling ursa_cl_credential_key_correctness_proof_free. 459 | * 460 | * # Arguments 461 | * * `credential_schema` - Reference that contains credential schema instance pointer. 462 | * * `non_credential_schema` - Reference that contains non credential schema instance pointer 463 | * * `support_revocation` - If true non revocation part of credential keys will be generated. 464 | * * `credential_pub_key_p` - Reference that will contain credential public key instance pointer. 465 | * * `credential_priv_key_p` - Reference that will contain credential private key instance pointer. 466 | * * `credential_key_correctness_proof_p` - Reference that will contain credential keys correctness proof instance pointer. 467 | */ 468 | struct ExternError ursa_cl_issuer_new_credential_def(const void *credential_schema, 469 | const void *non_credential_schema, 470 | _Bool support_revocation, 471 | const void **credential_pub_key_p, 472 | const void **credential_priv_key_p, 473 | const void **credential_key_correctness_proof_p); 474 | 475 | /** 476 | * Deallocates credential schema instance. 477 | * 478 | * # Arguments 479 | * * `credential_schema` - Reference that contains credential schema instance pointer. 480 | */ 481 | struct ExternError ursa_cl_credential_schema_free(const void *credential_schema); 482 | 483 | /** 484 | * Deallocates credential key correctness proof instance. 485 | * 486 | * # Arguments 487 | * * `credential_key_correctness_proof` - Reference that contains credential key correctness proof instance pointer. 488 | */ 489 | struct ExternError ursa_cl_credential_key_correctness_proof_free(const void *credential_key_correctness_proof); 490 | 491 | /** 492 | * Deallocates credential schema instance. 493 | * 494 | * # Arguments 495 | * * `non_credential_schema` - Reference that contains non credential schema instance pointer. 496 | */ 497 | struct ExternError ursa_cl_non_credential_schema_free(const void *non_credential_schema); 498 | 499 | /** 500 | * Deallocates credential private key instance. 501 | * 502 | * # Arguments 503 | * * `credential_priv_key` - Reference that contains credential private key instance pointer. 504 | */ 505 | struct ExternError ursa_cl_credential_private_key_free(const void *credential_priv_key); 506 | 507 | /** 508 | * Deallocates credential public key instance. 509 | * 510 | * # Arguments 511 | * * `credential_pub_key` - Reference that contains credential public key instance pointer. 512 | */ 513 | struct ExternError ursa_cl_credential_public_key_free(const void *credential_pub_key); 514 | 515 | /** 516 | * Creates and returns proof builder. 517 | * 518 | * The purpose of proof builder is building of proof entity according to the given request . 519 | * 520 | * Note that proof builder deallocation must be performed by 521 | * calling ursa_cl_proof_builder_finalize. 522 | * 523 | * # Arguments 524 | * * `proof_builder_p` - Reference that will contain proof builder instance pointer. 525 | */ 526 | struct ExternError ursa_cl_prover_new_proof_builder(const void **proof_builder_p); 527 | 528 | 529 | 530 | /** 531 | * Add a common attribute to the proof builder 532 | * 533 | * # Arguments 534 | * * `proof_builder` - Reference that contain proof builder instance pointer. 535 | * * `attribute_name` - Common attribute's name 536 | */ 537 | struct ExternError ursa_cl_proof_builder_add_common_attribute(const void *proof_builder, 538 | const char *attribute_name); 539 | 540 | /** 541 | * Add a sub proof request to the proof builder 542 | * 543 | * # Arguments 544 | * * `proof_builder` - Reference that contain proof builder instance pointer. 545 | * * `sub_proof_request` - Reference that contain sub proof request instance pointer. 546 | * * `credential_schema` - Reference that contains credential schema instance pointer. 547 | * * `non_credential_schema` - Reference that contains non credential schema instance pointer. 548 | * * `credential_signature` - Reference that contains the credential signature pointer. 549 | * * `credential_values` - Reference that contains credential values instance pointer. 550 | * * `credential_pub_key` - Reference that contains credential public key instance pointer. 551 | * * `rev_reg` - (Optional) Reference that will contain revocation registry public instance pointer. 552 | * * `witness` - (Optional) Reference that will contain witness instance pointer. 553 | */ 554 | struct ExternError ursa_cl_proof_builder_add_sub_proof_request(const void *proof_builder, 555 | const void *sub_proof_request, 556 | const void *credential_schema, 557 | const void *non_credential_schema, 558 | const void *credential_signature, 559 | const void *credential_values, 560 | const void *credential_pub_key, 561 | const void *rev_reg, 562 | const void *witness); 563 | 564 | /** 565 | * Finalize proof. 566 | * 567 | * Note that proof deallocation must be performed by 568 | * calling ursa_cl_proof_free. 569 | * 570 | * # Arguments 571 | * * `proof_builder` - Reference that contain proof builder instance pointer. 572 | * * `nonce` - Reference that contain nonce instance pointer. 573 | * * `proof_p` - Reference that will contain proof instance pointer. 574 | */ 575 | struct ExternError ursa_cl_proof_builder_finalize(const void *proof_builder, 576 | const void *nonce, 577 | const void **proof_p); 578 | 579 | /** 580 | * Deallocates proof instance. 581 | * 582 | * # Arguments 583 | * * `proof` - Reference that contains proof instance pointer. 584 | */ 585 | struct ExternError ursa_cl_proof_free(const void *proof); 586 | 587 | /** 588 | * Creates and returns proof json. 589 | * 590 | * Note: Proof instance deallocation must be performed by calling ursa_cl_proof_free. 591 | * 592 | * # Arguments 593 | * * `proof_json` - Reference that contains proof json. 594 | * * `proof_p` - Reference that will contain proof instance pointer. 595 | */ 596 | struct ExternError ursa_cl_proof_from_json(const char *proof_json, const void **proof_p); 597 | 598 | /** 599 | * Returns json representation of proof. 600 | * 601 | * # Arguments 602 | * * `proof` - Reference that contains proof instance pointer. 603 | * * `proof_json_p` - Reference that will contain proof json. 604 | */ 605 | struct ExternError ursa_cl_proof_to_json(const void *proof, const char **proof_json_p); 606 | 607 | /** 608 | * Creates and returns sub proof request entity builder. 609 | * 610 | * The purpose of sub proof request builder is building of sub proof request entity that 611 | * represents requested attributes and predicates. 612 | * 613 | * Note: sub proof request builder instance deallocation must be performed by 614 | * calling ursa_cl_sub_proof_request_builder_finalize. 615 | * 616 | * # Arguments 617 | * * `sub_proof_request_builder_p` - Reference that will contain sub proof request builder instance pointer. 618 | */ 619 | struct ExternError ursa_cl_sub_proof_request_builder_new(const void **sub_proof_request_builder_p); 620 | 621 | /** 622 | * Adds predicate to sub proof request. 623 | * 624 | * # Arguments 625 | * * `sub_proof_request_builder` - Reference that contains sub proof request builder instance pointer. 626 | * * `attr_name` - Related attribute 627 | * * `p_type` - Predicate type (Currently `GE` only). 628 | * * `value` - Requested value. 629 | */ 630 | struct ExternError ursa_cl_sub_proof_request_builder_add_predicate(const void *sub_proof_request_builder, 631 | const char *attr_name, 632 | const char *p_type, 633 | int32_t value); 634 | 635 | /** 636 | * Adds new revealed attribute to sub proof request. 637 | * 638 | * # Arguments 639 | * * `sub_proof_request_builder` - Reference that contains sub proof request builder instance pointer. 640 | * * `attr` - Credential attr to add as null terminated string. 641 | */ 642 | struct ExternError ursa_cl_sub_proof_request_builder_add_revealed_attr(const void *sub_proof_request_builder, 643 | const char *attr); 644 | 645 | /** 646 | * Deallocates sub proof request builder and returns sub proof request entity instead. 647 | * 648 | * Note: Sub proof request instance deallocation must be performed by 649 | * calling ursa_cl_sub_proof_request_free. 650 | * 651 | * # Arguments 652 | * * `sub_proof_request_builder` - Reference that contains sub proof request builder instance pointer. 653 | * * `sub_proof_request_p` - Reference that will contain sub proof request instance pointer. 654 | */ 655 | struct ExternError ursa_cl_sub_proof_request_builder_finalize(const void *sub_proof_request_builder, 656 | const void **sub_proof_request_p); 657 | 658 | /** 659 | * Deallocates sub proof request instance. 660 | * 661 | * # Arguments 662 | * * `sub_proof_request` - Reference that contains sub proof request instance pointer. 663 | */ 664 | struct ExternError ursa_cl_sub_proof_request_free(const void *sub_proof_request); 665 | 666 | /** 667 | * Returns json representation of credential key correctness proof. 668 | * 669 | * # Arguments 670 | * * `credential_key_correctness_proof` - Reference that contains credential key correctness proof instance pointer. 671 | * * `credential_key_correctness_proof_p` - Reference that will contain credential key correctness proof json. 672 | */ 673 | struct ExternError ursa_cl_credential_key_correctness_proof_to_json(const void *credential_key_correctness_proof, 674 | const char **credential_key_correctness_proof_json_p); 675 | 676 | /** 677 | * Creates blinded credential secrets for given issuer key and master secret. 678 | * 679 | * Note that blinded credential secrets deallocation must be performed by 680 | * calling ursa_cl_blinded_credential_secrets_free. 681 | * 682 | * Note that credential secrets blinding factors deallocation must be performed by 683 | * calling ursa_cl_credential_secrets_blinding_factors_free. 684 | * 685 | * Note that blinded credential secrets correctness proof deallocation must be performed by 686 | * calling ursa_cl_blinded_credential_secrets_correctness_proof_free. 687 | * 688 | * # Arguments 689 | * * `credential_pub_key` - Reference that contains credential public key instance pointer. 690 | * * `credential_key_correctness_proof` - Reference that contains credential key correctness proof instance pointer. 691 | * * `credential_values` - Reference that contains credential values pointer. 692 | * * `credential_nonce` - Reference that contains nonce instance pointer. 693 | * * `blinded_credential_secrets_p` - Reference that will contain blinded credential secrets instance pointer. 694 | * * `credential_secrets_blinding_factors_p` - Reference that will contain credential secrets blinding factors instance pointer. 695 | * * `blinded_credential_secrets_correctness_proof_p` - Reference that will contain blinded credential secrets correctness proof instance pointer. 696 | */ 697 | struct ExternError ursa_cl_prover_blind_credential_secrets(const void *credential_pub_key, 698 | const void *credential_key_correctness_proof, 699 | const void *credential_values, 700 | const void *credential_nonce, 701 | const void **blinded_credential_secrets_p, 702 | const void **credential_secrets_blinding_factors_p, 703 | const void **blinded_credential_secrets_correctness_proof_p); 704 | 705 | /** 706 | * Returns json representation of blinded credential secrets correctness proof. 707 | * 708 | * # Arguments 709 | * * `blinded_credential_secrets_correctness_proof` - Reference that contains blinded credential secrets correctness proof pointer. 710 | * * `blinded_credential_secrets_correctness_proof_json_p` - Reference that will contain blinded credential secrets correctness proof json. 711 | */ 712 | struct ExternError ursa_cl_blinded_credential_secrets_correctness_proof_to_json(const void *blinded_credential_secrets_correctness_proof, 713 | const char **blinded_credential_secrets_correctness_proof_json_p); 714 | 715 | /** 716 | * Deallocates blinded credential secrets correctness proof instance. 717 | * 718 | * # Arguments 719 | * * `blinded_credential_secrets_correctness_proof` - Reference that contains blinded credential secrets correctness proof instance pointer. 720 | */ 721 | struct ExternError ursa_cl_blinded_credential_secrets_correctness_proof_free(const void *blinded_credential_secrets_correctness_proof); 722 | 723 | 724 | /** 725 | * Deallocates credential secrets blinding factors instance. 726 | * 727 | * # Arguments 728 | * * `credential_secrets_blinding_factors` - Reference that contains credential secrets blinding factors instance pointer. 729 | */ 730 | struct ExternError ursa_cl_credential_secrets_blinding_factors_free(const void *credential_secrets_blinding_factors); 731 | 732 | /** 733 | * Creates and returns credential secrets blinding factors json. 734 | * 735 | * Note: Credential secrets blinding factors instance deallocation must be performed 736 | * by calling ursa_cl_credential_secrets_blinding_factors_free. 737 | * 738 | * # Arguments 739 | * * `credential_secrets_blinding_factors_json` - Reference that contains credential secrets blinding factors json. 740 | * * `credential_secrets_blinding_factors_p` - Reference that will contain credential secrets blinding factors instance pointer. 741 | */ 742 | struct ExternError ursa_cl_credential_secrets_blinding_factors_from_json(const char *credential_secrets_blinding_factors_json, 743 | const void **credential_secrets_blinding_factors_p); 744 | 745 | /** 746 | * Returns json representation of credential secrets blinding factors. 747 | * 748 | * # Arguments 749 | * * `credential_secrets_blinding_factors` - Reference that contains credential secrets blinding factors pointer. 750 | * * `credential_secrets_blinding_factors_json_p` - Reference that will contain credential secrets blinding factors json. 751 | */ 752 | struct ExternError ursa_cl_credential_secrets_blinding_factors_to_json(const void *credential_secrets_blinding_factors, 753 | const char **credential_secrets_blinding_factors_json_p); 754 | 755 | 756 | /** 757 | * Returns json representation of blinded credential secrets. 758 | * 759 | * # Arguments 760 | * * `blinded_credential_secrets` - Reference that contains Blinded credential secrets pointer. 761 | * * `blinded_credential_secrets_json_p` - Reference that will contain blinded credential secrets json. 762 | */ 763 | struct ExternError ursa_cl_blinded_credential_secrets_to_json(const void *blinded_credential_secrets, 764 | const char **blinded_credential_secrets_json_p); 765 | 766 | /** 767 | * Deallocates blinded credential secrets instance. 768 | * 769 | * # Arguments 770 | * * `blinded_credential_secrets` - Reference that contains blinded credential secrets instance pointer. 771 | */ 772 | struct ExternError ursa_cl_blinded_credential_secrets_free(const void *blinded_credential_secrets); 773 | 774 | /** 775 | * Creates a master secret. 776 | * 777 | * Note that master secret deallocation must be performed by 778 | * calling ursa_cl_master_secret_free. 779 | * 780 | * # Arguments 781 | * * `master_secret_p` - Reference that will contain master secret instance pointer. 782 | */ 783 | struct ExternError ursa_cl_prover_new_master_secret(const void **master_secret_p); 784 | 785 | /** 786 | * Deallocates master secret instance. 787 | * 788 | * # Arguments 789 | * * `master_secret` - Reference that contains master secret instance pointer. 790 | */ 791 | struct ExternError ursa_cl_master_secret_free(const void *master_secret); 792 | 793 | /** 794 | * Creates and returns master secret from json. 795 | * 796 | * Note: Master secret instance deallocation must be performed 797 | * by calling ursa_cl_master_secret_free. 798 | * 799 | * # Arguments 800 | * * `master_secret_json` - Reference that contains master secret json. 801 | * * `master_secret_p` - Reference that will contain master secret instance pointer. 802 | */ 803 | struct ExternError ursa_cl_master_secret_from_json(const char *master_secret_json, 804 | const void **master_secret_p); 805 | 806 | /** 807 | * Returns json representation of master secret. 808 | * 809 | * # Arguments 810 | * * `master_secret` - Reference that contains master secret instance pointer. 811 | * * `master_secret_json_p` - Reference that will contain master secret json. 812 | */ 813 | struct ExternError ursa_cl_master_secret_to_json(const void *master_secret, 814 | const char **master_secret_json_p); 815 | 816 | /** 817 | * Creates and returns proof verifier. 818 | * 819 | * Note that proof verifier deallocation must be performed by 820 | * calling ursa_cl_proof_verifier_finalize. 821 | * 822 | * # Arguments 823 | * * `proof_verifier_p` - Reference that will contain proof verifier instance pointer. 824 | */ 825 | struct ExternError ursa_cl_verifier_new_proof_verifier(const void **proof_verifier_p); 826 | 827 | 828 | /** 829 | * Verifies proof and deallocates proof verifier. 830 | * 831 | * # Arguments 832 | * * `proof_verifier` - Reference that contain proof verifier instance pointer. 833 | * * `proof` - Reference that contain proof instance pointer. 834 | * * `nonce` - Reference that contain nonce instance pointer. 835 | * * `valid_p` - Reference that will be filled with true - if proof valid or false otherwise. 836 | */ 837 | struct ExternError ursa_cl_proof_verifier_verify(const void *proof_verifier, 838 | const void *proof, 839 | const void *nonce, 840 | bool *valid_p); 841 | 842 | /** 843 | * Add a common attribute to the proof verifier 844 | * 845 | * # Arguments 846 | * * `proof_builder` - Reference that contain proof verifier instance pointer. 847 | * * `attribute_name` - Common attribute's name 848 | */ 849 | struct ExternError ursa_cl_proof_verifier_add_common_attribute(const void *proof_verifier, 850 | const char *attribute_name); 851 | 852 | struct ExternError ursa_cl_proof_verifier_add_sub_proof_request(const void *proof_verifier, 853 | const void *sub_proof_request, 854 | const void *credential_schema, 855 | const void *non_credential_schema, 856 | const void *credential_pub_key, 857 | const void *rev_key_pub, 858 | const void *rev_reg); 859 | 860 | /** 861 | * Updates the credential signature by a credential secrets blinding factors. 862 | * 863 | * # Arguments 864 | * * `credential_signature` - Credential signature instance pointer generated by Issuer. 865 | * * `credential_values` - Credential values instance pointer. 866 | * * `signature_correctness_proof` - Credential signature correctness proof instance pointer. 867 | * * `credential_secrets_blinding_factors` - Credential secrets blinding factors instance pointer. 868 | * * `credential_pub_key` - Credential public key instance pointer. 869 | * * `nonce` - Nonce instance pointer was used by Issuer for the creation of signature_correctness_proof. 870 | * * `rev_key_pub` - (Optional) Revocation registry public key instance pointer. 871 | * * `rev_reg` - (Optional) Revocation registry instance pointer. 872 | * * `witness` - (Optional) Witness instance pointer. 873 | */ 874 | struct ExternError ursa_cl_prover_process_credential_signature(const void *credential_signature, 875 | const void *credential_values, 876 | const void *signature_correctness_proof, 877 | const void *credential_secrets_blinding_factors, 878 | const void *credential_pub_key, 879 | const void *credential_issuance_nonce, 880 | const void *rev_key_pub, 881 | const void *rev_reg, 882 | const void *witness); 883 | 884 | --------------------------------------------------------------------------------