106 lines
2.1 KiB
Go
106 lines
2.1 KiB
Go
package tokens
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/ipld/go-ipld-prime"
|
|
"github.com/ipld/go-ipld-prime/codec"
|
|
"github.com/ipld/go-ipld-prime/codec/cbor"
|
|
"github.com/ipld/go-ipld-prime/codec/dagcbor"
|
|
"github.com/ipld/go-ipld-prime/codec/dagjson"
|
|
"github.com/ipld/go-ipld-prime/codec/json"
|
|
"github.com/ipld/go-ipld-prime/codec/raw"
|
|
"github.com/ipld/go-ipld-prime/datamodel"
|
|
"github.com/ucan-wg/go-ucan/tokens/internal/envelope"
|
|
)
|
|
|
|
// EnvelopeInfo describes the fields of an Envelope enclosing a UCAN token.
|
|
type EnvelopeInfo struct {
|
|
Signature []byte
|
|
Tag string
|
|
VarsigHeader []byte
|
|
}
|
|
|
|
// InspectEnvelope accepts arbitrary data and attempts to decode it as a
|
|
// UCAN token's Envelope.
|
|
func Inspect(data []byte) (EnvelopeInfo, error) {
|
|
undef := EnvelopeInfo{}
|
|
|
|
node, err := decodeAny(data)
|
|
if err != nil {
|
|
return undef, err
|
|
}
|
|
|
|
info, err := envelope.Inspect(node)
|
|
if err != nil {
|
|
return undef, err
|
|
}
|
|
|
|
iterator := info.SigPayloadNode.MapIterator()
|
|
foundVarsigHeader := false
|
|
foundTokenPayload := false
|
|
tag := ""
|
|
i := 0
|
|
|
|
for !iterator.Done() {
|
|
k, _, err := iterator.Next()
|
|
if err != nil {
|
|
return undef, err
|
|
}
|
|
|
|
key, err := k.AsString()
|
|
if err != nil {
|
|
return undef, err
|
|
}
|
|
|
|
if key == envelope.VarsigHeaderKey {
|
|
foundVarsigHeader = true
|
|
i++
|
|
|
|
continue
|
|
}
|
|
|
|
if strings.HasPrefix(key, envelope.UCANTagPrefix) {
|
|
tag = key
|
|
foundTokenPayload = true
|
|
i++
|
|
}
|
|
}
|
|
|
|
if i != 2 {
|
|
return undef, fmt.Errorf("expected two and only two fields in SigPayload: %d", i)
|
|
}
|
|
|
|
if !foundVarsigHeader {
|
|
return undef, errors.New("failed to find VarsigHeader field")
|
|
}
|
|
|
|
if !foundTokenPayload {
|
|
return undef, errors.New("failed to find TokenPayload field")
|
|
}
|
|
|
|
return EnvelopeInfo{
|
|
Signature: info.Signature,
|
|
Tag: tag,
|
|
VarsigHeader: info.VarsigHeader,
|
|
}, nil
|
|
}
|
|
|
|
func decodeAny(data []byte) (datamodel.Node, error) {
|
|
for _, decoder := range []codec.Decoder{
|
|
dagcbor.Decode,
|
|
dagjson.Decode,
|
|
cbor.Decode,
|
|
json.Decode,
|
|
raw.Decode,
|
|
} {
|
|
if node, err := ipld.Decode(data, decoder); err == nil {
|
|
return node, nil
|
|
}
|
|
}
|
|
|
|
return nil, errors.New("failed to decode (any) the provided data")
|
|
}
|