token: don't store the CID in the token, symmetric API for sealed

This commit is contained in:
Michael Muré
2024-10-02 11:57:24 +02:00
parent 6b8fbcee0a
commit d9739a3bab
7 changed files with 68 additions and 57 deletions

View File

@@ -15,7 +15,6 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/crypto"
"github.com/ucan-wg/go-ucan/did" "github.com/ucan-wg/go-ucan/did"
@@ -44,8 +43,6 @@ type Token struct {
notBefore *time.Time notBefore *time.Time
// The timestamp at which the Invocation becomes invalid // The timestamp at which the Invocation becomes invalid
expiration *time.Time 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. // New creates a validated Token from the provided parameters and options.
@@ -67,7 +64,6 @@ func New(privKey crypto.PrivKey, aud did.DID, cmd command.Command, pol policy.Po
policy: pol, policy: pol,
meta: meta.NewMeta(), meta: meta.NewMeta(),
nonce: nil, nonce: nil,
cid: cid.Undef,
} }
for _, opt := range opts { for _, opt := range opts {
@@ -156,13 +152,6 @@ func (t *Token) Expiration() *time.Time {
return t.expiration 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 { func (t *Token) validate() error {
var errs error var errs error

View File

@@ -223,10 +223,10 @@ func ExampleToken_FromSealed() {
cborBytes := exampleCBORData() cborBytes := exampleCBORData()
fmt.Println("DAG-CBOR (base64) in:", base64.StdEncoding.EncodeToString(cborBytes)) fmt.Println("DAG-CBOR (base64) in:", base64.StdEncoding.EncodeToString(cborBytes))
tkn, err := delegation.FromSealed(cborBytes) tkn, c, err := delegation.FromSealed(cborBytes)
printThenPanicOnErr(err) printThenPanicOnErr(err)
fmt.Println("CID (base58BTC):", envelope.CIDToBase58BTC(tkn.CID())) fmt.Println("CID (base58BTC):", envelope.CIDToBase58BTC(c))
fmt.Println("Issuer (iss):", tkn.Issuer().String()) fmt.Println("Issuer (iss):", tkn.Issuer().String())
fmt.Println("Audience (aud):", tkn.Audience().String()) fmt.Println("Audience (aud):", tkn.Audience().String())
fmt.Println("Subject (sub):", tkn.Subject().String()) fmt.Println("Subject (sub):", tkn.Subject().String())

View File

@@ -47,39 +47,35 @@ func (t *Token) ToSealedWriter(w io.Writer, privKey crypto.PrivKey) (cid.Cid, er
// verifies that the envelope's signature is correct based on the public // verifies that the envelope's signature is correct based on the public
// key taken from the issuer (iss) field and calculates the CID of the // key taken from the issuer (iss) field and calculates the CID of the
// incoming data. // incoming data.
func FromSealed(data []byte) (*Token, error) { func FromSealed(data []byte) (*Token, cid.Cid, error) {
tkn, err := FromDagCbor(data) tkn, err := FromDagCbor(data)
if err != nil { if err != nil {
return nil, err return nil, cid.Undef, err
} }
id, err := envelope.CIDFromBytes(data) id, err := envelope.CIDFromBytes(data)
if err != nil { if err != nil {
return nil, err return nil, cid.Undef, err
} }
tkn.cid = id return tkn, id, nil
return tkn, nil
} }
// FromSealedReader is the same as Unseal but accepts an io.Reader. // FromSealedReader is the same as Unseal but accepts an io.Reader.
func FromSealedReader(r io.Reader) (*Token, error) { func FromSealedReader(r io.Reader) (*Token, cid.Cid, error) {
cidReader := envelope.NewCIDReader(r) cidReader := envelope.NewCIDReader(r)
tkn, err := FromDagCborReader(cidReader) tkn, err := FromDagCborReader(cidReader)
if err != nil { if err != nil {
return nil, err return nil, cid.Undef, err
} }
id, err := cidReader.CID() id, err := cidReader.CID()
if err != nil { if err != nil {
return nil, err return nil, cid.Undef, err
} }
tkn.cid = id return tkn, id, nil
return tkn, nil
} }
// Encode marshals a Token to the format specified by the provided // Encode marshals a Token to the format specified by the provided

View File

@@ -39,9 +39,9 @@ func TestSchemaRoundTrip(t *testing.T) {
fmt.Println("cborBytes length", len(cborBytes)) fmt.Println("cborBytes length", len(cborBytes))
fmt.Println("cbor", string(cborBytes)) fmt.Println("cbor", string(cborBytes))
p2, err := delegation.FromSealed(cborBytes) p2, c2, err := delegation.FromSealed(cborBytes)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, id, p2.CID()) assert.Equal(t, id, c2)
fmt.Println("read Cbor", p2) fmt.Println("read Cbor", p2)
readJson, err := p2.ToDagJson(privKey) readJson, err := p2.ToDagJson(privKey)
@@ -70,10 +70,9 @@ func TestSchemaRoundTrip(t *testing.T) {
assert.Equal(t, newCID, envelope.CIDToBase58BTC(id)) assert.Equal(t, newCID, envelope.CIDToBase58BTC(id))
// buf = bytes.NewBuffer(cborBytes.Bytes()) // buf = bytes.NewBuffer(cborBytes.Bytes())
p2, err := delegation.FromSealedReader(cborBytes) p2, c2, err := delegation.FromSealedReader(cborBytes)
require.NoError(t, err) require.NoError(t, err)
t.Log(len(p2.CID().Bytes()), p2.CID().Bytes()) assert.Equal(t, envelope.CIDToBase58BTC(id), envelope.CIDToBase58BTC(c2))
assert.Equal(t, envelope.CIDToBase58BTC(id), envelope.CIDToBase58BTC(p2.CID()))
readJson := &bytes.Buffer{} readJson := &bytes.Buffer{}
require.NoError(t, p2.ToDagJsonWriter(readJson, privKey)) require.NoError(t, p2.ToDagJsonWriter(readJson, privKey))
@@ -96,7 +95,7 @@ func BenchmarkRoundTrip(b *testing.B) {
b.Run("via buffers", func(b *testing.B) { b.Run("via buffers", func(b *testing.B) {
p1, _ := delegation.FromDagJson(delegationJson) p1, _ := delegation.FromDagJson(delegationJson)
cborBytes, _, _ := p1.ToSealed(privKey) cborBytes, _, _ := p1.ToSealed(privKey)
p2, _ := delegation.FromSealed(cborBytes) p2, _, _ := delegation.FromSealed(cborBytes)
b.ResetTimer() b.ResetTimer()
@@ -117,7 +116,7 @@ func BenchmarkRoundTrip(b *testing.B) {
b.Run("Unseal", func(b *testing.B) { b.Run("Unseal", func(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, _ = delegation.FromSealed(cborBytes) _, _, _ = delegation.FromSealed(cborBytes)
} }
}) })
@@ -134,7 +133,7 @@ func BenchmarkRoundTrip(b *testing.B) {
cborBuf := &bytes.Buffer{} cborBuf := &bytes.Buffer{}
_, _ = p1.ToSealedWriter(cborBuf, privKey) _, _ = p1.ToSealedWriter(cborBuf, privKey)
cborBytes := cborBuf.Bytes() cborBytes := cborBuf.Bytes()
p2, _ := delegation.FromSealedReader(bytes.NewReader(cborBytes)) p2, _, _ := delegation.FromSealedReader(bytes.NewReader(cborBytes))
b.ResetTimer() b.ResetTimer()
@@ -161,7 +160,7 @@ func BenchmarkRoundTrip(b *testing.B) {
reader := bytes.NewReader(cborBytes) reader := bytes.NewReader(cborBytes)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, _ = reader.Seek(0, 0) _, _ = reader.Seek(0, 0)
_, _ = delegation.FromSealedReader(reader) _, _, _ = delegation.FromSealedReader(reader)
} }
}) })

View File

@@ -13,8 +13,6 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/ipfs/go-cid"
"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"
@@ -41,8 +39,6 @@ type Token struct {
// The timestamp at which the Invocation was created // The timestamp at which the Invocation was created
invokedAt *time.Time invokedAt *time.Time
// TODO: cause // TODO: cause
// The CID of the Token when enclosed in an Envelope and encoded to DAG-CBOR
cid cid.Cid
} }
// Issuer returns the did.DID representing the Token's issuer. // Issuer returns the did.DID representing the Token's issuer.
@@ -84,13 +80,6 @@ func (t *Token) Expiration() *time.Time {
return t.expiration 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 { func (t *Token) validate() error {
var errs error var errs error

View File

@@ -47,39 +47,35 @@ func (t *Token) ToSealedWriter(w io.Writer, privKey crypto.PrivKey) (cid.Cid, er
// verifies that the envelope's signature is correct based on the public // verifies that the envelope's signature is correct based on the public
// key taken from the issuer (iss) field and calculates the CID of the // key taken from the issuer (iss) field and calculates the CID of the
// incoming data. // incoming data.
func FromSealed(data []byte) (*Token, error) { func FromSealed(data []byte) (*Token, cid.Cid, error) {
tkn, err := FromDagCbor(data) tkn, err := FromDagCbor(data)
if err != nil { if err != nil {
return nil, err return nil, cid.Undef, err
} }
id, err := envelope.CIDFromBytes(data) id, err := envelope.CIDFromBytes(data)
if err != nil { if err != nil {
return nil, err return nil, cid.Undef, err
} }
tkn.cid = id return tkn, id, nil
return tkn, nil
} }
// FromSealedReader is the same as Unseal but accepts an io.Reader. // FromSealedReader is the same as Unseal but accepts an io.Reader.
func FromSealedReader(r io.Reader) (*Token, error) { func FromSealedReader(r io.Reader) (*Token, cid.Cid, error) {
cidReader := envelope.NewCIDReader(r) cidReader := envelope.NewCIDReader(r)
tkn, err := FromDagCborReader(cidReader) tkn, err := FromDagCborReader(cidReader)
if err != nil { if err != nil {
return nil, err return nil, cid.Undef, err
} }
id, err := cidReader.CID() id, err := cidReader.CID()
if err != nil { if err != nil {
return nil, err return nil, cid.Undef, err
} }
tkn.cid = id return tkn, id, nil
return tkn, nil
} }
// Encode marshals a Token to the format specified by the provided // Encode marshals a Token to the format specified by the provided

View File

@@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"io" "io"
"github.com/ipfs/go-cid"
"github.com/ipld/go-ipld-prime" "github.com/ipld/go-ipld-prime"
"github.com/ipld/go-ipld-prime/codec" "github.com/ipld/go-ipld-prime/codec"
"github.com/ipld/go-ipld-prime/codec/dagcbor" "github.com/ipld/go-ipld-prime/codec/dagcbor"
@@ -15,12 +16,51 @@ import (
"github.com/ucan-wg/go-ucan/token/invocation" "github.com/ucan-wg/go-ucan/token/invocation"
) )
// FromSealed decodes an arbitrary token type from the binary data,
// verifies that the envelope's signature is correct based on the public
// key taken from the issuer (iss) field and calculates the CID of the
// incoming data.
// Supported and returned types are:
// - delegation.Token
// - invocation.Token
func FromSealed(data []byte) (Token, cid.Cid, error) {
tkn, err := FromDagCbor(data)
if err != nil {
return nil, cid.Undef, err
}
id, err := envelope.CIDFromBytes(data)
if err != nil {
return nil, cid.Undef, err
}
return tkn, id, nil
}
// FromSealedReader is the same as Unseal but accepts an io.Reader.
func FromSealedReader(r io.Reader) (Token, cid.Cid, error) {
cidReader := envelope.NewCIDReader(r)
tkn, err := FromDagCborReader(cidReader)
if err != nil {
return nil, cid.Undef, err
}
id, err := cidReader.CID()
if err != nil {
return nil, cid.Undef, err
}
return tkn, id, nil
}
// Decode unmarshals the input data using the format specified by the // Decode unmarshals the input data using the format specified by the
// provided codec.Decoder into an arbitrary UCAN token. // provided codec.Decoder into an arbitrary UCAN token.
// An error is returned if the conversion fails, or if the resulting // An error is returned if the conversion fails, or if the resulting
// Token is invalid. // Token is invalid.
// Supported and returned types are: // Supported and returned types are:
// - delegation.Token // - delegation.Token
// - invocation.Token
func Decode(b []byte, decFn codec.Decoder) (Token, error) { func Decode(b []byte, decFn codec.Decoder) (Token, error) {
node, err := ipld.Decode(b, decFn) node, err := ipld.Decode(b, decFn)
if err != nil { if err != nil {
@@ -43,6 +83,7 @@ func DecodeReader(r io.Reader, decFn codec.Decoder) (Token, error) {
// Token is invalid. // Token is invalid.
// Supported and returned types are: // Supported and returned types are:
// - delegation.Token // - delegation.Token
// - invocation.Token
func FromDagCbor(b []byte) (Token, error) { func FromDagCbor(b []byte) (Token, error) {
return Decode(b, dagcbor.Decode) return Decode(b, dagcbor.Decode)
} }
@@ -57,6 +98,7 @@ func FromDagCborReader(r io.Reader) (Token, error) {
// Token is invalid. // Token is invalid.
// Supported and returned types are: // Supported and returned types are:
// - delegation.Token // - delegation.Token
// - invocation.Token
func FromDagJson(b []byte) (Token, error) { func FromDagJson(b []byte) (Token, error) {
return Decode(b, dagjson.Decode) return Decode(b, dagjson.Decode)
} }