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

Commit

Permalink
chore: update to orb v0.1
Browse files Browse the repository at this point in the history
Signed-off-by: Firas Qutishat <[email protected]>
  • Loading branch information
fqutishat committed May 5, 2021
1 parent 6c349de commit e11f0d1
Show file tree
Hide file tree
Showing 7 changed files with 281 additions and 33 deletions.
245 changes: 245 additions & 0 deletions component/vdr/orb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
# Orb VDR
Orb vdr used to manage DID operation.


## New VDR
```
import (
"crypto"
"github.com/hyperledger/aries-framework-go-ext/component/vdr/orb"
)
type keyRetrieverImpl struct {
nextRecoveryPublicKey crypto.PublicKey
nextUpdatePublicKey crypto.PublicKey
updateKey crypto.PrivateKey
recoverKey crypto.PrivateKey
}
func (k *keyRetrieverImpl) GetNextRecoveryPublicKey(didID string) (crypto.PublicKey, error) {
return k.nextRecoveryPublicKey, nil
}
func (k *keyRetrieverImpl) GetNextUpdatePublicKey(didID string) (crypto.PublicKey, error) {
return k.nextUpdatePublicKey, nil
}
func (k *keyRetrieverImpl) GetSigningKey(didID string, ot orb.OperationType) (crypto.PrivateKey, error) {
if ot == orb.Update {
return k.updateKey, nil
}
return k.recoverKey, nil
}
keyRetrieverImpl := &keyRetrieverImpl{}
vdr, err := orb.New(keyRetrieverImpl, orb.WithDomain("https://testnet.devel.trustbloc.dev"))
if err != nil {
return err
}
```

## Create DID
For creating DID use vdr create and pass DID document. To discover orb instance there are two ways explicitly or
through domain.

```
import (
"crypto"
"crypto/ed25519"
"crypto/rand"
"fmt"
ariesdid "github.com/hyperledger/aries-framework-go/pkg/doc/did"
"github.com/hyperledger/aries-framework-go/pkg/doc/jose"
vdrapi "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr"
"github.com/hyperledger/aries-framework-go-ext/component/vdr/orb"
)
recoveryKey, recoveryKeyPrivateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return err
}
updateKey, updateKeyPrivateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return err
}
didPublicKey, _, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return err
}
jwk, err := jose.JWKFromKey(didPublicKey)
if err != nil {
return err
}
vm,err:=ariesdid.NewVerificationMethodFromJWK("key1", "Ed25519VerificationKey2018", "", jwk)
if err != nil {
return err
}
didDoc := &ariesdid.Doc{}
// add did keys
didDoc.Authentication = append(didDoc.Authentication, *ariesdid.NewReferencedVerification(vm,
ariesdid.Authentication))
// add did services
didDoc.Service = []ariesdid.Service{{ID: "svc1", Type: "type", ServiceEndpoint: "http://www.example.com/"}}
// create did
createdDocResolution, err := vdr.Create(didDoc,
vdrapi.WithOption(orb.RecoveryPublicKeyOpt, recoveryKey),
vdrapi.WithOption(orb.UpdatePublicKeyOpt, updateKey),
// No need to use this option because we already use domain
// vdrapi.WithOption(orb.OperationEndpointsOpt, []string{"https://orb-1.devel.trustbloc.dev/sidetree/v1/operations"}),
vdrapi.WithOption(orb.AnchorOriginOpt, "https://orb-2.devel.trustbloc.dev/services/orb"))
if err != nil {
return err
}
fmt.Println(createdDocResolution.DIDDocument.ID)
// recovery private key be will used to sign next recovery request
keyRetrieverImpl.recoverKey = recoveryKeyPrivateKey
// update private key will be used to sign next update request
keyRetrieverImpl.updateKey = updateKeyPrivateKey
// if you need did to be discoverable just add domain to did URI (did:orb:123 => did:orb:domain.com:123)
discoverableDID := strings.ReplaceAll(createdDocResolution.DIDDocument.ID, "did:orb", "did:orb:testnet.devel.trustbloc.dev")
fmt.Println(discoverableDID)
```

