Skip to content

Commit

Permalink
Merge pull request #26 from ucan-wg/feat/calculate-cid
Browse files Browse the repository at this point in the history
feat(cid): calculate the CID for decoded and newly created Tokeners
  • Loading branch information
smoyer64 authored Sep 24, 2024
2 parents 1301688 + f779477 commit 5202056
Show file tree
Hide file tree
Showing 11 changed files with 637 additions and 173 deletions.
25 changes: 25 additions & 0 deletions delegation/delegation.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
// Package delegation implements the UCAN [delegation] specification with
// an immutable Token type as well as methods to convert the Token to and
// from the [envelope]-enclosed, signed and DAG-CBOR-encoded form that
// should most commonly be used for transport and storage.
//
// [delegation]: https://github.com/ucan-wg/delegation/tree/v1_ipld
// [envelope]: https://github.com/ucan-wg/spec#envelope
package delegation

// TODO: change the "delegation" link above when the specification is merged

import (
"crypto/rand"
"errors"
"fmt"
"time"

"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p/core/crypto"

"github.com/ucan-wg/go-ucan/capability/command"
Expand All @@ -14,6 +24,7 @@ import (
"github.com/ucan-wg/go-ucan/pkg/meta"
)

// Token is an immutable type that holds the fields of a UCAN delegation.
type Token struct {
// Issuer DID (sender)
issuer did.DID
Expand All @@ -33,6 +44,8 @@ type Token struct {
notBefore *time.Time
// The timestamp at which the Invocation becomes invalid
expiration *time.Time
// The CID of the Token when enclosed in an Envelope and encoded to DAG-CBOR
cid cid.Cid
}

// New creates a validated Token from the provided parameters and options.
Expand All @@ -50,6 +63,7 @@ func New(privKey crypto.PrivKey, aud did.DID, cmd command.Command, pol policy.Po
policy: pol,
meta: meta.NewMeta(),
nonce: nil,
cid: cid.Undef,
}

for _, opt := range opts {
Expand Down Expand Up @@ -132,6 +146,13 @@ func (t *Token) Expiration() *time.Time {
return t.expiration
}

// CID returns the content identifier of the Token model when enclosed
// in an Envelope and encoded to DAG-CBOR.
// Returns cid.Undef if the token has not been serialized or deserialized yet.
func (t *Token) CID() cid.Cid {
return t.cid
}

func (t *Token) validate() error {
var errs error

Expand All @@ -151,6 +172,8 @@ func (t *Token) validate() error {
return errs
}

// Option is a type that allows optional fields to be set during the
// creation of a Token.
type Option func(*Token) error

// WithExpiration set's the Token's optional "expiration" field to the
Expand All @@ -168,6 +191,7 @@ func WithExpiration(exp time.Time) Option {
}

// WithMeta adds a key/value pair in the "meta" field.
//
// WithMeta can be used multiple times in the same call.
// Accepted types for the value are: bool, string, int, int32, int64, []byte,
// and ipld.Node.
Expand Down Expand Up @@ -277,6 +301,7 @@ func tokenFromModel(m tokenPayloadModel) (*Token, error) {
}

// generateNonce creates a 12-byte random nonce.
// TODO: some crypto scheme require more, is that our case?
func generateNonce() ([]byte, error) {
res := make([]byte, 12)
_, err := rand.Read(res)
Expand Down
36 changes: 8 additions & 28 deletions delegation/delegation_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package delegation_test

import (
"crypto/rand"
"testing"
"time"

Expand Down Expand Up @@ -64,6 +63,9 @@ const (
]
]
`

newCID = "zdpuAn9JgGPvnt2WCmTaKktZdbuvcVGTg9bUT5kQaufwUtZ6e"
rootCID = "zdpuAkgGmUp5JrXvehGuuw9JA8DLQKDaxtK3R8brDQQVC2i5X"
)

func TestConstructors(t *testing.T) {
Expand All @@ -86,7 +88,7 @@ func TestConstructors(t *testing.T) {
require.NoError(t, err)

t.Run("New", func(t *testing.T) {
dlg, err := delegation.New(privKey, aud, cmd, pol,
tkn, err := delegation.New(privKey, aud, cmd, pol,
delegation.WithNonce([]byte(nonce)),
delegation.WithSubject(sub),
delegation.WithExpiration(exp),
Expand All @@ -95,7 +97,7 @@ func TestConstructors(t *testing.T) {
)
require.NoError(t, err)

data, err := dlg.ToDagJson(privKey)
data, err := tkn.ToDagJson(privKey)
require.NoError(t, err)

t.Log(string(data))
Expand All @@ -106,15 +108,15 @@ func TestConstructors(t *testing.T) {
t.Run("Root", func(t *testing.T) {
t.Parallel()

dlg, err := delegation.Root(privKey, aud, cmd, pol,
tkn, err := delegation.Root(privKey, aud, cmd, pol,
delegation.WithNonce([]byte(nonce)),
delegation.WithExpiration(exp),
delegation.WithMeta("foo", "fooo"),
delegation.WithMeta("bar", "barr"),
)
require.NoError(t, err)

data, err := dlg.ToDagJson(privKey)
data, err := tkn.ToDagJson(privKey)
require.NoError(t, err)

t.Log(string(data))
Expand All @@ -123,9 +125,7 @@ func TestConstructors(t *testing.T) {
})
}

func privKey(t *testing.T, privKeyCfg string) crypto.PrivKey {
t.Helper()

func privKey(t require.TestingT, privKeyCfg string) crypto.PrivKey {
privKeyMar, err := crypto.ConfigDecodeKey(privKeyCfg)
require.NoError(t, err)

Expand All @@ -134,23 +134,3 @@ func privKey(t *testing.T, privKeyCfg string) crypto.PrivKey {

return privKey
}

func TestKey(t *testing.T) {
// TODO: why is this broken?
t.Skip("TODO: why is this broken?")

priv, _, err := crypto.GenerateEd25519Key(rand.Reader)
require.NoError(t, err)

privMar, err := crypto.MarshalPrivateKey(priv)
require.NoError(t, err)

privCfg := crypto.ConfigEncodeKey(privMar)
t.Log(privCfg)

id, err := did.FromPubKey(priv.GetPublic())
require.NoError(t, err)
t.Log(id)

t.Fail()
}
Loading

0 comments on commit 5202056

Please sign in to comment.