fix: support ED25519 keys

This commit is contained in:
b5
2021-09-07 20:23:15 -04:00
parent e528b5825f
commit 8002b1ddd2
6 changed files with 139 additions and 83 deletions

View File

@@ -4,6 +4,9 @@
package didkey
import (
"crypto/ed25519"
"crypto/rsa"
"crypto/x509"
"fmt"
"strings"
@@ -15,10 +18,8 @@ import (
const (
// KeyPrefix indicates a decentralized identifier that uses the key method
KeyPrefix = "did:key"
// MulticodecKindRSAPubKey IS NOT A REAL MULTICODEC PREFIX.
// pulled from: https://github.com/w3c-ccg/lds-ed25519-2018/issues/3 because
// it's only slighly better than picking a random available byte prefix
MulticodecKindRSAPubKey = 0x5d
// MulticodecKindRSAPubKey rsa-x509-pub https://github.com/multiformats/multicodec/pull/226
MulticodecKindRSAPubKey = 0x1205
// MulticodecKindEd25519PubKey ed25519-pub
MulticodecKindEd25519PubKey = 0xed
)
@@ -28,6 +29,16 @@ type ID struct {
crypto.PubKey
}
// NewID constructs an Identifier from a public key
func NewID(pub crypto.PubKey) (ID, error) {
switch pub.Type() {
case crypto.Ed25519, crypto.RSA:
return ID{PubKey: pub}, nil
default:
return ID{}, fmt.Errorf("unsupported key type: %s", pub.Type())
}
}
// MulticodecType indicates the type for this multicodec
func (id ID) MulticodecType() uint64 {
switch id.Type() {
@@ -61,6 +72,31 @@ func (id ID) String() string {
return fmt.Sprintf("%s:%s", KeyPrefix, b58BKeyStr)
}
// VerifyKey returns the backing implementation for a public key, one of:
// *rsa.PublicKey, ed25519.PublicKey
func (id ID) VerifyKey() (interface{}, error) {
rawPubBytes, err := id.PubKey.Raw()
if err != nil {
return nil, err
}
switch id.PubKey.Type() {
case crypto.RSA:
verifyKeyiface, err := x509.ParsePKIXPublicKey(rawPubBytes)
if err != nil {
return nil, err
}
verifyKey, ok := verifyKeyiface.(*rsa.PublicKey)
if !ok {
return nil, fmt.Errorf("public key is not an RSA key. got type: %T", verifyKeyiface)
}
return verifyKey, nil
case crypto.Ed25519:
return ed25519.PublicKey(rawPubBytes), nil
default:
return nil, fmt.Errorf("unrecognized Public Key type: %s", id.PubKey.Type())
}
}
// Parse turns a string into a key method ID
func Parse(keystr string) (ID, error) {
var id ID
@@ -70,9 +106,13 @@ func Parse(keystr string) (ID, error) {
keystr = strings.TrimPrefix(keystr, KeyPrefix+":")
_, data, err := mb.Decode(keystr)
enc, data, err := mb.Decode(keystr)
if err != nil {
return id, err
return id, fmt.Errorf("decoding multibase: %w", err)
}
if enc != mb.Base58BTC {
return id, fmt.Errorf("unexpected multibase encoding: %s", mb.EncodingToStr[enc])
}
keyType, n, err := varint.FromUvarint(data)

View File

@@ -56,9 +56,9 @@ func Example() {
panicIfError(err)
// Output:
// cid of root UCAN: bafkreidhsvhlctwylgeibl2eeapdvbl3qm3mbqcqhxhvy4grmr25ji77hu
// cid of root UCAN: bafkreih6guuxohv47s2e366l6jn6stlsukgoerkdvtsni3kxr4jjmkaf3y
// scope of ucan attenuations must be less than it's parent
// cid of derived UCAN: bafkreifglbwtr27fbzmv3uardlygvggr722fckusfvfyfsonwkroca7efu
// cid of derived UCAN: bafkreihpk5474uoolkqrge3yk5uy2s7rarhn5xwxfoiobcy6ye7vfxetgm
}
func panicIfError(err error) {

4
go.mod
View File

@@ -10,6 +10,6 @@ require (
github.com/multiformats/go-multibase v0.0.3
github.com/multiformats/go-multihash v0.0.14
github.com/multiformats/go-varint v0.0.6
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 // indirect
)

12
go.sum
View File

@@ -82,8 +82,8 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -95,6 +95,7 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -105,10 +106,13 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

115
token.go
View File

@@ -10,18 +10,18 @@ package ucan
import (
"context"
"crypto/ed25519"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"errors"
"fmt"
"strings"
"time"
"github.com/golang-jwt/jwt"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p-core/crypto"
mh "github.com/multiformats/go-multihash"
"github.com/qri-io/ucan/didkey"
)
// ErrInvalidToken indicates an access token is invalid
@@ -125,12 +125,8 @@ type pkSource struct {
issuerDID string
signingMethod jwt.SigningMethod
verifyKey *rsa.PublicKey
signKey *rsa.PrivateKey
ap AttenuationConstructorFunc
resolver CIDBytesResolver
store TokenStore
verifyKey interface{} // one of: *rsa.PublicKey, *edsa.PublicKey
signKey interface{} // one of: *rsa.PrivateKey,
}
// assert pkSource implements tokens at compile time
@@ -139,41 +135,51 @@ var _ Source = (*pkSource)(nil)
// NewPrivKeySource creates an authentication interface backed by a single
// private key. Intended for a node running as remote, or providing a public API
func NewPrivKeySource(privKey crypto.PrivKey) (Source, error) {
methodStr := ""
keyType := privKey.Type()
rawPrivBytes, err := privKey.Raw()
if err != nil {
return nil, fmt.Errorf("getting private key bytes: %w", err)
}
var (
methodStr = ""
keyType = privKey.Type()
signKey interface{}
verifyKey interface{}
)
switch keyType {
case crypto.RSA:
methodStr = "RS256"
// TODO(b5) - detect if key is encoded as PEM block, here we're assuming it is
signKey, err = x509.ParsePKCS1PrivateKey(rawPrivBytes)
if err != nil {
return nil, err
}
rawPubBytes, err := privKey.GetPublic().Raw()
if err != nil {
return nil, fmt.Errorf("getting raw public key bytes: %w", err)
}
verifyKeyiface, err := x509.ParsePKIXPublicKey(rawPubBytes)
if err != nil {
return nil, fmt.Errorf("parsing public key bytes: %w", err)
}
var ok bool
verifyKey, ok = verifyKeyiface.(*rsa.PublicKey)
if !ok {
return nil, fmt.Errorf("public key is not an RSA key. got type: %T", verifyKeyiface)
}
case crypto.Ed25519:
methodStr = "EdDSA"
signKey = ed25519.PrivateKey(rawPrivBytes)
rawPubBytes, err := privKey.GetPublic().Raw()
if err != nil {
return nil, fmt.Errorf("getting raw public key bytes: %w", err)
}
verifyKey = ed25519.PublicKey(rawPubBytes)
default:
return nil, fmt.Errorf("unsupported key type for token creation: %q", keyType)
}
signingMethod := jwt.GetSigningMethod(methodStr)
rawPrivBytes, err := privKey.Raw()
if err != nil {
return nil, err
}
signKey, err := x509.ParsePKCS1PrivateKey(rawPrivBytes)
if err != nil {
return nil, err
}
rawPubBytes, err := privKey.GetPublic().Raw()
if err != nil {
return nil, err
}
verifyKeyiface, err := x509.ParsePKIXPublicKey(rawPubBytes)
if err != nil {
return nil, err
}
verifyKey, ok := verifyKeyiface.(*rsa.PublicKey)
if !ok {
return nil, fmt.Errorf("public key is not an RSA key. got type: %T", verifyKeyiface)
}
issuerDID, err := DIDStringFromPublicKey(privKey.GetPublic())
if err != nil {
return nil, err
@@ -181,7 +187,7 @@ func NewPrivKeySource(privKey crypto.PrivKey) (Source, error) {
return &pkSource{
pk: privKey,
signingMethod: signingMethod,
signingMethod: jwt.GetSigningMethod(methodStr),
verifyKey: verifyKey,
signKey: signKey,
issuerDID: issuerDID,
@@ -253,16 +259,16 @@ func (a *pkSource) newToken(subjectDID string, prf []Proof, att Attenuations, fc
// DIDPubKeyResolver turns did:key Decentralized IDentifiers into a public key,
// possibly using a network request
type DIDPubKeyResolver interface {
ResolveDIDKey(ctx context.Context, did string) (crypto.PubKey, error)
ResolveDIDKey(ctx context.Context, did string) (didkey.ID, error)
}
// DIDStringFromPublicKey creates a did:key identifier string from a public key
func DIDStringFromPublicKey(pub crypto.PubKey) (string, error) {
rawPubBytes, err := pub.Raw()
id, err := didkey.NewID(pub)
if err != nil {
return "", err
}
return fmt.Sprintf("did:key:%s", base64.URLEncoding.EncodeToString(rawPubBytes)), nil
return id.String(), nil
}
// StringDIDPubKeyResolver implements the DIDPubKeyResolver interface without
@@ -271,18 +277,8 @@ func DIDStringFromPublicKey(pub crypto.PubKey) (string, error) {
type StringDIDPubKeyResolver struct{}
// ResolveDIDKey extracts a public key from a did:key string
func (StringDIDPubKeyResolver) ResolveDIDKey(ctx context.Context, didStr string) (crypto.PubKey, error) {
// id, err := did.Parse(didStr)
// if err != nil {
// return nil, fmt.Errorf("invalid DID: %w", err)
// }
data, err := base64.URLEncoding.DecodeString(strings.TrimPrefix(didStr, "did:key:"))
if err != nil {
return nil, err
}
return crypto.UnmarshalRsaPublicKey(data)
func (StringDIDPubKeyResolver) ResolveDIDKey(ctx context.Context, didStr string) (didkey.ID, error) {
return didkey.Parse(didStr)
}
// TokenParser parses a raw string into a Token
@@ -309,7 +305,7 @@ func (p *TokenParser) ParseAndVerify(ctx context.Context, raw string) (*Token, e
func (p *TokenParser) parseAndVerify(ctx context.Context, raw string, child *Token) (*Token, error) {
tok, err := jwt.Parse(raw, p.matchVerifyKeyFunc(ctx))
if err != nil {
return nil, err
return nil, fmt.Errorf("parsing UCAN: %w", err)
}
mc, ok := tok.Claims.(jwt.MapClaims)
@@ -366,24 +362,11 @@ func (p *TokenParser) matchVerifyKeyFunc(ctx context.Context) func(tok *jwt.Toke
return nil, fmt.Errorf(`"iss" claims key is required`)
}
pubKey, err := p.didr.ResolveDIDKey(ctx, iss)
id, err := p.didr.ResolveDIDKey(ctx, iss)
if err != nil {
return nil, err
}
rawPubBytes, err := pubKey.Raw()
if err != nil {
return nil, err
}
verifyKeyiface, err := x509.ParsePKIXPublicKey(rawPubBytes)
if err != nil {
return nil, err
}
verifyKey, ok := verifyKeyiface.(*rsa.PublicKey)
if !ok {
return nil, fmt.Errorf("public key is not an RSA key. got type: %T", verifyKeyiface)
}
return verifyKey, nil
return id.VerifyKey()
}
}

View File

@@ -62,7 +62,7 @@ func TestPrivKeySource(t *testing.T) {
t.Fatal(err)
}
expect := `eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsInVjdiI6IjAuNC4wIn0.eyJpc3MiOiJkaWQ6a2V5Ok1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBb2FkUjRtY1U3QzBBbWg1bHRfM0hObVEyYVlDOEotYU5mNTJUNEtrLTBzbHh6LVc1LXhrREJ0NUR4RUZuSmVKNGJTMV9ZWkt3UkxKQjYzU0phcWZjMXhUTUFYMnJmcW44d3NwUmd2MEFReGU4RV9icGkzZTUyNnU2UU1VRjdYbDRKN2JkbVlZT0lCUDVCSk83eU1pX2pfU3FWaVdmOG82Y3BJTEF3dXpUNTY2X0ttUWFOclM5QmVNUHQ5NTJZUk1lejZlMFoycXR0aVRQS3hmalJ3b0VwRklldDVhZTFZY0p2VDBLQnJiZEYwNXhDc2F6RUoxSm52eUlSamNiUE9FYVljUjNPZnAxdW8ySTRKdVczQ2FKeHNqMU8yNnZyLWRUSzlqcGVFVTl5X1dUU1lNOUVsazBwZ0xZZ1M4ZHE4aTYwNDVnejByemU4QzV2YkZoSFZwa1ZRSURBUUFCIiwic3ViIjoiZGlkOmtleTpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQW9hZFI0bWNVN0MwQW1oNWx0XzNITm1RMmFZQzhKLWFOZjUyVDRLay0wc2x4ei1XNS14a0RCdDVEeEVGbkplSjRiUzFfWVpLd1JMSkI2M1NKYXFmYzF4VE1BWDJyZnFuOHdzcFJndjBBUXhlOEVfYnBpM2U1MjZ1NlFNVUY3WGw0SjdiZG1ZWU9JQlA1QkpPN3lNaV9qX1NxVmlXZjhvNmNwSUxBd3V6VDU2Nl9LbVFhTnJTOUJlTVB0OTUyWVJNZXo2ZTBaMnF0dGlUUEt4ZmpSd29FcEZJZXQ1YWUxWWNKdlQwS0JyYmRGMDV4Q3NhekVKMUpudnlJUmpjYlBPRWFZY1IzT2ZwMXVvMkk0SnVXM0NhSnhzajFPMjZ2ci1kVEs5anBlRVU5eV9XVFNZTTlFbGswcGdMWWdTOGRxOGk2MDQ1Z3owcnplOEM1dmJGaEhWcGtWUUlEQVFBQiIsImF0dCI6W3siYXBpIjoiKiIsImNhcCI6IlNVUEVSX1VTRVIifSx7ImNhcCI6IlNVUEVSX1VTRVIiLCJkYXRhc2V0IjoiYjU6d29ybGRfYmFua19wb3B1bGF0aW9uOioifV19.Z32-i-pGAtPRsG0JW4ZS8-c17x3mX3kFrmZ0BYhyWk2JH4QMwXFRtkUl8xVQtrC3JigeQeaDiz-WTUSFqJIs5dunL1Xf_SXqq8SZ7NCh6u6OEo2L1BnQkwdO8kDsFoiF42byWDBwzHRog0N-pRXgMhlo8si6Pek4KAZokQ5F-8FuLb3MXXxc9-FnhGRsKgGt_bNWS322h5gXCaXJAzbdAHwGSlORCCJI4CrbWUHs03i4viun2Ht01JO-p4ySlut6YyQ_vW4NGNSAAXGeR-ggkB0B6TGgt695CxX1zgQKV7X6JZx-NF_J-OXCIWngCfr6VdRv1_ADce9s1ODEm2N7eA`
expect := `eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsInVjdiI6IjAuNC4wIn0.eyJpc3MiOiJkaWQ6a2V5OnoyTUd3NGdrODRVU290YVdmNEFrSjgzRGNucmZnR2FjZUY4NktRWFJZTWZRN3hxblVGRVREN3RGNGprTkd2QUV0dlZ6Rm5RdTkydEZ3ZkNyb2ZWZ0c2WnkyZVlKZURSckVVZ1c5WXZCazJXSHVUUnJFZ0FTZnBxR2tKUkdnR3FiNmNidjFxR2N2Nm1FSFF5YlR5M2JOeXFxd3VRWXA3c3BuSlFObVJhUGk0Z3F1czVEWnVOc2NRZjFSMXhCdVN6WHk1YnNCaFlSZzdFcDZmNkJad0U2cHZCamt5ellqWERVYlF2a0VpeG0zcHR3RTRnZ2VZU21oUXFxbU1ac1lwcG1lY1VFMjhuTTdFekx2Q3hRZEZ1QndXZ2U3QURVYzdxVGYxeXNpUzl1YXdOTnA1aER2aHl2cXRDaWg3a3FvTHVzTGVnd2pHZTJTcDhDcUZmdUNRNWgxdHh4WHozdEdtRGZEUDE3Nm15R1htc3R0eDV5MjVTOXpwejg1ZEc4WnRrRnZ4bXNjOFltaXZlRUMycWFkY2FrWEoiLCJzdWIiOiJkaWQ6a2V5OnoyTUd3NGdrODRVU290YVdmNEFrSjgzRGNucmZnR2FjZUY4NktRWFJZTWZRN3hxblVGRVREN3RGNGprTkd2QUV0dlZ6Rm5RdTkydEZ3ZkNyb2ZWZ0c2WnkyZVlKZURSckVVZ1c5WXZCazJXSHVUUnJFZ0FTZnBxR2tKUkdnR3FiNmNidjFxR2N2Nm1FSFF5YlR5M2JOeXFxd3VRWXA3c3BuSlFObVJhUGk0Z3F1czVEWnVOc2NRZjFSMXhCdVN6WHk1YnNCaFlSZzdFcDZmNkJad0U2cHZCamt5ellqWERVYlF2a0VpeG0zcHR3RTRnZ2VZU21oUXFxbU1ac1lwcG1lY1VFMjhuTTdFekx2Q3hRZEZ1QndXZ2U3QURVYzdxVGYxeXNpUzl1YXdOTnA1aER2aHl2cXRDaWg3a3FvTHVzTGVnd2pHZTJTcDhDcUZmdUNRNWgxdHh4WHozdEdtRGZEUDE3Nm15R1htc3R0eDV5MjVTOXpwejg1ZEc4WnRrRnZ4bXNjOFltaXZlRUMycWFkY2FrWEoiLCJhdHQiOlt7ImFwaSI6IioiLCJjYXAiOiJTVVBFUl9VU0VSIn0seyJjYXAiOiJTVVBFUl9VU0VSIiwiZGF0YXNldCI6ImI1OndvcmxkX2JhbmtfcG9wdWxhdGlvbjoqIn1dfQ.SwctK9sJpUtgyOSKN3BMI1BfNT_X6xxy5Oy6aTCvGvdj-vJIxsioz2Po3TlFxpmo9uSJ_nGoUTW7fr7Hc5m8qqrUFnPrtPXOnSNluExh9sh0aXY1ACGNoDknhbnsU_5nkEhDSTOMQ0Y0MoqvkV_Ti-7ZjISEuGukvl4-FFXZVGl6zY7ii8-J3RQu60cMbR4xK-VnlXcZUnhREr8JQtPKfBnmjIvbPclnaOdXLSACgEPXsAX4gekYAb2HR8CduHmaFWqAq_Th-QbqgQVmqUw-VIwtwuxxfxpc-PTNV4L0eDH5jO9i7jVzU3KaWM8NzQ2vux_zhscjBQFR2SmpQuGO7A`
if expect != root.Raw {
t.Errorf("token mismatch. expected: %q.\ngot: %q", expect, root.Raw)
}
@@ -77,7 +77,7 @@ func TestPrivKeySource(t *testing.T) {
}
cidStr := mustCidString(t, derivedToken)
expectCID := "bafkreifglbwtr27fbzmv3uardlygvggr722fckusfvfyfsonwkroca7efu"
expectCID := "bafkreihpk5474uoolkqrge3yk5uy2s7rarhn5xwxfoiobcy6ye7vfxetgm"
if expectCID != cidStr {
t.Errorf("derived token CID mismatch. expected: %q.\ngot: %q", expectCID, cidStr)
@@ -90,6 +90,35 @@ func TestPrivKeySource(t *testing.T) {
// }
}
func TestED25519PrivKeySource(t *testing.T) {
keyOne, _, err := crypto.GenerateKeyPair(crypto.Ed25519, 123)
if err != nil {
t.Fatal(err)
}
source, err := ucan.NewPrivKeySource(keyOne)
if err != nil {
t.Fatal(err)
}
subjectDID, err := ucan.DIDStringFromPublicKey(keyOne.GetPublic())
if err != nil {
panic(err)
}
zero := time.Time{}
// create a root UCAN
origin, err := source.NewOriginToken(subjectDID, nil, nil, zero, zero)
if err != nil {
panic(err)
}
if _, err = origin.CID(); err != nil {
t.Fatal(err)
}
}
func TestTokenSource(t *testing.T) {
// ucan_spec.AssertTokenSourceSpec(t, func(ctx context.Context) ucan.TokenSource {
// source, err := ucan.NewPrivKeyTokenSource(peerInfo.PrivKey)
@@ -101,7 +130,7 @@ func TestTokenSource(t *testing.T) {
}
func TestTokenParse(t *testing.T) {
raw := `eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsInVjdiI6IjAuNC4wIn0.eyJpc3MiOiJkaWQ6a2V5Ok1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBb2FkUjRtY1U3QzBBbWg1bHRfM0hObVEyYVlDOEotYU5mNTJUNEtrLTBzbHh6LVc1LXhrREJ0NUR4RUZuSmVKNGJTMV9ZWkt3UkxKQjYzU0phcWZjMXhUTUFYMnJmcW44d3NwUmd2MEFReGU4RV9icGkzZTUyNnU2UU1VRjdYbDRKN2JkbVlZT0lCUDVCSk83eU1pX2pfU3FWaVdmOG82Y3BJTEF3dXpUNTY2X0ttUWFOclM5QmVNUHQ5NTJZUk1lejZlMFoycXR0aVRQS3hmalJ3b0VwRklldDVhZTFZY0p2VDBLQnJiZEYwNXhDc2F6RUoxSm52eUlSamNiUE9FYVljUjNPZnAxdW8ySTRKdVczQ2FKeHNqMU8yNnZyLWRUSzlqcGVFVTl5X1dUU1lNOUVsazBwZ0xZZ1M4ZHE4aTYwNDVnejByemU4QzV2YkZoSFZwa1ZRSURBUUFCIiwic3ViIjoiZGlkOmtleTpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQW9hZFI0bWNVN0MwQW1oNWx0XzNITm1RMmFZQzhKLWFOZjUyVDRLay0wc2x4ei1XNS14a0RCdDVEeEVGbkplSjRiUzFfWVpLd1JMSkI2M1NKYXFmYzF4VE1BWDJyZnFuOHdzcFJndjBBUXhlOEVfYnBpM2U1MjZ1NlFNVUY3WGw0SjdiZG1ZWU9JQlA1QkpPN3lNaV9qX1NxVmlXZjhvNmNwSUxBd3V6VDU2Nl9LbVFhTnJTOUJlTVB0OTUyWVJNZXo2ZTBaMnF0dGlUUEt4ZmpSd29FcEZJZXQ1YWUxWWNKdlQwS0JyYmRGMDV4Q3NhekVKMUpudnlJUmpjYlBPRWFZY1IzT2ZwMXVvMkk0SnVXM0NhSnhzajFPMjZ2ci1kVEs5anBlRVU5eV9XVFNZTTlFbGswcGdMWWdTOGRxOGk2MDQ1Z3owcnplOEM1dmJGaEhWcGtWUUlEQVFBQiIsImF0dCI6W3siYXBpIjoiKiIsImNhcCI6IlNVUEVSX1VTRVIifSx7ImNhcCI6IlNVUEVSX1VTRVIiLCJkYXRhc2V0IjoiYjU6d29ybGRfYmFua19wb3B1bGF0aW9uOioifV19.Z32-i-pGAtPRsG0JW4ZS8-c17x3mX3kFrmZ0BYhyWk2JH4QMwXFRtkUl8xVQtrC3JigeQeaDiz-WTUSFqJIs5dunL1Xf_SXqq8SZ7NCh6u6OEo2L1BnQkwdO8kDsFoiF42byWDBwzHRog0N-pRXgMhlo8si6Pek4KAZokQ5F-8FuLb3MXXxc9-FnhGRsKgGt_bNWS322h5gXCaXJAzbdAHwGSlORCCJI4CrbWUHs03i4viun2Ht01JO-p4ySlut6YyQ_vW4NGNSAAXGeR-ggkB0B6TGgt695CxX1zgQKV7X6JZx-NF_J-OXCIWngCfr6VdRv1_ADce9s1ODEm2N7eA`
raw := `eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsInVjdiI6IjAuNC4wIn0.eyJpc3MiOiJkaWQ6a2V5OnoyTUd3NGdrODRVU290YVdmNEFrSjgzRGNucmZnR2FjZUY4NktRWFJZTWZRN3hxblVGRVREN3RGNGprTkd2QUV0dlZ6Rm5RdTkydEZ3ZkNyb2ZWZ0c2WnkyZVlKZURSckVVZ1c5WXZCazJXSHVUUnJFZ0FTZnBxR2tKUkdnR3FiNmNidjFxR2N2Nm1FSFF5YlR5M2JOeXFxd3VRWXA3c3BuSlFObVJhUGk0Z3F1czVEWnVOc2NRZjFSMXhCdVN6WHk1YnNCaFlSZzdFcDZmNkJad0U2cHZCamt5ellqWERVYlF2a0VpeG0zcHR3RTRnZ2VZU21oUXFxbU1ac1lwcG1lY1VFMjhuTTdFekx2Q3hRZEZ1QndXZ2U3QURVYzdxVGYxeXNpUzl1YXdOTnA1aER2aHl2cXRDaWg3a3FvTHVzTGVnd2pHZTJTcDhDcUZmdUNRNWgxdHh4WHozdEdtRGZEUDE3Nm15R1htc3R0eDV5MjVTOXpwejg1ZEc4WnRrRnZ4bXNjOFltaXZlRUMycWFkY2FrWEoiLCJzdWIiOiJkaWQ6a2V5OnoyTUd3NGdrODRVU290YVdmNEFrSjgzRGNucmZnR2FjZUY4NktRWFJZTWZRN3hxblVGRVREN3RGNGprTkd2QUV0dlZ6Rm5RdTkydEZ3ZkNyb2ZWZ0c2WnkyZVlKZURSckVVZ1c5WXZCazJXSHVUUnJFZ0FTZnBxR2tKUkdnR3FiNmNidjFxR2N2Nm1FSFF5YlR5M2JOeXFxd3VRWXA3c3BuSlFObVJhUGk0Z3F1czVEWnVOc2NRZjFSMXhCdVN6WHk1YnNCaFlSZzdFcDZmNkJad0U2cHZCamt5ellqWERVYlF2a0VpeG0zcHR3RTRnZ2VZU21oUXFxbU1ac1lwcG1lY1VFMjhuTTdFekx2Q3hRZEZ1QndXZ2U3QURVYzdxVGYxeXNpUzl1YXdOTnA1aER2aHl2cXRDaWg3a3FvTHVzTGVnd2pHZTJTcDhDcUZmdUNRNWgxdHh4WHozdEdtRGZEUDE3Nm15R1htc3R0eDV5MjVTOXpwejg1ZEc4WnRrRnZ4bXNjOFltaXZlRUMycWFkY2FrWEoiLCJhdHQiOlt7ImFwaSI6IioiLCJjYXAiOiJTVVBFUl9VU0VSIn0seyJjYXAiOiJTVVBFUl9VU0VSIiwiZGF0YXNldCI6ImI1OndvcmxkX2JhbmtfcG9wdWxhdGlvbjoqIn1dfQ.SwctK9sJpUtgyOSKN3BMI1BfNT_X6xxy5Oy6aTCvGvdj-vJIxsioz2Po3TlFxpmo9uSJ_nGoUTW7fr7Hc5m8qqrUFnPrtPXOnSNluExh9sh0aXY1ACGNoDknhbnsU_5nkEhDSTOMQ0Y0MoqvkV_Ti-7ZjISEuGukvl4-FFXZVGl6zY7ii8-J3RQu60cMbR4xK-VnlXcZUnhREr8JQtPKfBnmjIvbPclnaOdXLSACgEPXsAX4gekYAb2HR8CduHmaFWqAq_Th-QbqgQVmqUw-VIwtwuxxfxpc-PTNV4L0eDH5jO9i7jVzU3KaWM8NzQ2vux_zhscjBQFR2SmpQuGO7A`
caps := ucan.NewNestedCapabilities("SUPER_USER", "OVERWRITE", "SOFT_DELETE", "REVISE", "CREATE")