## Resolve DID
For resolving DID use vdr read and pass DID URI. To discover orb instance there are two ways explicitly or
through did URI.

```
docResolution, err := vdr.Read(discoverableDID)
if err != nil {
return err
}
fmt.Println(docResolution.DIDDocument.ID)
```

## Update DID
For updating DID use vdr update and pass DID document. To discover orb instance there are two ways explicitly or
through domain.

```
updateKey, updateKeyPrivateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return err
}
// this key will used for next update request
keyRetrieverImpl.nextUpdatePublicKey = updateKey
didPublicKey, _, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return err
}
jwk, err := jose.JWKFromKey(didPublicKey)
if err != nil {
return err
}
vm,err:=ariesdid.NewVerificationMethodFromJWK("key1", "Ed25519VerificationKey2018", "", jwk)
if err != nil {
return err
}
didDoc := &ariesdid.Doc{ID: discoverableDID}
didDoc.Authentication = append(didDoc.Authentication, *ariesdid.NewReferencedVerification(vm,
ariesdid.Authentication))
didDoc.CapabilityInvocation = append(didDoc.CapabilityInvocation, *ariesdid.NewReferencedVerification(vm,
ariesdid.CapabilityInvocation))
didDoc.Service = []ariesdid.Service{
{
ID: "svc1",
Type: "typeUpdated",
ServiceEndpoint: "http://www.example.com/",
},
{
ID: "svc2",
Type: "type",
ServiceEndpoint: "http://www.example.com/",
},
}
if err := vdr.Update(didDoc); err != nil {
return err
}
// update private key will be used to sign next update request
keyRetrieverImpl.updateKey = updateKeyPrivateKey
```

## Recover DID
For recovering DID use vdr recover and pass DID document. To discover orb instance there are two ways explicitly or
through domain.

```
recoveryKey, recoveryKeyPrivateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return err
}
// this key will used for next recover request
keyRetriever.nextRecoveryPublicKey = recoveryKey
didDoc := &ariesdid.Doc{ID: discoverableDID}
didPublicKey, _, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return err
}
jwk, err := jose.JWKFromKey(didPublicKey)
if err != nil {
return err
}
vm,err:=ariesdid.NewVerificationMethodFromJWK("key1", "Ed25519VerificationKey2018", "", jwk)
if err != nil {
return err
}
didDoc.CapabilityInvocation = append(didDoc.CapabilityInvocation, *ariesdid.NewReferencedVerification(vm,
ariesdid.CapabilityDelegation))
didDoc.Service = []ariesdid.Service{{ID: "svc1", Type: "type", ServiceEndpoint: "http://www.example.com/"}}
if err := e.vdr.Update(didDoc,
vdrapi.WithOption(orb.RecoverOpt, true),
vdrapi.WithOption(orb.AnchorOriginOpt, "https://orb-2.devel.trustbloc.dev/services/orb")); err != nil {
return err
}
// recover private key will be used to sign next recover request
keyRetrieverImpl.recoverKey = recoveryKeyPrivateKey
```

## Deactivate DID
For deactivating DID use vdr recover and pass DID URI. To discover orb instance there are two ways explicitly or
through domain.

```
if err:=vdr.Deactivate(discoverableDID);err!=nil{
return err
}
```
15 changes: 10 additions & 5 deletions component/vdr/orb/config/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func (cs *Service) getSidetreeConfig() (*models.SidetreeConfig, error) { //nolin
return &models.SidetreeConfig{MultiHashAlgorithm: sha2_256, MaxAge: maxAge}, nil
}

