Skip to content
This repository has been archived by the owner on Apr 27, 2023. It is now read-only.

Commit

Permalink
Wrapper for signing credentials as well as generating a proof. Includ…
Browse files Browse the repository at this point in the history
…es a refactor of some existing methods to match a pattern to encapsulate the `unsafe.Pointer` handles from callers. (#25)

Signed-off-by: Phil Feairheller <[email protected]>
  • Loading branch information
pfeairheller authored Dec 10, 2020
1 parent 1be50fe commit d1d4d04
Show file tree
Hide file tree
Showing 10 changed files with 1,483 additions and 231 deletions.
131 changes: 131 additions & 0 deletions pkg/libursa/ursa/credential_definition_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package ursa

import (
"encoding/json"
"math/big"
"testing"

"github.com/stretchr/testify/assert"
)

func TestCredentialDefinition(t *testing.T) {
t.Run("happy path", func(t *testing.T) {
fields := []string{"attr1", "attr2", "attr3"}
var nonfields []string

credDef := createCredentialDefinition(t, fields, nonfields)

pubKeyJSON, err := credDef.PubKey.ToJSON()
assert.NoError(t, err)
m := map[string]interface{}{}
err = json.Unmarshal(pubKeyJSON, &m)
assert.NoError(t, err)

pkey, ok := m["p_key"].(map[string]interface{})
assert.True(t, ok)

r, ok := pkey["r"].(map[string]interface{})
assert.True(t, ok)

for _, field := range fields {
x, ok := r[field].(string)
assert.True(t, ok)
i := new(big.Int)
_, ok = i.SetString(x, 10)
assert.True(t, ok)
}

privKeyJSON, err := credDef.PrivKey.ToJSON()
assert.NoError(t, err)
assert.NotEmpty(t, privKeyJSON)

correctnessJSON, err := credDef.PubKey.ToJSON()
assert.NoError(t, err)

m = map[string]interface{}{}
err = json.Unmarshal(correctnessJSON, &m)
assert.NoError(t, err)

pkey, ok = m["p_key"].(map[string]interface{})
assert.True(t, ok)

r, ok = pkey["r"].(map[string]interface{})
assert.True(t, ok)

for _, field := range fields {
x, ok := r[field].(string)
assert.True(t, ok)
i := new(big.Int)
_, ok = i.SetString(x, 10)
assert.True(t, ok)
}

err = credDef.PubKey.Free()
assert.NoError(t, err)

err = credDef.PrivKey.Free()
assert.NoError(t, err)

err = credDef.KeyCorrectnessProof.Free()
assert.NoError(t, err)
})
}

func createCredentialDefinition(t *testing.T, fields, nonfields []string) *CredentialDef {

fields = append(fields, "master_secret")

schema := createSchema(t, fields)

nonschema := createNonSchema(t, nonfields)

credDef, err := NewCredentialDef(schema, nonschema, false)
assert.NoError(t, err)

return credDef
}

func createSchema(t *testing.T, fields []string) *CredentialSchemaHandle {
schemaBuilder, err := NewCredentialSchemaBuilder()
assert.NoError(t, err)

for _, field := range fields {
err = schemaBuilder.AddAttr(field)
assert.NoError(t, err)
}

schema, err := schemaBuilder.Finalize()
assert.NoError(t, err)

return schema
}

func createNonSchema(t *testing.T, fields []string) *NonCredentialSchemaHandle {
nonSchemaBuilder, err := NewNonCredentialSchemaBuilder()
assert.NoError(t, err)

for _, field := range fields {
err = nonSchemaBuilder.AddAttr(field)
assert.NoError(t, err)
}

nonSchema, err := nonSchemaBuilder.Finalize()
assert.NoError(t, err)

return nonSchema
}

func createValues(t *testing.T, values map[string]interface{}) *CredentialValues {
builder, err := NewValueBuilder()
assert.NoError(t, err)

for k, v := range values {
err = builder.AddDecKnown(k, EncodeValue(v))
assert.NoError(t, err)
}

value, err := builder.Finalize()
assert.NoError(t, err)

return value
}
60 changes: 60 additions & 0 deletions pkg/libursa/ursa/master_secret.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package ursa

/*
#cgo LDFLAGS: -lursa
#include "ursa_cl.h"
#include <stdlib.h>
*/
import "C"
import (
"unsafe"
)

type MasterSecret Handle

func NewMasterSecret() (*MasterSecret, error) {
var ms unsafe.Pointer

result := C.ursa_cl_prover_new_master_secret(&ms)
if result.code != 0 {
return nil, ursaError(C.GoString(result.message))
}

return &MasterSecret{ms}, nil
}

//MasterSecretFromJson creates and returns nonce json
func MasterSecretFromJSON(jsn []byte) (*MasterSecret, error) {
var handle unsafe.Pointer
cjson := C.CString(string(jsn))
defer C.free(unsafe.Pointer(cjson))

result := C.ursa_cl_master_secret_from_json(cjson, &handle)
if result.code != 0 {
return nil, ursaError(C.GoString(result.message))
}

return &MasterSecret{handle}, nil
}

func (r *MasterSecret) ToJSON() ([]byte, error) {
var d *C.char
defer C.free(unsafe.Pointer(d))

result := C.ursa_cl_master_secret_to_json(r.ptr, &d)
if result.code != 0 {
return nil, ursaError(C.GoString(result.message))
}

out := []byte(C.GoString(d))
return out, nil
}

func (r *MasterSecret) Free() error {
result := C.ursa_cl_master_secret_free(r.ptr)
if result.code != 0 {
return ursaError(C.GoString(result.message))
}

return nil
}
42 changes: 42 additions & 0 deletions pkg/libursa/ursa/master_secret_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package ursa

import (
"encoding/json"
"math/big"
"testing"

"github.com/stretchr/testify/assert"
)

func TestMasterSecret(t *testing.T) {
t.Run("happy path", func(t *testing.T) {
ms, err := NewMasterSecret()
assert.NoError(t, err)

js, err := ms.ToJSON()
assert.NoError(t, err)

m := struct {
MasterSecret string `json:"ms"`
}{}
err = json.Unmarshal(js, &m)
assert.NoError(t, err)

i := new(big.Int)
_, ok := i.SetString(m.MasterSecret, 10)
assert.True(t, ok)

ms, err = MasterSecretFromJSON(js)
assert.NoError(t, err)
assert.NotEmpty(t, ms)

err = ms.Free()
assert.NoError(t, err)
})

t.Run("bad json", func(t *testing.T) {
ms, err := MasterSecretFromJSON([]byte(`{"t": "123"}`))
assert.Error(t, err)
assert.Empty(t, ms)
})
}
155 changes: 155 additions & 0 deletions pkg/libursa/ursa/proof_builder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package ursa

/*
#cgo LDFLAGS: -lursa
#include "ursa_cl.h"
#include <stdlib.h>
*/
import "C"
import (
"unsafe"
)

type ProofBuilder Handle
type ProofHandle Handle

func NewProofBuilder() (*ProofBuilder, error) {
var builder unsafe.Pointer

result := C.ursa_cl_prover_new_proof_builder(&builder)
if result.code != 0 {
return nil, ursaError(C.GoString(result.message))
}

return &ProofBuilder{builder}, nil
}

func ProofFromJSON(jsn []byte) (*ProofHandle, error) {
var builder unsafe.Pointer
cjson := C.CString(string(jsn))
defer C.free(unsafe.Pointer(cjson))

result := C.ursa_cl_proof_from_json(cjson, &builder)
if result.code != 0 {
return nil, ursaError(C.GoString(result.message))
}

return &ProofHandle{builder}, nil
}

func (r *ProofBuilder) AddCommonAttribute(attr string) error {
cattr := C.CString(attr)
defer C.free(unsafe.Pointer(cattr))

result := C.ursa_cl_proof_builder_add_common_attribute(r.ptr, cattr)
if result.code != 0 {
return ursaError(C.GoString(result.message))
}

return nil
}

func (r *ProofBuilder) AddSubProofRequest(subProof *SubProofRequestHandle, credSchema *CredentialSchemaHandle,
nonCredSchema *NonCredentialSchemaHandle, signature *CredentialSignature, values *CredentialValues, pubKey *CredentialDefPubKey) error {

result := C.ursa_cl_proof_builder_add_sub_proof_request(r.ptr, subProof.ptr, credSchema.ptr, nonCredSchema.ptr,
signature.ptr, values.ptr, pubKey.ptr /*revoc_reg*/, nil /*witness*/, nil)
if result.code != 0 {
return ursaError(C.GoString(result.message))
}

return nil
}

func (r *ProofBuilder) Finalize(nonce *Nonce) (*ProofHandle, error) {
var proof unsafe.Pointer

result := C.ursa_cl_proof_builder_finalize(r.ptr, nonce.ptr, &proof)
if result.code != 0 {
return nil, ursaError(C.GoString(result.message))
}

return &ProofHandle{proof}, nil
}

func (r *ProofHandle) ToJSON() ([]byte, error) {
var d *C.char
defer C.free(unsafe.Pointer(d))

result := C.ursa_cl_proof_to_json(r.ptr, &d)
if result.code != 0 {
return nil, ursaError(C.GoString(result.message))
}

return []byte(C.GoString(d)), nil
}

func (r *ProofHandle) Free() error {
result := C.ursa_cl_proof_free(r.ptr)
if result.code != 0 {
return ursaError(C.GoString(result.message))
}

return nil
}

type SubProofRequestBuilder Handle
type SubProofRequestHandle Handle

func NewSubProofRequestBuilder() (*SubProofRequestBuilder, error) {
var builder unsafe.Pointer

result := C.ursa_cl_sub_proof_request_builder_new(&builder)
if result.code != 0 {
return nil, ursaError(C.GoString(result.message))
}

return &SubProofRequestBuilder{builder}, nil

}

func (r *SubProofRequestBuilder) AddPredicate(attr, ptype string, value int32) error {
cattr := C.CString(attr)
defer C.free(unsafe.Pointer(cattr))
cptype := C.CString(ptype)
defer C.free(unsafe.Pointer(cptype))

result := C.ursa_cl_sub_proof_request_builder_add_predicate(r.ptr, cattr, cptype, C.int32_t(value))
if result.code != 0 {
return ursaError(C.GoString(result.message))
}

return nil
}

func (r *SubProofRequestBuilder) AddRevealedAttr(attr string) error {
cattr := C.CString(attr)
defer C.free(unsafe.Pointer(cattr))

result := C.ursa_cl_sub_proof_request_builder_add_revealed_attr(r.ptr, cattr)
if result.code != 0 {
return ursaError(C.GoString(result.message))
}

return nil
}

func (r *SubProofRequestBuilder) Finalize() (*SubProofRequestHandle, error) {
var proof unsafe.Pointer

result := C.ursa_cl_sub_proof_request_builder_finalize(r.ptr, &proof)
if result.code != 0 {
return nil, ursaError(C.GoString(result.message))
}

return &SubProofRequestHandle{proof}, nil
}

func (r *SubProofRequestHandle) Free() error {
result := C.ursa_cl_sub_proof_request_free(r.ptr)
if result.code != 0 {
return ursaError(C.GoString(result.message))
}

return nil
}
Loading

0 comments on commit d1d4d04

Please sign in to comment.