Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for BLS keys and BBS+ signatures #288

Merged
merged 59 commits into from
Mar 23, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
5d3e9cf
simple bbs key usage
Feb 15, 2023
47d5a63
some progress
Feb 17, 2023
ff80ef6
progress
Feb 17, 2023
ba641de
Merge branch 'main' into bbs-plus
decentralgabe Feb 17, 2023
425adbd
switch to any
Feb 17, 2023
f28b789
sign verify working
Feb 18, 2023
50e56c6
create derive proof
Feb 18, 2023
24c1d20
implemented but untested
Feb 18, 2023
835c3e3
some bugs
Feb 18, 2023
f783cc0
fix test issue
Feb 20, 2023
42cc8e2
not passing test vector yet
Feb 20, 2023
7eeb7b3
problem with bls verify
Feb 20, 2023
1402b90
fix test vector
Feb 21, 2023
e477161
problem with signing and derive verify
Feb 21, 2023
d6e597d
fix signing with suite
Feb 21, 2023
39c8c84
it works
Feb 21, 2023
4e34014
tests pass
Feb 21, 2023
384f5e4
not there yet
Feb 22, 2023
2d8630e
progress with nonces
Feb 22, 2023
c196a03
one bug fixed
Feb 22, 2023
340d947
same input different output
Feb 22, 2023
c72ce22
add compaction
Feb 22, 2023
23f5e49
not working fully
Feb 22, 2023
77be15e
bbs+ working
Feb 22, 2023
2319afb
Merge branch 'main' into bbs-plus
decentralgabe Feb 22, 2023
7e4c63f
fix lint
Feb 22, 2023
e2cb937
revert map any replacement
Feb 22, 2023
70bba0a
remove more any
Feb 22, 2023
1650236
more replacements
Feb 22, 2023
90b1106
more replacements
Feb 22, 2023
28d9e70
more more
Feb 22, 2023
c6d2e8d
fix lint
Feb 22, 2023
cdb2cba
more lints
Feb 22, 2023
a90fa5a
final ones
Feb 22, 2023
8b317af
Update crypto/bbs_test.go
decentralgabe Feb 23, 2023
38119e6
Update cryptosuite/bbsplussignaturesuite.go
decentralgabe Feb 23, 2023
2ca6a48
pr comments
Feb 23, 2023
54cda26
more comments
Feb 23, 2023
b6ae137
better err messages
Feb 23, 2023
eb8fdf3
Update cryptosuite/bbsplussignaturesuite.go
decentralgabe Feb 23, 2023
310b499
pr comments
Feb 23, 2023
e7883da
Merge remote-tracking branch 'origin/bbs-plus' into bbs-plus
Feb 23, 2023
8f98524
remove provable from cvh
Feb 23, 2023
805f1a2
pr comments
Feb 23, 2023
b84cfdb
move generic provable
Feb 23, 2023
425b0c6
pr comments
Feb 23, 2023
2b73629
Merge branch 'main' into bbs-plus
decentralgabe Feb 28, 2023
a981ef8
Update cryptosuite/bbsplussignaturesuite.go
decentralgabe Mar 21, 2023
3e816a5
pr comments
Mar 21, 2023
0d36a93
Update cryptosuite/bbsplussignatureproofsuite.go
decentralgabe Mar 21, 2023
7d968e2
Update cryptosuite/bbsplussignatureproofsuite.go
decentralgabe Mar 21, 2023
247339f
pr comments
Mar 21, 2023
b172d0a
Merge remote-tracking branch 'origin/main' into bbs-plus
Mar 21, 2023
625fe9c
merge
Mar 21, 2023
5562aa0
simpler proof handling
Mar 21, 2023
66c7a3f
update re:pr comments
Mar 22, 2023
f1fee95
Merge remote-tracking branch 'origin/main' into bbs-plus
Mar 22, 2023
4f1c00b
merge
Mar 22, 2023
fc73c86
pr comment
Mar 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/idea-submission.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Idea Submission
about: Suggest an idea for this project
title: "[Idea] <Idea Title Here>"
labels: enhancement
assignees: decentralgabe, nitro-neal
assignees: decentralgabe, nitro-neal, andresuribe87

---

