Merge commit '60bdc8873b3d259ff297be4873a9623fcebb7f75'

This commit is contained in:
Michael Muré
2024-11-26 11:44:27 +01:00
11 changed files with 188 additions and 202 deletions

View File

@@ -166,7 +166,7 @@ func randToken() (*delegation.Token, cid.Cid, []byte) {
opts = append(opts, delegation.WithMeta(randomString(8), randomString(10))) opts = append(opts, delegation.WithMeta(randomString(8), randomString(10)))
} }
t, err := delegation.New(priv, aud, cmd, pol, opts...) t, err := delegation.New(iss, aud, cmd, pol, opts...)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@@ -14,8 +14,6 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/ucan-wg/go-ucan/did" "github.com/ucan-wg/go-ucan/did"
"github.com/ucan-wg/go-ucan/pkg/command" "github.com/ucan-wg/go-ucan/pkg/command"
"github.com/ucan-wg/go-ucan/pkg/meta" "github.com/ucan-wg/go-ucan/pkg/meta"
@@ -51,12 +49,7 @@ type Token struct {
// When creating a delegated token, the Issuer's (iss) DID is assembled // When creating a delegated token, the Issuer's (iss) DID is assembled
// using the public key associated with the private key sent as the first // using the public key associated with the private key sent as the first
// parameter. // parameter.
func New(privKey crypto.PrivKey, aud did.DID, cmd command.Command, pol policy.Policy, opts ...Option) (*Token, error) { func New(iss, aud did.DID, cmd command.Command, pol policy.Policy, opts ...Option) (*Token, error) {
iss, err := did.FromPrivKey(privKey)
if err != nil {
return nil, err
}
tkn := &Token{ tkn := &Token{
issuer: iss, issuer: iss,
audience: aud, audience: aud,
@@ -73,6 +66,7 @@ func New(privKey crypto.PrivKey, aud did.DID, cmd command.Command, pol policy.Po
} }
} }
var err error
if len(tkn.nonce) == 0 { if len(tkn.nonce) == 0 {
tkn.nonce, err = nonce.Generate() tkn.nonce, err = nonce.Generate()
if err != nil { if err != nil {
@@ -93,15 +87,10 @@ func New(privKey crypto.PrivKey, aud did.DID, cmd command.Command, pol policy.Po
// When creating a root token, both the Issuer's (iss) and Subject's // When creating a root token, both the Issuer's (iss) and Subject's
// (sub) DIDs are assembled from the public key associated with the // (sub) DIDs are assembled from the public key associated with the
// private key passed as the first argument. // private key passed as the first argument.
func Root(privKey crypto.PrivKey, aud did.DID, cmd command.Command, pol policy.Policy, opts ...Option) (*Token, error) { func Root(iss, aud did.DID, cmd command.Command, pol policy.Policy, opts ...Option) (*Token, error) {
sub, err := did.FromPrivKey(privKey) opts = append(opts, WithSubject(iss))
if err != nil {
return nil, err
}
opts = append(opts, WithSubject(sub)) return New(iss, aud, cmd, pol, opts...)
return New(privKey, aud, cmd, pol, opts...)
} }
// Issuer returns the did.DID representing the Token's issuer. // Issuer returns the did.DID representing the Token's issuer.

View File

@@ -5,11 +5,10 @@ import (
"testing" "testing"
"time" "time"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gotest.tools/v3/golden" "gotest.tools/v3/golden"
"github.com/ucan-wg/go-ucan/did" "github.com/ucan-wg/go-ucan/did/didtest"
"github.com/ucan-wg/go-ucan/pkg/command" "github.com/ucan-wg/go-ucan/pkg/command"
"github.com/ucan-wg/go-ucan/pkg/policy" "github.com/ucan-wg/go-ucan/pkg/policy"
"github.com/ucan-wg/go-ucan/token/delegation" "github.com/ucan-wg/go-ucan/token/delegation"
@@ -18,16 +17,8 @@ import (
const ( const (
nonce = "6roDhGi0kiNriQAz7J3d+bOeoI/tj8ENikmQNbtjnD0" nonce = "6roDhGi0kiNriQAz7J3d+bOeoI/tj8ENikmQNbtjnD0"
AudiencePrivKeyCfg = "CAESQL1hvbXpiuk2pWr/XFbfHJcZNpJ7S90iTA3wSCTc/BPRneCwPnCZb6c0vlD6ytDWqaOt0HEOPYnqEpnzoBDprSM=" subJectCmd = "/foo/bar"
AudienceDID = "did:key:z6Mkq5YmbJcTrPExNDi26imrTCpKhepjBFBSHqrBDN2ArPkv" subjectPol = `
issuerPrivKeyCfg = "CAESQLSql38oDmQXIihFFaYIjb73mwbPsc7MIqn4o8PN4kRNnKfHkw5gRP1IV9b6d0estqkZayGZ2vqMAbhRixjgkDU="
issuerDID = "did:key:z6Mkpzn2n3ZGT2VaqMGSQC3tzmzV4TS9S71iFsDXE1WnoNH2"
subjectPrivKeyCfg = "CAESQL9RtjZ4dQBeXtvDe53UyvslSd64kSGevjdNiA1IP+hey5i/3PfRXSuDr71UeJUo1fLzZ7mGldZCOZL3gsIQz5c="
subjectDID = "did:key:z6MktA1uBdCpq4uJBqE9jjMiLyxZBg9a6xgPPKJjMqss6Zc2"
subJectCmd = "/foo/bar"
subjectPol = `
[ [
[ [
"==", "==",
@@ -65,7 +56,7 @@ const (
] ]
` `
newCID = "zdpuAn9JgGPvnt2WCmTaKktZdbuvcVGTg9bUT5kQaufwUtZ6e" newCID = "zdpuAwa4qv3ncMDPeDoqVxjZy3JoyWsbqUzm94rdA1AvRFkkw"
rootCID = "zdpuAkgGmUp5JrXvehGuuw9JA8DLQKDaxtK3R8brDQQVC2i5X" rootCID = "zdpuAkgGmUp5JrXvehGuuw9JA8DLQKDaxtK3R8brDQQVC2i5X"
aesKey = "xQklMmNTnVrmaPBq/0pwV5fEwuv/iClF5HWak9MsgI8=" aesKey = "xQklMmNTnVrmaPBq/0pwV5fEwuv/iClF5HWak9MsgI8="
@@ -74,13 +65,6 @@ const (
func TestConstructors(t *testing.T) { func TestConstructors(t *testing.T) {
t.Parallel() t.Parallel()
privKey := privKey(t, issuerPrivKeyCfg)
aud, err := did.Parse(AudienceDID)
sub, err := did.Parse(subjectDID)
require.NoError(t, err)
cmd, err := command.Parse(subJectCmd) cmd, err := command.Parse(subJectCmd)
require.NoError(t, err) require.NoError(t, err)
@@ -91,16 +75,16 @@ func TestConstructors(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
t.Run("New", func(t *testing.T) { t.Run("New", func(t *testing.T) {
tkn, err := delegation.New(privKey, aud, cmd, pol, tkn, err := delegation.New(didtest.PersonaAlice.DID(), didtest.PersonaBob.DID(), cmd, pol,
delegation.WithNonce([]byte(nonce)), delegation.WithNonce([]byte(nonce)),
delegation.WithSubject(sub), delegation.WithSubject(didtest.PersonaAlice.DID()),
delegation.WithExpiration(exp), delegation.WithExpiration(exp),
delegation.WithMeta("foo", "fooo"), delegation.WithMeta("foo", "fooo"),
delegation.WithMeta("bar", "barr"), delegation.WithMeta("bar", "barr"),
) )
require.NoError(t, err) require.NoError(t, err)
data, err := tkn.ToDagJson(privKey) data, err := tkn.ToDagJson(didtest.PersonaAlice.PrivKey())
require.NoError(t, err) require.NoError(t, err)
golden.Assert(t, string(data), "new.dagjson") golden.Assert(t, string(data), "new.dagjson")
@@ -109,7 +93,7 @@ func TestConstructors(t *testing.T) {
t.Run("Root", func(t *testing.T) { t.Run("Root", func(t *testing.T) {
t.Parallel() t.Parallel()
tkn, err := delegation.Root(privKey, aud, cmd, pol, tkn, err := delegation.Root(didtest.PersonaAlice.DID(), didtest.PersonaBob.DID(), cmd, pol,
delegation.WithNonce([]byte(nonce)), delegation.WithNonce([]byte(nonce)),
delegation.WithExpiration(exp), delegation.WithExpiration(exp),
delegation.WithMeta("foo", "fooo"), delegation.WithMeta("foo", "fooo"),
@@ -117,7 +101,7 @@ func TestConstructors(t *testing.T) {
) )
require.NoError(t, err) require.NoError(t, err)
data, err := tkn.ToDagJson(privKey) data, err := tkn.ToDagJson(didtest.PersonaAlice.PrivKey())
require.NoError(t, err) require.NoError(t, err)
golden.Assert(t, string(data), "root.dagjson") golden.Assert(t, string(data), "root.dagjson")
@@ -127,9 +111,6 @@ func TestConstructors(t *testing.T) {
func TestEncryptedMeta(t *testing.T) { func TestEncryptedMeta(t *testing.T) {
t.Parallel() t.Parallel()
privKey := privKey(t, issuerPrivKeyCfg)
aud, err := did.Parse(AudienceDID)
require.NoError(t, err)
cmd, err := command.Parse(subJectCmd) cmd, err := command.Parse(subJectCmd)
require.NoError(t, err) require.NoError(t, err)
pol, err := policy.FromDagJson(subjectPol) pol, err := policy.FromDagJson(subjectPol)
@@ -172,12 +153,12 @@ func TestEncryptedMeta(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
t.Parallel() t.Parallel()
tkn, err := delegation.New(privKey, aud, cmd, pol, tkn, err := delegation.New(didtest.PersonaAlice.DID(), didtest.PersonaBob.DID(), cmd, pol,
delegation.WithEncryptedMetaString(tt.key, tt.value, encryptionKey), delegation.WithEncryptedMetaString(tt.key, tt.value, encryptionKey),
) )
require.NoError(t, err) require.NoError(t, err)
data, err := tkn.ToDagCbor(privKey) data, err := tkn.ToDagCbor(didtest.PersonaAlice.PrivKey())
require.NoError(t, err) require.NoError(t, err)
decodedTkn, _, err := delegation.FromSealed(data) decodedTkn, _, err := delegation.FromSealed(data)
@@ -210,10 +191,10 @@ func TestEncryptedMeta(t *testing.T) {
} }
// Create token with multiple encrypted values // Create token with multiple encrypted values
tkn, err := delegation.New(privKey, aud, cmd, pol, opts...) tkn, err := delegation.New(didtest.PersonaAlice.DID(), didtest.PersonaBob.DID(), cmd, pol, opts...)
require.NoError(t, err) require.NoError(t, err)
data, err := tkn.ToDagCbor(privKey) data, err := tkn.ToDagCbor(didtest.PersonaAlice.PrivKey())
require.NoError(t, err) require.NoError(t, err)
decodedTkn, _, err := delegation.FromSealed(data) decodedTkn, _, err := delegation.FromSealed(data)
@@ -226,13 +207,3 @@ func TestEncryptedMeta(t *testing.T) {
} }
}) })
} }
func privKey(t require.TestingT, privKeyCfg string) crypto.PrivKey {
privKeyMar, err := crypto.ConfigDecodeKey(privKeyCfg)
require.NoError(t, err)
privKey, err := crypto.UnmarshalPrivateKey(privKeyMar)
require.NoError(t, err)
return privKey
}

View File

@@ -151,7 +151,12 @@ func (g *generator) chainPersonas(personas []didtest.Persona, acc acc, vari vari
func (g *generator) createDelegation(params newDelegationParams, name string, vari variant) (cid.Cid, error) { func (g *generator) createDelegation(params newDelegationParams, name string, vari variant) (cid.Cid, error) {
vari.variant(&params) vari.variant(&params)
tkn, err := delegation.New(params.privKey, params.aud, params.cmd, params.pol, params.opts...) issDID, err := did.FromPrivKey(params.privKey)
if err != nil {
return cid.Undef, err
}
tkn, err := delegation.New(issDID, params.aud, params.cmd, params.pol, params.opts...)
if err != nil { if err != nil {
return cid.Undef, err return cid.Undef, err
} }

View File

@@ -2,7 +2,6 @@ package delegation_test
import ( import (
"bytes" "bytes"
"crypto/rand"
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
@@ -13,9 +12,8 @@ import (
"github.com/ipld/go-ipld-prime" "github.com/ipld/go-ipld-prime"
"github.com/ipld/go-ipld-prime/codec/dagcbor" "github.com/ipld/go-ipld-prime/codec/dagcbor"
"github.com/ipld/go-ipld-prime/codec/dagjson" "github.com/ipld/go-ipld-prime/codec/dagjson"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/ucan-wg/go-ucan/did" "github.com/ucan-wg/go-ucan/did/didtest"
"github.com/ucan-wg/go-ucan/pkg/command" "github.com/ucan-wg/go-ucan/pkg/command"
"github.com/ucan-wg/go-ucan/pkg/policy" "github.com/ucan-wg/go-ucan/pkg/policy"
"github.com/ucan-wg/go-ucan/pkg/policy/literal" "github.com/ucan-wg/go-ucan/pkg/policy/literal"
@@ -26,15 +24,7 @@ import (
// The following example shows how to create a delegation.Token with // The following example shows how to create a delegation.Token with
// distinct DIDs for issuer (iss), audience (aud) and subject (sub). // distinct DIDs for issuer (iss), audience (aud) and subject (sub).
func ExampleNew() { func ExampleNew() {
issPriv, issPub, err := crypto.GenerateEd25519Key(rand.Reader) fmt.Println("issDid:", didtest.PersonaBob.DID().String())
printThenPanicOnErr(err)
issDid, err := did.FromPubKey(issPub)
printThenPanicOnErr(err)
fmt.Println("issDid:", issDid)
audDid := did.MustParse(AudienceDID)
subDid := did.MustParse(subjectDID)
// The command defines the shape of the arguments that will be evaluated against the policy // The command defines the shape of the arguments that will be evaluated against the policy
cmd := command.MustParse("/foo/bar") cmd := command.MustParse("/foo/bar")
@@ -51,8 +41,8 @@ func ExampleNew() {
)), )),
) )
tkn, err := delegation.New(issPriv, audDid, cmd, pol, tkn, err := delegation.New(didtest.PersonaBob.DID(), didtest.PersonaCarol.DID(), cmd, pol,
delegation.WithSubject(subDid), delegation.WithSubject(didtest.PersonaAlice.DID()),
delegation.WithExpirationIn(time.Hour), delegation.WithExpirationIn(time.Hour),
delegation.WithNotBeforeIn(time.Minute), delegation.WithNotBeforeIn(time.Minute),
delegation.WithMeta("foo", "bar"), delegation.WithMeta("foo", "bar"),
@@ -61,101 +51,91 @@ func ExampleNew() {
printThenPanicOnErr(err) printThenPanicOnErr(err)
// "Seal", meaning encode and wrap into a signed envelope. // "Seal", meaning encode and wrap into a signed envelope.
data, id, err := tkn.ToSealed(issPriv) data, id, err := tkn.ToSealed(didtest.PersonaBob.PrivKey())
printThenPanicOnErr(err) printThenPanicOnErr(err)
printCIDAndSealed(id, data) printCIDAndSealed(id, data)
// Example output: // Example output:
// //
// issDid: did:key:z6MkhVFznPeR572rTK51UjoTNpnF8cxuWfPm9oBMPr7y8ABe // issDid: did:key:z6MkvJPmEZZYbgiw1ouT1oouTsTFBHJSts9ophVsNgcRmYxU
// //
// CID (base58BTC): zdpuAv6g2eJSc4RJwEpmooGLVK4wJ4CZpnM92tPVYt5jtMoLW // CID (base58BTC): zdpuAsqfZkgg2jgZyob23sq1J9xwtf9PHgt1PsskVCMq7Vvxk
//
// DAG-CBOR (base64) out: glhA5rvl8uKmDVGvAVSt4m/0MGiXl9dZwljJJ9m2qHCoIB617l26UvMxyH5uvN9hM7ozfVATiq4mLhoGgm9IGnEEAqJhaEQ07QFxc3VjYW4vZGxnQDEuMC4wLXJjLjGpY2F1ZHg4ZGlkOmtleTp6Nk1rcTVZbWJKY1RyUEV4TkRpMjZpbXJUQ3BLaGVwakJGQlNIcXJCRE4yQXJQa3ZjY21kaC9mb28vYmFyY2V4cBpnDWzqY2lzc3g4ZGlkOmtleTp6Nk1raFZGem5QZVI1NzJyVEs1MVVqb1ROcG5GOGN4dVdmUG05b0JNUHI3eThBQmVjbmJmGmcNXxZjcG9sg4NiPT1nLnN0YXR1c2VkcmFmdINjYWxsaS5yZXZpZXdlcoNkbGlrZWYuZW1haWxtKkBleGFtcGxlLmNvbYNjYW55ZS50YWdzgmJvcoKDYj09YS5kbmV3c4NiPT1hLmVwcmVzc2NzdWJ4OGRpZDprZXk6ejZNa3RBMXVCZENwcTR1SkJxRTlqak1pTHl4WkJnOWE2eGdQUEtKak1xc3M2WmMyZG1ldGGiY2Jhehh7Y2Zvb2NiYXJlbm9uY2VMu0HMgJ5Y+M84I/66
// //
// DAG-CBOR (base64) out: lhAOnjc0bPptlI5MxRBrIK3YmAP1CxKfXOPkz6MHt/UJCx2gCN+6gXZX2N+BIJvmy8XmAO5sT2GYimiV7HlJH1AA6JhaEQ07QFxc3VjYW4vZGxnQDEuMC4wLXJjLjGpY2F1ZHg4ZGlkOmtleTp6Nk1rZ3VwY2hoNUh3dUhhaFM3WXN5RThiTHVhMU1yOHAyaUtOUmh5dlN2UkFzOW5jY21kaC9mb28vYmFyY2V4cBpnROP/Y2lzc3g4ZGlkOmtleTp6Nk1rdkpQbUVaWlliZ2l3MW91VDFvb3VUc1RGQkhKU3RzOW9waFZzTmdjUm1ZeFVjbmJmGmdE1itjcG9sg4NiPT1nLnN0YXR1c2VkcmFmdINjYWxsaS5yZXZpZXdlcoNkbGlrZWYuZW1haWxtKkBleGFtcGxlLmNvbYNjYW55ZS50YWdzgmJvcoKDYj09YS5kbmV3c4NiPT1hLmVwcmVzc2NzdWJ4OGRpZDprZXk6ejZNa3V1a2syc2tEWExRbjdOSzNFaDlqTW5kWWZ2REJ4eGt0Z3BpZEpBcWI3TTNwZG1ldGGiY2Jhehh7Y2Zvb2NiYXJlbm9uY2VMv+Diy6GExIuM1eX4
// Converted to DAG-JSON out: // Converted to DAG-JSON out:
// [ // [
// { // {
// "/": {
// "bytes": "5rvl8uKmDVGvAVSt4m/0MGiXl9dZwljJJ9m2qHCoIB617l26UvMxyH5uvN9hM7ozfVATiq4mLhoGgm9IGnEEAg"
// }
// },
// {
// "h": {
// "/": { // "/": {
// "bytes": "NO0BcQ" // "bytes": "5rvl8uKmDVGvAVSt4m/0MGiXl9dZwljJJ9m2qHCoIB617l26UvMxyH5uvN9hM7ozfVATiq4mLhoGgm9IGnEEAg"
// } // }
// }, // },
// "ucan/dlg@1.0.0-rc.1": { // {
// "aud": "did:key:z6Mkq5YmbJcTrPExNDi26imrTCpKhepjBFBSHqrBDN2ArPkv", // "h": {
// "cmd": "/foo/bar",
// "exp": 1728933098,
// "iss": "did:key:z6MkhVFznPeR572rTK51UjoTNpnF8cxuWfPm9oBMPr7y8ABe",
// "meta": {
// "baz": 123,
// "foo": "bar"
// },
// "nbf": 1728929558,
// "nonce": {
// "/": { // "/": {
// "bytes": "u0HMgJ5Y+M84I/66" // "bytes": "NO0BcQ"
// } // }
// }, // },
// "pol": [ // "ucan/dlg@1.0.0-rc.1": {
// [ // "aud": "did:key:z6Mkq5YmbJcTrPExNDi26imrTCpKhepjBFBSHqrBDN2ArPkv",
// "==", // "cmd": "/foo/bar",
// ".status", // "exp": 1728933098,
// "draft" // "iss": "did:key:z6MkhVFznPeR572rTK51UjoTNpnF8cxuWfPm9oBMPr7y8ABe",
// ], // "meta": {
// [ // "baz": 123,
// "all", // "foo": "bar"
// ".reviewer", // },
// "nbf": 1728929558,
// "nonce": {
// "/": {
// "bytes": "u0HMgJ5Y+M84I/66"
// }
// },
// "pol": [
// [ // [
// "like", // "==",
// ".email", // ".status",
// "*@example.com" // "draft"
// ] // ],
// ],
// [
// "any",
// ".tags",
// [ // [
// "or", // "all",
// ".reviewer",
// [ // [
// "like",
// ".email",
// "*@example.com"
// ]
// ],
// [
// "any",
// ".tags",
// [
// "or",
// [ // [
// "==", // [
// ".", // "==",
// "news" // ".",
// ], // "news"
// [ // ],
// "==", // [
// ".", // "==",
// "press" // ".",
// "press"
// ]
// ] // ]
// ] // ]
// ] // ]
// ] // ],
// ], // "sub": "did:key:z6MktA1uBdCpq4uJBqE9jjMiLyxZBg9a6xgPPKJjMqss6Zc2"
// "sub": "did:key:z6MktA1uBdCpq4uJBqE9jjMiLyxZBg9a6xgPPKJjMqss6Zc2" // }
// } // }
// } // ]
// ]
} }
// The following example shows how to create a UCAN root delegation.Token // The following example shows how to create a UCAN root delegation.Token
// - a delegation.Token with the subject (sub) set to the value of issuer // - a delegation.Token with the subject (sub) set to the value of issuer
// (iss). // (iss).
func ExampleRoot() { func ExampleRoot() {
issPriv, issPub, err := crypto.GenerateEd25519Key(rand.Reader)
printThenPanicOnErr(err)
issDid, err := did.FromPubKey(issPub)
printThenPanicOnErr(err)
fmt.Println("issDid:", issDid)
audDid := did.MustParse(AudienceDID)
// The command defines the shape of the arguments that will be evaluated against the policy // The command defines the shape of the arguments that will be evaluated against the policy
cmd := command.MustParse("/foo/bar") cmd := command.MustParse("/foo/bar")
@@ -171,7 +151,7 @@ func ExampleRoot() {
)), )),
) )
tkn, err := delegation.Root(issPriv, audDid, cmd, pol, tkn, err := delegation.Root(didtest.PersonaAlice.DID(), didtest.PersonaBob.DID(), cmd, pol,
delegation.WithExpirationIn(time.Hour), delegation.WithExpirationIn(time.Hour),
delegation.WithNotBeforeIn(time.Minute), delegation.WithNotBeforeIn(time.Minute),
delegation.WithMeta("foo", "bar"), delegation.WithMeta("foo", "bar"),
@@ -180,7 +160,7 @@ func ExampleRoot() {
printThenPanicOnErr(err) printThenPanicOnErr(err)
// "Seal", meaning encode and wrap into a signed envelope. // "Seal", meaning encode and wrap into a signed envelope.
data, id, err := tkn.ToSealed(issPriv) data, id, err := tkn.ToSealed(didtest.PersonaAlice.PrivKey())
printThenPanicOnErr(err) printThenPanicOnErr(err)
printCIDAndSealed(id, data) printCIDAndSealed(id, data)
@@ -189,82 +169,82 @@ func ExampleRoot() {
// //
// issDid: did:key:z6MknWJqz17Y4AfsXSJUFKomuBR4GTkViM7kJYutzTMkCyFF // issDid: did:key:z6MknWJqz17Y4AfsXSJUFKomuBR4GTkViM7kJYutzTMkCyFF
// //
// CID (base58BTC): zdpuAwLojgfvFCbjz2FsKrvN1khDQ9mFGT6b6pxjMfz73Roed // CID (base58BTC): zdpuAkwYz8nY7uU8j3F6wVTfFY1VEoExwvUAYBEwRWfTozddE
// //
// DAG-CBOR (base64) out: glhA6dBhbhhGE36CW22OxjOEIAqdDmBqCNsAhCRljnBdXd7YrVOUG+bnXGCIwd4dTGgpEdmY06PFIl7IXKXCh/ESBqJhaEQ07QFxc3VjYW4vZGxnQDEuMC4wLXJjLjGpY2F1ZHg4ZGlkOmtleTp6Nk1rcTVZbWJKY1RyUEV4TkRpMjZpbXJUQ3BLaGVwakJGQlNIcXJCRE4yQXJQa3ZjY21kaC9mb28vYmFyY2V4cBpnDW0wY2lzc3g4ZGlkOmtleTp6Nk1rbldKcXoxN1k0QWZzWFNKVUZLb211QlI0R1RrVmlNN2tKWXV0elRNa0N5RkZjbmJmGmcNX1xjcG9sg4NiPT1nLnN0YXR1c2VkcmFmdINjYWxsaS5yZXZpZXdlcoNkbGlrZWYuZW1haWxtKkBleGFtcGxlLmNvbYNjYW55ZS50YWdzgmJvcoKDYj09YS5kbmV3c4NiPT1hLmVwcmVzc2NzdWJ4OGRpZDprZXk6ejZNa25XSnF6MTdZNEFmc1hTSlVGS29tdUJSNEdUa1ZpTTdrSll1dHpUTWtDeUZGZG1ldGGiY2Jhehh7Y2Zvb2NiYXJlbm9uY2VMJOsjYi1Pq3OIB0La // DAG-CBOR (base64) out: glhAVpW67FJ+myNi+azvnw2jivuiqXTuMrDZI2Qdaa8jE1Oi3mkjnm7DyqSQGADcomcuDslMWKmJ+OIyvbPG5PtSA6JhaEQ07QFxc3VjYW4vZGxnQDEuMC4wLXJjLjGpY2F1ZHg4ZGlkOmtleTp6Nk1rdkpQbUVaWlliZ2l3MW91VDFvb3VUc1RGQkhKU3RzOW9waFZzTmdjUm1ZeFVjY21kaC9mb28vYmFyY2V4cBpnROVoY2lzc3g4ZGlkOmtleTp6Nk1rdXVrazJza0RYTFFuN05LM0VoOWpNbmRZZnZEQnh4a3RncGlkSkFxYjdNM3BjbmJmGmdE15RjcG9sg4NiPT1nLnN0YXR1c2VkcmFmdINjYWxsaS5yZXZpZXdlcoNkbGlrZWYuZW1haWxtKkBleGFtcGxlLmNvbYNjYW55ZS50YWdzgmJvcoKDYj09YS5kbmV3c4NiPT1hLmVwcmVzc2NzdWJ4OGRpZDprZXk6ejZNa3V1a2syc2tEWExRbjdOSzNFaDlqTW5kWWZ2REJ4eGt0Z3BpZEpBcWI3TTNwZG1ldGGiY2Jhehh7Y2Zvb2NiYXJlbm9uY2VMwzDc03WBciJIGPWG
// //
// Converted to DAG-JSON out: // Converted to DAG-JSON out:
// [ // [
// { // {
// "/": {
// "bytes": "6dBhbhhGE36CW22OxjOEIAqdDmBqCNsAhCRljnBdXd7YrVOUG+bnXGCIwd4dTGgpEdmY06PFIl7IXKXCh/ESBg"
// }
// },
// {
// "h": {
// "/": { // "/": {
// "bytes": "NO0BcQ" // "bytes": "VpW67FJ+myNi+azvnw2jivuiqXTuMrDZI2Qdaa8jE1Oi3mkjnm7DyqSQGADcomcuDslMWKmJ+OIyvbPG5PtSAw"
// } // }
// }, // },
// "ucan/dlg@1.0.0-rc.1": { // {
// "aud": "did:key:z6Mkq5YmbJcTrPExNDi26imrTCpKhepjBFBSHqrBDN2ArPkv", // "h": {
// "cmd": "/foo/bar",
// "exp": 1728933168,
// "iss": "did:key:z6MknWJqz17Y4AfsXSJUFKomuBR4GTkViM7kJYutzTMkCyFF",
// "meta": {
// "baz": 123,
// "foo": "bar"
// },
// "nbf": 1728929628,
// "nonce": {
// "/": { // "/": {
// "bytes": "JOsjYi1Pq3OIB0La" // "bytes": "NO0BcQ"
// } // }
// }, // },
// "pol": [ // "ucan/dlg@1.0.0-rc.1": {
// [ // "aud": "did:key:z6MkvJPmEZZYbgiw1ouT1oouTsTFBHJSts9ophVsNgcRmYxU",
// "==", // "cmd": "/foo/bar",
// ".status", // "exp": 1732568424,
// "draft" // "iss": "did:key:z6Mkuukk2skDXLQn7NK3Eh9jMndYfvDBxxktgpidJAqb7M3p",
// ], // "meta": {
// [ // "baz": 123,
// "all", // "foo": "bar"
// ".reviewer", // },
// "nbf": 1732564884,
// "nonce": {
// "/": {
// "bytes": "wzDc03WBciJIGPWG"
// }
// },
// "pol": [
// [ // [
// "like", // "==",
// ".email", // ".status",
// "*@example.com" // "draft"
// ] // ],
// ],
// [
// "any",
// ".tags",
// [ // [
// "or", // "all",
// ".reviewer",
// [ // [
// "like",
// ".email",
// "*@example.com"
// ]
// ],
// [
// "any",
// ".tags",
// [
// "or",
// [ // [
// "==", // [
// ".", // "==",
// "news" // ".",
// ], // "news"
// [ // ],
// "==", // [
// ".", // "==",
// "press" // ".",
// "press"
// ]
// ] // ]
// ] // ]
// ] // ]
// ] // ],
// ], // "sub": "did:key:z6Mkuukk2skDXLQn7NK3Eh9jMndYfvDBxxktgpidJAqb7M3p"
// "sub": "did:key:z6MknWJqz17Y4AfsXSJUFKomuBR4GTkViM7kJYutzTMkCyFF" // }
// } // }
// } // ]
// ]
} }
// The following example demonstrates how to get a delegation.Token from // The following example demonstrates how to get a delegation.Token from
// a DAG-CBOR []byte. // a DAG-CBOR []byte.
func ExampleToken_FromSealed() { func ExampleFromSealed() {
const cborBase64 = "glhAmnAkgfjAx4SA5pzJmtaHRJtTGNpF1y6oqb4yhGoM2H2EUGbBYT4rVDjMKBgCjhdGHjipm00L8iR5SsQh3sIEBaJhaEQ07QFxc3VjYW4vZGxnQDEuMC4wLXJjLjGoY2F1ZHg4ZGlkOmtleTp6Nk1rcTVZbWJKY1RyUEV4TkRpMjZpbXJUQ3BLaGVwakJGQlNIcXJCRE4yQXJQa3ZjY21kaC9mb28vYmFyY2V4cPZjaXNzeDhkaWQ6a2V5Ono2TWtwem4ybjNaR1QyVmFxTUdTUUMzdHptelY0VFM5UzcxaUZzRFhFMVdub05IMmNwb2yDg2I9PWcuc3RhdHVzZWRyYWZ0g2NhbGxpLnJldmlld2Vyg2RsaWtlZi5lbWFpbG0qQGV4YW1wbGUuY29tg2NhbnllLnRhZ3OCYm9ygoNiPT1hLmRuZXdzg2I9PWEuZXByZXNzY3N1Yng4ZGlkOmtleTp6Nk1rdEExdUJkQ3BxNHVKQnFFOWpqTWlMeXhaQmc5YTZ4Z1BQS0pqTXFzczZaYzJkbWV0YaBlbm9uY2VMAAECAwQFBgcICQoL" const cborBase64 = "glhAmnAkgfjAx4SA5pzJmtaHRJtTGNpF1y6oqb4yhGoM2H2EUGbBYT4rVDjMKBgCjhdGHjipm00L8iR5SsQh3sIEBaJhaEQ07QFxc3VjYW4vZGxnQDEuMC4wLXJjLjGoY2F1ZHg4ZGlkOmtleTp6Nk1rcTVZbWJKY1RyUEV4TkRpMjZpbXJUQ3BLaGVwakJGQlNIcXJCRE4yQXJQa3ZjY21kaC9mb28vYmFyY2V4cPZjaXNzeDhkaWQ6a2V5Ono2TWtwem4ybjNaR1QyVmFxTUdTUUMzdHptelY0VFM5UzcxaUZzRFhFMVdub05IMmNwb2yDg2I9PWcuc3RhdHVzZWRyYWZ0g2NhbGxpLnJldmlld2Vyg2RsaWtlZi5lbWFpbG0qQGV4YW1wbGUuY29tg2NhbnllLnRhZ3OCYm9ygoNiPT1hLmRuZXdzg2I9PWEuZXByZXNzY3N1Yng4ZGlkOmtleTp6Nk1rdEExdUJkQ3BxNHVKQnFFOWpqTWlMeXhaQmc5YTZ4Z1BQS0pqTXFzczZaYzJkbWV0YaBlbm9uY2VMAAECAwQFBgcICQoL"
cborBytes, err := base64.StdEncoding.DecodeString(cborBase64) cborBytes, err := base64.StdEncoding.DecodeString(cborBase64)

View File

@@ -1,6 +1,7 @@
package delegation package delegation
import ( import (
"fmt"
"io" "io"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@@ -193,8 +194,16 @@ func FromIPLD(node datamodel.Node) (*Token, error) {
} }
func (t *Token) toIPLD(privKey crypto.PrivKey) (datamodel.Node, error) { func (t *Token) toIPLD(privKey crypto.PrivKey) (datamodel.Node, error) {
var sub *string // sanity check that privKey and issuer are matching
issPub, err := t.issuer.PubKey()
if err != nil {
return nil, err
}
if !issPub.Equals(privKey.GetPublic()) {
return nil, fmt.Errorf("private key doesn't match the issuer")
}
var sub *string
if t.subject != did.Undef { if t.subject != did.Undef {
s := t.subject.String() s := t.subject.String()
sub = &s sub = &s

View File

@@ -10,6 +10,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gotest.tools/v3/golden" "gotest.tools/v3/golden"
"github.com/ucan-wg/go-ucan/did/didtest"
"github.com/ucan-wg/go-ucan/token/delegation" "github.com/ucan-wg/go-ucan/token/delegation"
"github.com/ucan-wg/go-ucan/token/internal/envelope" "github.com/ucan-wg/go-ucan/token/internal/envelope"
) )
@@ -21,7 +22,7 @@ func TestSchemaRoundTrip(t *testing.T) {
t.Parallel() t.Parallel()
delegationJson := golden.Get(t, "new.dagjson") delegationJson := golden.Get(t, "new.dagjson")
privKey := privKey(t, issuerPrivKeyCfg) privKey := didtest.PersonaAlice.PrivKey()
t.Run("via buffers", func(t *testing.T) { t.Run("via buffers", func(t *testing.T) {
t.Parallel() t.Parallel()
@@ -72,6 +73,16 @@ func TestSchemaRoundTrip(t *testing.T) {
assert.JSONEq(t, string(delegationJson), readJson.String()) assert.JSONEq(t, string(delegationJson), readJson.String())
}) })
t.Run("fails with wrong PrivKey", func(t *testing.T) {
t.Parallel()
p1, err := delegation.FromDagJson(delegationJson)
require.NoError(t, err)
_, _, err = p1.ToSealed(didtest.PersonaBob.PrivKey())
require.EqualError(t, err, "private key doesn't match the issuer")
})
} }
func BenchmarkSchemaLoad(b *testing.B) { func BenchmarkSchemaLoad(b *testing.B) {
@@ -83,7 +94,7 @@ func BenchmarkSchemaLoad(b *testing.B) {
func BenchmarkRoundTrip(b *testing.B) { func BenchmarkRoundTrip(b *testing.B) {
delegationJson := golden.Get(b, "new.dagjson") delegationJson := golden.Get(b, "new.dagjson")
privKey := privKey(b, issuerPrivKeyCfg) privKey := didtest.PersonaAlice.PrivKey()
b.Run("via buffers", func(b *testing.B) { b.Run("via buffers", func(b *testing.B) {
p1, _ := delegation.FromDagJson(delegationJson) p1, _ := delegation.FromDagJson(delegationJson)

View File

@@ -1 +1 @@
[{"/":{"bytes":"FM6otj0r/noJWiGAC5WV86xAazxrF173IihuHJgEt35CtSzjeaelrR3UwaSr8xbE9sLpo5xJhUbo0QLI273hDA"}},{"h":{"/":{"bytes":"NO0BcQ"}},"ucan/dlg@1.0.0-rc.1":{"aud":"did:key:z6Mkq5YmbJcTrPExNDi26imrTCpKhepjBFBSHqrBDN2ArPkv","cmd":"/foo/bar","exp":7258118400,"iss":"did:key:z6Mkpzn2n3ZGT2VaqMGSQC3tzmzV4TS9S71iFsDXE1WnoNH2","meta":{"bar":"barr","foo":"fooo"},"nonce":{"/":{"bytes":"NnJvRGhHaTBraU5yaVFBejdKM2QrYk9lb0kvdGo4RU5pa21RTmJ0am5EMA"}},"pol":[["==",".status","draft"],["all",".reviewer",["like",".email","*@example.com"]],["any",".tags",["or",[["==",".","news"],["==",".","press"]]]]],"sub":"did:key:z6MktA1uBdCpq4uJBqE9jjMiLyxZBg9a6xgPPKJjMqss6Zc2"}}] [{"/":{"bytes":"BBabgnWqd+cjwG1td0w9BudNocmUwoR89RMZTqZHk3osCXEI/bOkko0zTvlusaE4EMBBeSzZDKzjvunLBfdiBg"}},{"h":{"/":{"bytes":"NO0BcQ"}},"ucan/dlg@1.0.0-rc.1":{"aud":"did:key:z6MkvJPmEZZYbgiw1ouT1oouTsTFBHJSts9ophVsNgcRmYxU","cmd":"/foo/bar","exp":7258118400,"iss":"did:key:z6Mkuukk2skDXLQn7NK3Eh9jMndYfvDBxxktgpidJAqb7M3p","meta":{"bar":"barr","foo":"fooo"},"nonce":{"/":{"bytes":"NnJvRGhHaTBraU5yaVFBejdKM2QrYk9lb0kvdGo4RU5pa21RTmJ0am5EMA"}},"pol":[["==",".status","draft"],["all",".reviewer",["like",".email","*@example.com"]],["any",".tags",["or",[["==",".","news"],["==",".","press"]]]]],"sub":"did:key:z6Mkuukk2skDXLQn7NK3Eh9jMndYfvDBxxktgpidJAqb7M3p"}}]

View File

@@ -1 +1 @@
[{"/":{"bytes":"aYBq08tfm0zQZnPg/5tB9kM5mklRU9PPIkV7CK68jEgbd76JbCGuu75vfLyBu3WTqKzLSJ583pbwu668m/7MBQ"}},{"h":{"/":{"bytes":"NO0BcQ"}},"ucan/dlg@1.0.0-rc.1":{"aud":"did:key:z6Mkq5YmbJcTrPExNDi26imrTCpKhepjBFBSHqrBDN2ArPkv","cmd":"/foo/bar","exp":7258118400,"iss":"did:key:z6Mkpzn2n3ZGT2VaqMGSQC3tzmzV4TS9S71iFsDXE1WnoNH2","meta":{"bar":"barr","foo":"fooo"},"nonce":{"/":{"bytes":"NnJvRGhHaTBraU5yaVFBejdKM2QrYk9lb0kvdGo4RU5pa21RTmJ0am5EMA"}},"pol":[["==",".status","draft"],["all",".reviewer",["like",".email","*@example.com"]],["any",".tags",["or",[["==",".","news"],["==",".","press"]]]]],"sub":"did:key:z6Mkpzn2n3ZGT2VaqMGSQC3tzmzV4TS9S71iFsDXE1WnoNH2"}}] [{"/":{"bytes":"BBabgnWqd+cjwG1td0w9BudNocmUwoR89RMZTqZHk3osCXEI/bOkko0zTvlusaE4EMBBeSzZDKzjvunLBfdiBg"}},{"h":{"/":{"bytes":"NO0BcQ"}},"ucan/dlg@1.0.0-rc.1":{"aud":"did:key:z6MkvJPmEZZYbgiw1ouT1oouTsTFBHJSts9ophVsNgcRmYxU","cmd":"/foo/bar","exp":7258118400,"iss":"did:key:z6Mkuukk2skDXLQn7NK3Eh9jMndYfvDBxxktgpidJAqb7M3p","meta":{"bar":"barr","foo":"fooo"},"nonce":{"/":{"bytes":"NnJvRGhHaTBraU5yaVFBejdKM2QrYk9lb0kvdGo4RU5pa21RTmJ0am5EMA"}},"pol":[["==",".status","draft"],["all",".reviewer",["like",".email","*@example.com"]],["any",".tags",["or",[["==",".","news"],["==",".","press"]]]]],"sub":"did:key:z6Mkuukk2skDXLQn7NK3Eh9jMndYfvDBxxktgpidJAqb7M3p"}}]

View File

@@ -1,6 +1,7 @@
package invocation package invocation
import ( import (
"fmt"
"io" "io"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@@ -193,6 +194,15 @@ func FromIPLD(node datamodel.Node) (*Token, error) {
} }
func (t *Token) toIPLD(privKey crypto.PrivKey) (datamodel.Node, error) { func (t *Token) toIPLD(privKey crypto.PrivKey) (datamodel.Node, error) {
// sanity check that privKey and issuer are matching
issPub, err := t.issuer.PubKey()
if err != nil {
return nil, err
}
if !issPub.Equals(privKey.GetPublic()) {
return nil, fmt.Errorf("private key doesn't match the issuer")
}
var aud *string var aud *string
if t.audience != did.Undef { if t.audience != did.Undef {

View File

@@ -10,6 +10,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gotest.tools/v3/golden" "gotest.tools/v3/golden"
"github.com/ucan-wg/go-ucan/did/didtest"
"github.com/ucan-wg/go-ucan/token/internal/envelope" "github.com/ucan-wg/go-ucan/token/internal/envelope"
"github.com/ucan-wg/go-ucan/token/invocation" "github.com/ucan-wg/go-ucan/token/invocation"
) )
@@ -78,6 +79,16 @@ func TestSchemaRoundTrip(t *testing.T) {
assert.JSONEq(t, string(invocationJson), readJson.String()) assert.JSONEq(t, string(invocationJson), readJson.String())
}) })
t.Run("fails with wrong PrivKey", func(t *testing.T) {
t.Parallel()
p1, err := invocation.FromDagJson(invocationJson)
require.NoError(t, err)
_, _, err = p1.ToSealed(didtest.PersonaBob.PrivKey())
require.EqualError(t, err, "private key doesn't match the issuer")
})
} }
func privKey(t require.TestingT, privKeyCfg string) crypto.PrivKey { func privKey(t require.TestingT, privKeyCfg string) crypto.PrivKey {