From 60bdc8873b3d259ff297be4873a9623fcebb7f75 Mon Sep 17 00:00:00 2001 From: Steve Moyer Date: Mon, 25 Nov 2024 15:12:29 -0500 Subject: [PATCH] feat(delegation): make Token constructors resemble invocation.New() signature --- pkg/container/serial_test.go | 2 +- token/delegation/delegation_test.go | 55 +--- .../delegationtest/generator/generator.go | 7 +- token/delegation/examples_test.go | 254 ++++++++---------- token/delegation/schema_test.go | 15 +- token/delegation/testdata/new.dagjson | 2 +- token/delegation/testdata/root.dagjson | 2 +- token/invocation/ipld.go | 10 + token/invocation/schema_test.go | 11 + 9 files changed, 173 insertions(+), 185 deletions(-) diff --git a/pkg/container/serial_test.go b/pkg/container/serial_test.go index 36560b0..e696208 100644 --- a/pkg/container/serial_test.go +++ b/pkg/container/serial_test.go @@ -166,7 +166,7 @@ func randToken() (*delegation.Token, cid.Cid, []byte) { 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 { panic(err) } diff --git a/token/delegation/delegation_test.go b/token/delegation/delegation_test.go index b49578c..8da08b4 100644 --- a/token/delegation/delegation_test.go +++ b/token/delegation/delegation_test.go @@ -5,11 +5,10 @@ import ( "testing" "time" - "github.com/libp2p/go-libp2p/core/crypto" "github.com/stretchr/testify/require" "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/policy" "github.com/ucan-wg/go-ucan/token/delegation" @@ -18,16 +17,8 @@ import ( const ( nonce = "6roDhGi0kiNriQAz7J3d+bOeoI/tj8ENikmQNbtjnD0" - AudiencePrivKeyCfg = "CAESQL1hvbXpiuk2pWr/XFbfHJcZNpJ7S90iTA3wSCTc/BPRneCwPnCZb6c0vlD6ytDWqaOt0HEOPYnqEpnzoBDprSM=" - AudienceDID = "did:key:z6Mkq5YmbJcTrPExNDi26imrTCpKhepjBFBSHqrBDN2ArPkv" - - issuerPrivKeyCfg = "CAESQLSql38oDmQXIihFFaYIjb73mwbPsc7MIqn4o8PN4kRNnKfHkw5gRP1IV9b6d0estqkZayGZ2vqMAbhRixjgkDU=" - issuerDID = "did:key:z6Mkpzn2n3ZGT2VaqMGSQC3tzmzV4TS9S71iFsDXE1WnoNH2" - - subjectPrivKeyCfg = "CAESQL9RtjZ4dQBeXtvDe53UyvslSd64kSGevjdNiA1IP+hey5i/3PfRXSuDr71UeJUo1fLzZ7mGldZCOZL3gsIQz5c=" - subjectDID = "did:key:z6MktA1uBdCpq4uJBqE9jjMiLyxZBg9a6xgPPKJjMqss6Zc2" - subJectCmd = "/foo/bar" - subjectPol = ` + subJectCmd = "/foo/bar" + subjectPol = ` [ [ "==", @@ -65,7 +56,7 @@ const ( ] ` - newCID = "zdpuAn9JgGPvnt2WCmTaKktZdbuvcVGTg9bUT5kQaufwUtZ6e" + newCID = "zdpuAwa4qv3ncMDPeDoqVxjZy3JoyWsbqUzm94rdA1AvRFkkw" rootCID = "zdpuAkgGmUp5JrXvehGuuw9JA8DLQKDaxtK3R8brDQQVC2i5X" aesKey = "xQklMmNTnVrmaPBq/0pwV5fEwuv/iClF5HWak9MsgI8=" @@ -74,13 +65,6 @@ const ( func TestConstructors(t *testing.T) { 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) require.NoError(t, err) @@ -91,16 +75,16 @@ func TestConstructors(t *testing.T) { require.NoError(t, err) 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.WithSubject(sub), + delegation.WithSubject(didtest.PersonaAlice.DID()), delegation.WithExpiration(exp), delegation.WithMeta("foo", "fooo"), delegation.WithMeta("bar", "barr"), ) require.NoError(t, err) - data, err := tkn.ToDagJson(privKey) + data, err := tkn.ToDagJson(didtest.PersonaAlice.PrivKey()) require.NoError(t, err) golden.Assert(t, string(data), "new.dagjson") @@ -109,7 +93,7 @@ func TestConstructors(t *testing.T) { t.Run("Root", func(t *testing.T) { 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.WithExpiration(exp), delegation.WithMeta("foo", "fooo"), @@ -117,7 +101,7 @@ func TestConstructors(t *testing.T) { ) require.NoError(t, err) - data, err := tkn.ToDagJson(privKey) + data, err := tkn.ToDagJson(didtest.PersonaAlice.PrivKey()) require.NoError(t, err) golden.Assert(t, string(data), "root.dagjson") @@ -127,9 +111,6 @@ func TestConstructors(t *testing.T) { func TestEncryptedMeta(t *testing.T) { t.Parallel() - privKey := privKey(t, issuerPrivKeyCfg) - aud, err := did.Parse(AudienceDID) - require.NoError(t, err) cmd, err := command.Parse(subJectCmd) require.NoError(t, err) pol, err := policy.FromDagJson(subjectPol) @@ -172,12 +153,12 @@ func TestEncryptedMeta(t *testing.T) { t.Run(tt.name, func(t *testing.T) { 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), ) require.NoError(t, err) - data, err := tkn.ToDagCbor(privKey) + data, err := tkn.ToDagCbor(didtest.PersonaAlice.PrivKey()) require.NoError(t, err) decodedTkn, _, err := delegation.FromSealed(data) @@ -210,10 +191,10 @@ func TestEncryptedMeta(t *testing.T) { } // 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) - data, err := tkn.ToDagCbor(privKey) + data, err := tkn.ToDagCbor(didtest.PersonaAlice.PrivKey()) require.NoError(t, err) 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 -} diff --git a/token/delegation/delegationtest/generator/generator.go b/token/delegation/delegationtest/generator/generator.go index 2eaacb2..f70cb0f 100644 --- a/token/delegation/delegationtest/generator/generator.go +++ b/token/delegation/delegationtest/generator/generator.go @@ -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) { vari.variant(¶ms) - 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 { return cid.Undef, err } diff --git a/token/delegation/examples_test.go b/token/delegation/examples_test.go index 3766939..1ea6f55 100644 --- a/token/delegation/examples_test.go +++ b/token/delegation/examples_test.go @@ -2,7 +2,6 @@ package delegation_test import ( "bytes" - "crypto/rand" "encoding/base64" "encoding/hex" "encoding/json" @@ -13,9 +12,8 @@ import ( "github.com/ipld/go-ipld-prime" "github.com/ipld/go-ipld-prime/codec/dagcbor" "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/policy" "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 // distinct DIDs for issuer (iss), audience (aud) and subject (sub). func ExampleNew() { - issPriv, issPub, err := crypto.GenerateEd25519Key(rand.Reader) - printThenPanicOnErr(err) - - issDid, err := did.FromPubKey(issPub) - printThenPanicOnErr(err) - fmt.Println("issDid:", issDid) - - audDid := did.MustParse(AudienceDID) - subDid := did.MustParse(subjectDID) + fmt.Println("issDid:", didtest.PersonaBob.DID().String()) // The command defines the shape of the arguments that will be evaluated against the policy cmd := command.MustParse("/foo/bar") @@ -51,8 +41,8 @@ func ExampleNew() { )), ) - tkn, err := delegation.New(issPriv, audDid, cmd, pol, - delegation.WithSubject(subDid), + tkn, err := delegation.New(didtest.PersonaBob.DID(), didtest.PersonaCarol.DID(), cmd, pol, + delegation.WithSubject(didtest.PersonaAlice.DID()), delegation.WithExpirationIn(time.Hour), delegation.WithNotBeforeIn(time.Minute), delegation.WithMeta("foo", "bar"), @@ -61,101 +51,91 @@ func ExampleNew() { printThenPanicOnErr(err) // "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) printCIDAndSealed(id, data) // Example output: // - // issDid: did:key:z6MkhVFznPeR572rTK51UjoTNpnF8cxuWfPm9oBMPr7y8ABe + // issDid: did:key:z6MkvJPmEZZYbgiw1ouT1oouTsTFBHJSts9ophVsNgcRmYxU // - // CID (base58BTC): zdpuAv6g2eJSc4RJwEpmooGLVK4wJ4CZpnM92tPVYt5jtMoLW - // - // DAG-CBOR (base64) out: glhA5rvl8uKmDVGvAVSt4m/0MGiXl9dZwljJJ9m2qHCoIB617l26UvMxyH5uvN9hM7ozfVATiq4mLhoGgm9IGnEEAqJhaEQ07QFxc3VjYW4vZGxnQDEuMC4wLXJjLjGpY2F1ZHg4ZGlkOmtleTp6Nk1rcTVZbWJKY1RyUEV4TkRpMjZpbXJUQ3BLaGVwakJGQlNIcXJCRE4yQXJQa3ZjY21kaC9mb28vYmFyY2V4cBpnDWzqY2lzc3g4ZGlkOmtleTp6Nk1raFZGem5QZVI1NzJyVEs1MVVqb1ROcG5GOGN4dVdmUG05b0JNUHI3eThBQmVjbmJmGmcNXxZjcG9sg4NiPT1nLnN0YXR1c2VkcmFmdINjYWxsaS5yZXZpZXdlcoNkbGlrZWYuZW1haWxtKkBleGFtcGxlLmNvbYNjYW55ZS50YWdzgmJvcoKDYj09YS5kbmV3c4NiPT1hLmVwcmVzc2NzdWJ4OGRpZDprZXk6ejZNa3RBMXVCZENwcTR1SkJxRTlqak1pTHl4WkJnOWE2eGdQUEtKak1xc3M2WmMyZG1ldGGiY2Jhehh7Y2Zvb2NiYXJlbm9uY2VMu0HMgJ5Y+M84I/66 + // CID (base58BTC): zdpuAsqfZkgg2jgZyob23sq1J9xwtf9PHgt1PsskVCMq7Vvxk // + // DAG-CBOR (base64) out: lhAOnjc0bPptlI5MxRBrIK3YmAP1CxKfXOPkz6MHt/UJCx2gCN+6gXZX2N+BIJvmy8XmAO5sT2GYimiV7HlJH1AA6JhaEQ07QFxc3VjYW4vZGxnQDEuMC4wLXJjLjGpY2F1ZHg4ZGlkOmtleTp6Nk1rZ3VwY2hoNUh3dUhhaFM3WXN5RThiTHVhMU1yOHAyaUtOUmh5dlN2UkFzOW5jY21kaC9mb28vYmFyY2V4cBpnROP/Y2lzc3g4ZGlkOmtleTp6Nk1rdkpQbUVaWlliZ2l3MW91VDFvb3VUc1RGQkhKU3RzOW9waFZzTmdjUm1ZeFVjbmJmGmdE1itjcG9sg4NiPT1nLnN0YXR1c2VkcmFmdINjYWxsaS5yZXZpZXdlcoNkbGlrZWYuZW1haWxtKkBleGFtcGxlLmNvbYNjYW55ZS50YWdzgmJvcoKDYj09YS5kbmV3c4NiPT1hLmVwcmVzc2NzdWJ4OGRpZDprZXk6ejZNa3V1a2syc2tEWExRbjdOSzNFaDlqTW5kWWZ2REJ4eGt0Z3BpZEpBcWI3TTNwZG1ldGGiY2Jhehh7Y2Zvb2NiYXJlbm9uY2VMv+Diy6GExIuM1eX4 // 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", - // "cmd": "/foo/bar", - // "exp": 1728933098, - // "iss": "did:key:z6MkhVFznPeR572rTK51UjoTNpnF8cxuWfPm9oBMPr7y8ABe", - // "meta": { - // "baz": 123, - // "foo": "bar" - // }, - // "nbf": 1728929558, - // "nonce": { + // { + // "h": { // "/": { - // "bytes": "u0HMgJ5Y+M84I/66" + // "bytes": "NO0BcQ" // } // }, - // "pol": [ - // [ - // "==", - // ".status", - // "draft" - // ], - // [ - // "all", - // ".reviewer", + // "ucan/dlg@1.0.0-rc.1": { + // "aud": "did:key:z6Mkq5YmbJcTrPExNDi26imrTCpKhepjBFBSHqrBDN2ArPkv", + // "cmd": "/foo/bar", + // "exp": 1728933098, + // "iss": "did:key:z6MkhVFznPeR572rTK51UjoTNpnF8cxuWfPm9oBMPr7y8ABe", + // "meta": { + // "baz": 123, + // "foo": "bar" + // }, + // "nbf": 1728929558, + // "nonce": { + // "/": { + // "bytes": "u0HMgJ5Y+M84I/66" + // } + // }, + // "pol": [ // [ - // "like", - // ".email", - // "*@example.com" - // ] - // ], - // [ - // "any", - // ".tags", + // "==", + // ".status", + // "draft" + // ], // [ - // "or", + // "all", + // ".reviewer", // [ + // "like", + // ".email", + // "*@example.com" + // ] + // ], + // [ + // "any", + // ".tags", + // [ + // "or", // [ - // "==", - // ".", - // "news" - // ], - // [ - // "==", - // ".", - // "press" + // [ + // "==", + // ".", + // "news" + // ], + // [ + // "==", + // ".", + // "press" + // ] // ] // ] // ] - // ] - // ], - // "sub": "did:key:z6MktA1uBdCpq4uJBqE9jjMiLyxZBg9a6xgPPKJjMqss6Zc2" + // ], + // "sub": "did:key:z6MktA1uBdCpq4uJBqE9jjMiLyxZBg9a6xgPPKJjMqss6Zc2" + // } // } - // } - // ] + // ] } // 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 // (iss). 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 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.WithNotBeforeIn(time.Minute), delegation.WithMeta("foo", "bar"), @@ -180,7 +160,7 @@ func ExampleRoot() { printThenPanicOnErr(err) // "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) printCIDAndSealed(id, data) @@ -189,82 +169,82 @@ func ExampleRoot() { // // 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: - // [ - // { - // "/": { - // "bytes": "6dBhbhhGE36CW22OxjOEIAqdDmBqCNsAhCRljnBdXd7YrVOUG+bnXGCIwd4dTGgpEdmY06PFIl7IXKXCh/ESBg" - // } - // }, - // { - // "h": { + // [ + // { // "/": { - // "bytes": "NO0BcQ" + // "bytes": "VpW67FJ+myNi+azvnw2jivuiqXTuMrDZI2Qdaa8jE1Oi3mkjnm7DyqSQGADcomcuDslMWKmJ+OIyvbPG5PtSAw" // } // }, - // "ucan/dlg@1.0.0-rc.1": { - // "aud": "did:key:z6Mkq5YmbJcTrPExNDi26imrTCpKhepjBFBSHqrBDN2ArPkv", - // "cmd": "/foo/bar", - // "exp": 1728933168, - // "iss": "did:key:z6MknWJqz17Y4AfsXSJUFKomuBR4GTkViM7kJYutzTMkCyFF", - // "meta": { - // "baz": 123, - // "foo": "bar" - // }, - // "nbf": 1728929628, - // "nonce": { + // { + // "h": { // "/": { - // "bytes": "JOsjYi1Pq3OIB0La" + // "bytes": "NO0BcQ" // } // }, - // "pol": [ - // [ - // "==", - // ".status", - // "draft" - // ], - // [ - // "all", - // ".reviewer", + // "ucan/dlg@1.0.0-rc.1": { + // "aud": "did:key:z6MkvJPmEZZYbgiw1ouT1oouTsTFBHJSts9ophVsNgcRmYxU", + // "cmd": "/foo/bar", + // "exp": 1732568424, + // "iss": "did:key:z6Mkuukk2skDXLQn7NK3Eh9jMndYfvDBxxktgpidJAqb7M3p", + // "meta": { + // "baz": 123, + // "foo": "bar" + // }, + // "nbf": 1732564884, + // "nonce": { + // "/": { + // "bytes": "wzDc03WBciJIGPWG" + // } + // }, + // "pol": [ // [ - // "like", - // ".email", - // "*@example.com" - // ] - // ], - // [ - // "any", - // ".tags", + // "==", + // ".status", + // "draft" + // ], // [ - // "or", + // "all", + // ".reviewer", // [ + // "like", + // ".email", + // "*@example.com" + // ] + // ], + // [ + // "any", + // ".tags", + // [ + // "or", // [ - // "==", - // ".", - // "news" - // ], - // [ - // "==", - // ".", - // "press" + // [ + // "==", + // ".", + // "news" + // ], + // [ + // "==", + // ".", + // "press" + // ] // ] // ] // ] - // ] - // ], - // "sub": "did:key:z6MknWJqz17Y4AfsXSJUFKomuBR4GTkViM7kJYutzTMkCyFF" + // ], + // "sub": "did:key:z6Mkuukk2skDXLQn7NK3Eh9jMndYfvDBxxktgpidJAqb7M3p" + // } // } - // } - // ] + // ] } // The following example demonstrates how to get a delegation.Token from // a DAG-CBOR []byte. -func ExampleToken_FromSealed() { +func ExampleFromSealed() { const cborBase64 = "glhAmnAkgfjAx4SA5pzJmtaHRJtTGNpF1y6oqb4yhGoM2H2EUGbBYT4rVDjMKBgCjhdGHjipm00L8iR5SsQh3sIEBaJhaEQ07QFxc3VjYW4vZGxnQDEuMC4wLXJjLjGoY2F1ZHg4ZGlkOmtleTp6Nk1rcTVZbWJKY1RyUEV4TkRpMjZpbXJUQ3BLaGVwakJGQlNIcXJCRE4yQXJQa3ZjY21kaC9mb28vYmFyY2V4cPZjaXNzeDhkaWQ6a2V5Ono2TWtwem4ybjNaR1QyVmFxTUdTUUMzdHptelY0VFM5UzcxaUZzRFhFMVdub05IMmNwb2yDg2I9PWcuc3RhdHVzZWRyYWZ0g2NhbGxpLnJldmlld2Vyg2RsaWtlZi5lbWFpbG0qQGV4YW1wbGUuY29tg2NhbnllLnRhZ3OCYm9ygoNiPT1hLmRuZXdzg2I9PWEuZXByZXNzY3N1Yng4ZGlkOmtleTp6Nk1rdEExdUJkQ3BxNHVKQnFFOWpqTWlMeXhaQmc5YTZ4Z1BQS0pqTXFzczZaYzJkbWV0YaBlbm9uY2VMAAECAwQFBgcICQoL" cborBytes, err := base64.StdEncoding.DecodeString(cborBase64) diff --git a/token/delegation/schema_test.go b/token/delegation/schema_test.go index d9a7e8c..d88c0a1 100644 --- a/token/delegation/schema_test.go +++ b/token/delegation/schema_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "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/internal/envelope" ) @@ -21,7 +22,7 @@ func TestSchemaRoundTrip(t *testing.T) { t.Parallel() delegationJson := golden.Get(t, "new.dagjson") - privKey := privKey(t, issuerPrivKeyCfg) + privKey := didtest.PersonaAlice.PrivKey() t.Run("via buffers", func(t *testing.T) { t.Parallel() @@ -72,6 +73,16 @@ func TestSchemaRoundTrip(t *testing.T) { 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) { @@ -83,7 +94,7 @@ func BenchmarkSchemaLoad(b *testing.B) { func BenchmarkRoundTrip(b *testing.B) { delegationJson := golden.Get(b, "new.dagjson") - privKey := privKey(b, issuerPrivKeyCfg) + privKey := didtest.PersonaAlice.PrivKey() b.Run("via buffers", func(b *testing.B) { p1, _ := delegation.FromDagJson(delegationJson) diff --git a/token/delegation/testdata/new.dagjson b/token/delegation/testdata/new.dagjson index b921a94..618c90f 100644 --- a/token/delegation/testdata/new.dagjson +++ b/token/delegation/testdata/new.dagjson @@ -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"}}] \ No newline at end of file +[{"/":{"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"}}] \ No newline at end of file diff --git a/token/delegation/testdata/root.dagjson b/token/delegation/testdata/root.dagjson index a5c3933..618c90f 100644 --- a/token/delegation/testdata/root.dagjson +++ b/token/delegation/testdata/root.dagjson @@ -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"}}] \ No newline at end of file +[{"/":{"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"}}] \ No newline at end of file diff --git a/token/invocation/ipld.go b/token/invocation/ipld.go index acaaf98..39ae0fc 100644 --- a/token/invocation/ipld.go +++ b/token/invocation/ipld.go @@ -1,6 +1,7 @@ package invocation import ( + "fmt" "io" "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) { + // 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 if t.audience != did.Undef { diff --git a/token/invocation/schema_test.go b/token/invocation/schema_test.go index 77b1afb..f6cb5fb 100644 --- a/token/invocation/schema_test.go +++ b/token/invocation/schema_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "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/invocation" ) @@ -78,6 +79,16 @@ func TestSchemaRoundTrip(t *testing.T) { 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 {