func (cs *Service) getEndpoint(domain string) (*models.Endpoint, error) { //nolint: funlen,gocyclo
func (cs *Service) getEndpoint(domain string) (*models.Endpoint, error) { //nolint: funlen,gocyclo,gocognit
var wellKnownResponse restapi.WellKnownResponse

if !strings.HasPrefix(domain, "http://") && !strings.HasPrefix(domain, "https://") {
Expand All @@ -158,8 +158,13 @@ func (cs *Service) getEndpoint(domain string) (*models.Endpoint, error) { //noli

var webFingerResponse restapi.WebFingerResponse

err = cs.sendRequest(nil, http.MethodGet, fmt.Sprintf("%s/.well-known/webfinger?resource=%s",
domain, url.PathEscape(wellKnownResponse.ResolutionEndpoint)), &webFingerResponse)
parsedURL, err := url.Parse(wellKnownResponse.ResolutionEndpoint)
if err != nil {
return nil, err
}

err = cs.sendRequest(nil, http.MethodGet, fmt.Sprintf("%s://%s/.well-known/webfinger?resource=%s",
parsedURL.Scheme, parsedURL.Host, url.PathEscape(wellKnownResponse.ResolutionEndpoint)), &webFingerResponse)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -222,8 +227,8 @@ func (cs *Service) getEndpoint(domain string) (*models.Endpoint, error) { //noli
endpoint.ResolutionEndpoints = append(endpoint.ResolutionEndpoints, v.Href)
}

err = cs.sendRequest(nil, http.MethodGet, fmt.Sprintf("%s/.well-known/webfinger?resource=%s",
domain, url.PathEscape(wellKnownResponse.OperationEndpoint)), &webFingerResponse)
err = cs.sendRequest(nil, http.MethodGet, fmt.Sprintf("%s://%s/.well-known/webfinger?resource=%s",
parsedURL.Scheme, parsedURL.Host, url.PathEscape(wellKnownResponse.OperationEndpoint)), &webFingerResponse)
if err != nil {
return nil, err
}
Expand Down
30 changes: 16 additions & 14 deletions component/vdr/orb/config/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ func TestConfigService_GetEndpoint(t *testing.T) { //nolint: gocyclo,gocognit
&mockHTTPClient{doFunc: func(req *http.Request) (*http.Response, error) {
if strings.Contains(req.URL.Path, ".well-known/did-orb") {
b, err := json.Marshal(restapi.WellKnownResponse{
OperationEndpoint: "/op",
ResolutionEndpoint: "/resolve1",
OperationEndpoint: "https://localhost/op",
ResolutionEndpoint: "https://localhost/resolve1",
})
require.NoError(t, err)
r := ioutil.NopCloser(bytes.NewReader(b))
Expand Down Expand Up @@ -102,8 +102,8 @@ func TestConfigService_GetEndpoint(t *testing.T) { //nolint: gocyclo,gocognit
&mockHTTPClient{doFunc: func(req *http.Request) (*http.Response, error) {
if strings.Contains(req.URL.Path, ".well-known/did-orb") {
b, err := json.Marshal(restapi.WellKnownResponse{
OperationEndpoint: "/op",
ResolutionEndpoint: "/resolve1",
OperationEndpoint: "https://localhost/op",
ResolutionEndpoint: "https://localhost/resolve1",
})
require.NoError(t, err)
r := ioutil.NopCloser(bytes.NewReader(b))
Expand Down Expand Up @@ -148,8 +148,8 @@ func TestConfigService_GetEndpoint(t *testing.T) { //nolint: gocyclo,gocognit
&mockHTTPClient{doFunc: func(req *http.Request) (*http.Response, error) {
if strings.Contains(req.URL.Path, ".well-known/did-orb") {
b, err := json.Marshal(restapi.WellKnownResponse{
OperationEndpoint: "/op",
ResolutionEndpoint: "/resolve1",
OperationEndpoint: "https://localhost/op",
ResolutionEndpoint: "https://localhost/resolve1",
})
require.NoError(t, err)
r := ioutil.NopCloser(bytes.NewReader(b))
Expand Down Expand Up @@ -214,8 +214,8 @@ func TestConfigService_GetEndpoint(t *testing.T) { //nolint: gocyclo,gocognit
&mockHTTPClient{doFunc: func(req *http.Request) (*http.Response, error) {
if strings.Contains(req.URL.Path, ".well-known/did-orb") {
b, err := json.Marshal(restapi.WellKnownResponse{
OperationEndpoint: "/op",
ResolutionEndpoint: "/resolve1",
OperationEndpoint: "https://localhost/op",
ResolutionEndpoint: "https://localhost/resolve1",
})
require.NoError(t, err)
r := ioutil.NopCloser(bytes.NewReader(b))
Expand Down Expand Up @@ -304,8 +304,8 @@ func TestConfigService_GetEndpoint(t *testing.T) { //nolint: gocyclo,gocognit
&mockHTTPClient{doFunc: func(req *http.Request) (*http.Response, error) {
if strings.Contains(req.URL.Path, ".well-known/did-orb") {
b, err := json.Marshal(restapi.WellKnownResponse{
OperationEndpoint: "/op",
ResolutionEndpoint: "/resolve",
OperationEndpoint: "https://localhost/op",
ResolutionEndpoint: "https://localhost/resolve",
})
require.NoError(t, err)
r := ioutil.NopCloser(bytes.NewReader(b))
Expand All @@ -322,16 +322,17 @@ func TestConfigService_GetEndpoint(t *testing.T) { //nolint: gocyclo,gocognit
_, err := cs.GetEndpoint("d1")
require.Error(t, err)
require.Contains(t, err.Error(),
"got unexpected response from https://d1/.well-known/webfinger?resource=%2Fresolve status")
"got unexpected response from https://localhost/.well-known"+
"/webfinger?resource=https:%2F%2Flocalhost%2Fresolve status")
})

t.Run("web finger operation return 500 status", func(t *testing.T) {
cs := NewService(WithHTTPClient(
&mockHTTPClient{doFunc: func(req *http.Request) (*http.Response, error) {
if strings.Contains(req.URL.Path, ".well-known/did-orb") {
b, err := json.Marshal(restapi.WellKnownResponse{
OperationEndpoint: "/op",
ResolutionEndpoint: "/resolve",
OperationEndpoint: "https://localhost/op",
ResolutionEndpoint: "https://localhost/resolve",
})
require.NoError(t, err)
r := ioutil.NopCloser(bytes.NewReader(b))
Expand Down Expand Up @@ -360,7 +361,8 @@ func TestConfigService_GetEndpoint(t *testing.T) { //nolint: gocyclo,gocognit
_, err := cs.GetEndpoint("d1")
require.Error(t, err)
require.Contains(t, err.Error(),
"got unexpected response from https://d1/.well-known/webfinger?resource=%2Fop status")
"got unexpected response from https://localhost/.well-known/"+
"webfinger?resource=https:%2F%2Flocalhost%2Fop status")
})
}

Expand Down
4 changes: 2 additions & 2 deletions test/bdd/vdr/orb/create_follow_activity.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ inviteWitnessID=2
curl -o /dev/null -s -w "%{http_code}" --header "Content-Type: application/json" \
--request POST \
--data '{"@context":"https://www.w3.org/ns/activitystreams","id":"'$domain2IRI'/activities/'$followID'","type":"Follow","actor":"'$domain2IRI'","to":"'$domain1IRI'","object":"'$domain1IRI'"}' \
--insecure https://testnet.orb.local/services/orb/inbox
--insecure https://localhost:8009/services/orb/outbox


curl -o /dev/null -s -w "%{http_code}" --header "Content-Type: application/json" \
--request POST \
--data '{"@context":["https://www.w3.org/ns/activitystreams","https://trustbloc.github.io/did-method-orb/contexts/anchor/v1"],"id":"'$domain1IRI'/activities/'$inviteWitnessID'","type":"InviteWitness","actor":"'$domain1IRI'","to":"'$domain2IRI'","object":"'$domain2IRI'"}' \
--insecure https://localhost:8009/services/orb/inbox
--insecure https://testnet.orb.local/services/orb/outbox
4 changes: 2 additions & 2 deletions test/bdd/vdr/orb/fixtures/orb/.env
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
# SPDX-License-Identifier: Apache-2.0
#

ORB_IMAGE=ghcr.io/trustbloc-cicd/orb
ORB_IMAGE_TAG=v0.1.0-snapshot-f3d673f
ORB_IMAGE=ghcr.io/trustbloc/orb
ORB_IMAGE_TAG=v0.1.0

# couch settings
COUCHDB_IMAGE=couchdb
Expand Down
Loading

0 comments on commit e11f0d1

Please sign in to comment.