Expand Down
24 changes: 12 additions & 12 deletions credential/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const (

// VerifiableCredentialBuilder uses the builder pattern to construct a verifiable credential
type VerifiableCredentialBuilder struct {
// contexts and types are kept to avoid having cast to/from interface{} values
// contexts and types are kept to avoid having cast to/from any values
contexts []string
types []string
*VerifiableCredential
Expand Down Expand Up @@ -65,7 +65,7 @@ func (vcb *VerifiableCredentialBuilder) IsEmpty() bool {
return reflect.DeepEqual(vcb, &VerifiableCredentialBuilder{})
}

func (vcb *VerifiableCredentialBuilder) AddContext(context interface{}) error {
func (vcb *VerifiableCredentialBuilder) AddContext(context any) error {
if vcb.IsEmpty() {
return errors.New(BuilderEmptyError)
}
Expand All @@ -88,7 +88,7 @@ func (vcb *VerifiableCredentialBuilder) SetID(id string) error {
return nil
}

func (vcb *VerifiableCredentialBuilder) AddType(t interface{}) error {
func (vcb *VerifiableCredentialBuilder) AddType(t any) error {
if vcb.IsEmpty() {
return errors.New(BuilderEmptyError)
}
Expand All @@ -102,7 +102,7 @@ func (vcb *VerifiableCredentialBuilder) AddType(t interface{}) error {
return nil
}

func (vcb *VerifiableCredentialBuilder) SetIssuer(issuer interface{}) error {
func (vcb *VerifiableCredentialBuilder) SetIssuer(issuer any) error {
if vcb.IsEmpty() {
return errors.New(BuilderEmptyError)
}
Expand Down Expand Up @@ -160,14 +160,14 @@ func (vcb *VerifiableCredentialBuilder) SetExpirationDate(dateTime string) error
return nil
}

func (vcb *VerifiableCredentialBuilder) SetCredentialStatus(status interface{}) error {
func (vcb *VerifiableCredentialBuilder) SetCredentialStatus(status any) error {
if vcb.IsEmpty() {
return errors.New(BuilderEmptyError)
}

statusMap, err := util.ToJSONMap(status)
if err != nil {
return errors.Wrap(err, "status value not of required type map[string]interface{}")
return errors.Wrap(err, "status value not of required type map[string]any")
}

// check required properties
Expand Down Expand Up @@ -233,7 +233,7 @@ func (vcb *VerifiableCredentialBuilder) SetTermsOfUse(terms []TermsOfUse) error
return nil
}

func (vcb *VerifiableCredentialBuilder) SetEvidence(evidence []interface{}) error {
func (vcb *VerifiableCredentialBuilder) SetEvidence(evidence []any) error {
if vcb.IsEmpty() {
return errors.New(BuilderEmptyError)
}
Expand All @@ -247,7 +247,7 @@ func (vcb *VerifiableCredentialBuilder) SetEvidence(evidence []interface{}) erro

// VerifiablePresentationBuilder uses the builder pattern to construct a verifiable presentation
type VerifiablePresentationBuilder struct {
// contexts and types are kept to avoid having cast to/from interface{} values
// contexts and types are kept to avoid having cast to/from any values
contexts []string
types []string
*VerifiablePresentation
Expand Down Expand Up @@ -289,7 +289,7 @@ func (vpb *VerifiablePresentationBuilder) IsEmpty() bool {
return reflect.DeepEqual(vpb, &VerifiablePresentationBuilder{})
}

func (vpb *VerifiablePresentationBuilder) AddContext(context interface{}) error {
func (vpb *VerifiablePresentationBuilder) AddContext(context any) error {
if vpb.IsEmpty() {
return errors.New(BuilderEmptyError)
}
Expand Down Expand Up @@ -321,7 +321,7 @@ func (vpb *VerifiablePresentationBuilder) SetHolder(holder string) error {
return nil
}

func (vpb *VerifiablePresentationBuilder) AddType(t interface{}) error {
func (vpb *VerifiablePresentationBuilder) AddType(t any) error {
if vpb.IsEmpty() {
return errors.New(BuilderEmptyError)
}
Expand All @@ -335,7 +335,7 @@ func (vpb *VerifiablePresentationBuilder) AddType(t interface{}) error {
return nil
}

func (vpb *VerifiablePresentationBuilder) SetPresentationSubmission(ps interface{}) error {
func (vpb *VerifiablePresentationBuilder) SetPresentationSubmission(ps any) error {
if vpb.IsEmpty() {
return errors.New(BuilderEmptyError)
}
Expand All @@ -346,7 +346,7 @@ func (vpb *VerifiablePresentationBuilder) SetPresentationSubmission(ps interface

// AddVerifiableCredentials appends the given credentials to the verifiable presentation.
// It does not check for duplicates.
func (vpb *VerifiablePresentationBuilder) AddVerifiableCredentials(creds ...interface{}) error {
func (vpb *VerifiablePresentationBuilder) AddVerifiableCredentials(creds ...any) error {
if vpb.IsEmpty() {
return errors.New(BuilderEmptyError)
}
Expand Down
20 changes: 10 additions & 10 deletions credential/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ func TestCredential(t *testing.T) {
knownType := []string{"VerifiableCredential", "AlumniCredential"}
knownIssuer := "https://example.edu/issuers/565049"
knownIssuanceDate := "2010-01-01T19:23:24Z"
knownSubject := map[string]interface{}{
knownSubject := map[string]any{
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"alumniOf": map[string]interface{}{
"alumniOf": map[string]any{
"id": "did:example:c276e12ec21ebfeb1f712ebc6f1",
"name": []interface{}{
map[string]interface{}{"value": "Example University",
"name": []any{
map[string]any{"value": "Example University",
"lang": "en",
}, map[string]interface{}{
}, map[string]any{
"value": "Exemple d'Université",
"lang": "fr",
},
Expand Down Expand Up @@ -119,7 +119,7 @@ func TestCredentialBuilder(t *testing.T) {
assert.NoError(t, err)

// reset issuer as an object without an id property
badIssuerObject := map[string]interface{}{
badIssuerObject := map[string]any{
"issuer": "abcd",
"bad": "efghi",
}
Expand All @@ -128,7 +128,7 @@ func TestCredentialBuilder(t *testing.T) {
assert.Contains(t, err.Error(), "issuer object did not contain `id` property")

// issuer object with an id property
goodIssuerObject := map[string]interface{}{
goodIssuerObject := map[string]any{
"id": "issuer",
}
err = builder.SetIssuer(goodIssuerObject)
Expand Down Expand Up @@ -227,12 +227,12 @@ func TestCredentialBuilder(t *testing.T) {
assert.NoError(t, err)

// empty evidence
err = builder.SetEvidence([]interface{}{})
err = builder.SetEvidence([]any{})
assert.Error(t, err)
assert.Contains(t, err.Error(), "evidence cannot be empty")

// valid evidence
evidence := []interface{}{"evidence"}
evidence := []any{"evidence"}
err = builder.SetEvidence(evidence)
assert.NoError(t, err)

Expand Down Expand Up @@ -303,7 +303,7 @@ func TestVerifiablePresentationBuilder(t *testing.T) {
assert.NoError(t, err)

// add two credentials
creds := []interface{}{
creds := []any{
VerifiableCredential{
ID: "cred-1",
Type: "type",
Expand Down
2 changes: 1 addition & 1 deletion credential/exchange/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func (pdb *PresentationDefinitionBuilder) SetSubmissionRequirements(requirements
return nil
}

func (pdb *PresentationDefinitionBuilder) SetFrame(frame interface{}) error {
func (pdb *PresentationDefinitionBuilder) SetFrame(frame any) error {
if pdb.IsEmpty() {
return errors.New(BuilderEmptyError)
}
Expand Down
4 changes: 2 additions & 2 deletions credential/exchange/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func TestInputDescriptorBuilderProperties(t *testing.T) {
}
}`)

var props interface{}
var props any
err := json.Unmarshal(b, &props)
assert.NoError(t, err)

Expand Down Expand Up @@ -169,7 +169,7 @@ func TestInputDescriptorBuilderRequired(t *testing.T) {
}
}`)

var props interface{}
var props any
err := json.Unmarshal(b, &props)
assert.NoError(t, err)

Expand Down
36 changes: 18 additions & 18 deletions credential/exchange/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ type PresentationDefinition struct {
SubmissionRequirements []SubmissionRequirement `json:"submission_requirements,omitempty" validate:"omitempty,dive"`

// https://identity.foundation/presentation-exchange/#json-ld-framing-feature
Frame interface{} `json:"frame,omitempty"`
Frame any `json:"frame,omitempty"`
}

func (pd *PresentationDefinition) IsEmpty() bool {
Expand Down Expand Up @@ -287,23 +287,23 @@ type RelationalConstraint struct {
}

type Filter struct {
Type string `json:"type,omitempty"`
Format string `json:"format,omitempty"`
Properties interface{} `json:"properties,omitempty"`
Required []string `json:"required,omitempty"`
AdditionalProperties bool `json:"additionalProperties,omitempty"`
Pattern string `json:"pattern,omitempty"`
Minimum interface{} `json:"minimum,omitempty"`
Maximum interface{} `json:"maximum,omitempty"`
MinLength int `json:"minLength,omitempty"`
MaxLength int `json:"maxLength,omitempty"`
ExclusiveMinimum interface{} `json:"exclusiveMinimum,omitempty"`
ExclusiveMaximum interface{} `json:"exclusiveMaximum,omitempty"`
Const interface{} `json:"const,omitempty"`
Enum []interface{} `json:"enum,omitempty"`
Not interface{} `json:"not,omitempty"`
AllOf interface{} `json:"allOf,omitempty"`
OneOf interface{} `json:"oneOf,omitempty"`
Type string `json:"type,omitempty"`
Format string `json:"format,omitempty"`
Properties any `json:"properties,omitempty"`
Required []string `json:"required,omitempty"`
AdditionalProperties bool `json:"additionalProperties,omitempty"`
Pattern string `json:"pattern,omitempty"`
Minimum any `json:"minimum,omitempty"`
Maximum any `json:"maximum,omitempty"`
MinLength int `json:"minLength,omitempty"`
MaxLength int `json:"maxLength,omitempty"`
ExclusiveMinimum any `json:"exclusiveMinimum,omitempty"`
ExclusiveMaximum any `json:"exclusiveMaximum,omitempty"`
Const any `json:"const,omitempty"`
Enum []any `json:"enum,omitempty"`
Not any `json:"not,omitempty"`
AllOf any `json:"allOf,omitempty"`
OneOf any `json:"oneOf,omitempty"`
}

// CredentialStatus https://identity.foundation/presentation-exchange/#credential-status-constraint-feature
Expand Down
2 changes: 1 addition & 1 deletion credential/exchange/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func BuildPresentationRequest(signer crypto.JWTSigner, pt PresentationRequestTyp

// BuildJWTPresentationRequest builds a JWT representation of a presentation request
func BuildJWTPresentationRequest(signer crypto.JWTSigner, def PresentationDefinition, target string) ([]byte, error) {
jwtValues := map[string]interface{}{
jwtValues := map[string]any{
jwt.JwtIDKey: uuid.NewString(),
jwt.IssuerKey: signer.KeyID(),
jwt.AudienceKey: target,
Expand Down
2 changes: 1 addition & 1 deletion credential/exchange/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func getDummyPresentationDefinition() PresentationDefinition {
}

// turn two objects into json and compare value equality
func jsonEq(t *testing.T, a interface{}, b interface{}) {
func jsonEq(t *testing.T, a any, b any) {
aBytes, err := json.Marshal(a)
assert.NoError(t, err)
bBytes, err := json.Marshal(b)
Expand Down
30 changes: 15 additions & 15 deletions credential/exchange/submission.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (pc *PresentationClaim) IsEmpty() bool {

// GetClaimValue returns the value of the claim, since PresentationClaim is a union type. An error is returned if
// no value is present in any of the possible embedded types.
func (pc *PresentationClaim) GetClaimValue() (interface{}, error) {
func (pc *PresentationClaim) GetClaimValue() (any, error) {
if pc.Credential != nil {
return *pc.Credential, nil
}
Expand Down Expand Up @@ -95,13 +95,13 @@ func (pc *PresentationClaim) GetClaimFormat() (string, error) {
return "", errors.New("claim is empty")
}

// GetClaimJSON gets the claim value and attempts to turn it into a generic go-JSON object represented by an interface{}
func (pc *PresentationClaim) GetClaimJSON() (map[string]interface{}, error) {
// GetClaimJSON gets the claim value and attempts to turn it into a generic go-JSON object represented by an any
func (pc *PresentationClaim) GetClaimJSON() (map[string]any, error) {
claimValue, err := pc.GetClaimValue()
if err != nil {
return nil, err
}
jsonClaim := make(map[string]interface{})
jsonClaim := make(map[string]any)

// need to handle the case where we already have a string, since we won't need to marshal it
var claimBytes []byte
Expand Down Expand Up @@ -151,15 +151,15 @@ type NormalizedClaim struct {
// id for the claim
ID string
// go-json representation of the claim
Data map[string]interface{}
Data map[string]any
// JWT_VC, JWT_VP, LDP_VC, LDP_VP, etc.
Format string
// Signing algorithm used for the claim (e.g. EdDSA, ES256, PS256, etc.).
// OR the Linked Data Proof Type (e.g. JsonWebSignature2020)
AlgOrProofType string
}

// normalizePresentationClaims takes a set of Presentation Claims and turns them into map[string]interface{} as
// normalizePresentationClaims takes a set of Presentation Claims and turns them into map[string]any as
// go-JSON representations. The claim format and signature algorithm type are noted as well.
// This method is greedy, meaning it returns the set of claims it was able to normalize.
func normalizePresentationClaims(claims []PresentationClaim) ([]NormalizedClaim, error) {
Expand Down Expand Up @@ -196,7 +196,7 @@ func normalizePresentationClaims(claims []PresentationClaim) ([]NormalizedClaim,
// processedClaim represents a claim that has been processed for an input descriptor along with relevant
// information for building a valid descriptor_map in the resulting presentation submission
type processedClaim struct {
claim map[string]interface{}
claim map[string]any
SubmissionDescriptor
}

Expand Down Expand Up @@ -236,7 +236,7 @@ func BuildPresentationSubmissionVP(def PresentationDefinition, claims []Normaliz

// check if claim already exists. if it has, we won't duplicate the claim
var currIndex int
var claim map[string]interface{}
var claim map[string]any
claimID := processedID.ClaimID
if seen, ok := seenClaims[claimID]; ok {
currIndex = seen
Expand Down Expand Up @@ -285,15 +285,15 @@ type processedInputDescriptor struct {
// ID of the claim
ClaimID string
// generic claim
Claim map[string]interface{}
Claim map[string]any
// claim format
Format string
}

// limitedInputDescriptor is the claim data after being filtered/limited via JSON path
type limitedInputDescriptor struct {
Path string
Data interface{}
Data any
}

// processInputDescriptor runs the input evaluation algorithm described in the spec for a specific input descriptor
Expand Down Expand Up @@ -387,8 +387,8 @@ func filterClaimsByFormat(claims []NormalizedClaim, format *ClaimFormat) []Norma
}

// constructLimitedClaim builds a limited disclosure/filtered claim from a set of filtered input descriptors
func constructLimitedClaim(limitedDescriptors []limitedInputDescriptor) map[string]interface{} {
result := make(map[string]interface{})
func constructLimitedClaim(limitedDescriptors []limitedInputDescriptor) map[string]any {
result := make(map[string]any)
for _, ld := range limitedDescriptors {
curr := result

Expand All @@ -407,12 +407,12 @@ func constructLimitedClaim(limitedDescriptors []limitedInputDescriptor) map[stri

// if the path is not contained in the resulting JSON, create it
if _, ok := curr[normalizedPart]; !ok {
curr[normalizedPart] = make(map[string]interface{})
curr[normalizedPart] = make(map[string]any)
}

// make sure the value is represented in curr
currVal, _ := curr[normalizedPart]
curr = currVal.(map[string]interface{})
curr = currVal.(map[string]any)
}

// since we've gone to one short of the end, we need to repeat the process for the last element in the path
Expand All @@ -437,7 +437,7 @@ func normalizeJSONPath(path string) string {
// processInputDescriptorField applies all possible path values to a claim, and checks to see if any match.
// if a path matches fulfilled will be set to true and no processed value will be returned. if limitDisclosure is
// set to true, the processed value will be returned as well.
func processInputDescriptorField(field Field, claimData map[string]interface{}) (*limitedInputDescriptor, bool) {
func processInputDescriptorField(field Field, claimData map[string]any) (*limitedInputDescriptor, bool) {
for _, path := range field.Path {
pathedData, err := jsonpath.JsonPathLookup(claimData, path)
if err == nil {
Expand Down
Loading