From 5a1b6fd3753653b74577c7992b341a011a0ec416 Mon Sep 17 00:00:00 2001 From: Shulhan Date: Tue, 31 Mar 2026 18:52:39 +0700 Subject: lib/paseto: move [Message.Unpack] to [v4.UnpackPublicToken] Unpacking v4 public protocol on parent package seems wrong. Only v4 package should know how to unpack it regarding the available fields in the Message. --- lib/paseto/message.go | 51 -------------------------- lib/paseto/message_test.go | 44 ----------------------- lib/paseto/paseto.go | 11 ++++++ lib/paseto/payload.go | 4 +-- lib/paseto/v4/pasetov4.go | 51 ++++++++++++++++++++++++++ lib/paseto/v4/pasetov4_test.go | 59 +++++++++++++++++++++++++++++++ lib/paseto/v4/public_mode.go | 7 ++-- lib/paseto/v4/public_mode_example_test.go | 15 ++++---- 8 files changed, 136 insertions(+), 106 deletions(-) create mode 100644 lib/paseto/v4/pasetov4_test.go diff --git a/lib/paseto/message.go b/lib/paseto/message.go index f4383df2..7e9767ad 100644 --- a/lib/paseto/message.go +++ b/lib/paseto/message.go @@ -4,22 +4,9 @@ package paseto import ( - "crypto/ed25519" - "encoding/base64" - "errors" - "fmt" - "strings" "time" ) -// List of error messages for [Message.Unpack]. -var ( - ErrTokenHeader = errors.New(`invalid token header`) - ErrTokenPayload = errors.New(`invalid token payload`) - ErrTokenFooter = errors.New(`invalid token footer`) - ErrTokenSize = errors.New(`invalid token payload size`) -) - // Message defines the payload be signed and verified by sender/receiver. type Message struct { // The following fields are filled after Unpack and MUST not be used @@ -53,41 +40,3 @@ func NewMessage(sender, receiver Peer, subject string) (msg *Message) { } return msg } - -// Unpack returns the decoded token into a [Message]. -func (msg *Message) Unpack(header, token string, implicit []byte) (err error) { - logp := `Unpack` - - // Step 3: verify the header and unpack the footer if it exists. - token, found := strings.CutPrefix(token, header) - if !found { - return fmt.Errorf(`%s: %w: want %s`, logp, ErrTokenHeader, header) - } - token, footerb64, found := strings.Cut(token, `.`) - if found { - msg.RawFooter, err = base64.RawURLEncoding.DecodeString(footerb64) - if err != nil { - return fmt.Errorf(`%s: %w: %w`, logp, ErrTokenFooter, err) - } - } - - // Step 4: Decodes the payload. - paysig, err := base64.RawURLEncoding.DecodeString(token) - if err != nil { - return fmt.Errorf(`%s: %w: %w`, logp, ErrTokenPayload, err) - } - lenpaysig := len(paysig) - if lenpaysig <= ed25519.SignatureSize { - return fmt.Errorf(`%s: %w %d`, logp, ErrTokenSize, lenpaysig) - } - msg.RawPayload = paysig[:lenpaysig-64] - msg.Sig = paysig[lenpaysig-64:] - - // Step 5: Generate PAE. - msg.PAE, err = PreAuthEncode([]byte(header), msg.RawPayload, msg.RawFooter, implicit) - if err != nil { - return fmt.Errorf(`%s: %w`, logp, err) - } - - return nil -} diff --git a/lib/paseto/message_test.go b/lib/paseto/message_test.go index 4dd63755..aa4f7a23 100644 --- a/lib/paseto/message_test.go +++ b/lib/paseto/message_test.go @@ -43,47 +43,3 @@ func TestNewMessage(t *testing.T) { test.Assert(t, `NewMessage`, expmsg, string(gotmsg)) }) } - -func TestMessage_Unpack(t *testing.T) { - listcase := []struct { - desc string - token string - expError string - expMsg Message - }{{ - desc: `ErrTokenHeader`, - token: `v5.public.xxx.xxx`, - expError: `Unpack: invalid token header: want v4.public.`, - }, { - desc: `ErrTokenFooter`, - token: `v4.public.xxx.+++`, - expError: `Unpack: invalid token footer: illegal base64 data at input byte 0`, - }, { - desc: `ErrTokenPayload`, - token: `v4.public.WvLTlMrX9NpYDQlEIFlnDB==.xxx`, - expError: `Unpack: invalid token payload: illegal base64 data at input byte 22`, - }, { - desc: `ErrTokenSize`, - token: `v4.public.WvLTlMrX9NpYDQlEIFlnDB.xxx`, - expError: `Unpack: invalid token payload size 16`, - }, { - desc: `Valid`, - token: `v4.public.eyJkYXRhIjp7ImVtYWlsIjoiaGVsbG9AZXhhbXBsZS5jb20ifSwiaXNzIjoiam9obkBleGFtcGxlLmNvbSIsInN1YiI6ImhlbGxvIiwiYXVkIjoiamFuZUBleGFtcGxlLm9yZyIsImV4cCI6MTc3NDg1OTg4OSwibmJmIjoxNzc0ODU5ODI5LCJpYXQiOjE3NzQ4NTk4Mjl9eGHMkOlYiVchKl1GqQwSMyTC8eWCpXhNJHGHq_MEJNqlKur-kPpHqY-hWHoh4I1RaBq68MN_TNveqwPIbk9iBQ.eyJkYXRhIjp7InF1b3RlIjoiTGl2ZSB0byBlYXQifSwicGVlcl9pZCI6ImpvaG5AZXhhbXBsZS5jb20ifQ`, - expMsg: Message{ - RawPayload: []byte(`{"data":{"email":"hello@example.com"},"iss":"john@example.com","sub":"hello","aud":"jane@example.org","exp":1774859889,"nbf":1774859829,"iat":1774859829}`), - RawFooter: []byte(`{"data":{"quote":"Live to eat"},"peer_id":"john@example.com"}`), - Sig: []byte{0x78, 0x61, 0xcc, 0x90, 0xe9, 0x58, 0x89, 0x57, 0x21, 0x2a, 0x5d, 0x46, 0xa9, 0xc, 0x12, 0x33, 0x24, 0xc2, 0xf1, 0xe5, 0x82, 0xa5, 0x78, 0x4d, 0x24, 0x71, 0x87, 0xab, 0xf3, 0x4, 0x24, 0xda, 0xa5, 0x2a, 0xea, 0xfe, 0x90, 0xfa, 0x47, 0xa9, 0x8f, 0xa1, 0x58, 0x7a, 0x21, 0xe0, 0x8d, 0x51, 0x68, 0x1a, 0xba, 0xf0, 0xc3, 0x7f, 0x4c, 0xdb, 0xde, 0xab, 0x3, 0xc8, 0x6e, 0x4f, 0x62, 0x5}, - PAE: []byte{0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x76, 0x34, 0x2e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2e, 0x99, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7b, 0x22, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x3a, 0x22, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x40, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x22, 0x7d, 0x2c, 0x22, 0x69, 0x73, 0x73, 0x22, 0x3a, 0x22, 0x6a, 0x6f, 0x68, 0x6e, 0x40, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x22, 0x3a, 0x22, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x22, 0x2c, 0x22, 0x61, 0x75, 0x64, 0x22, 0x3a, 0x22, 0x6a, 0x61, 0x6e, 0x65, 0x40, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x22, 0x2c, 0x22, 0x65, 0x78, 0x70, 0x22, 0x3a, 0x31, 0x37, 0x37, 0x34, 0x38, 0x35, 0x39, 0x38, 0x38, 0x39, 0x2c, 0x22, 0x6e, 0x62, 0x66, 0x22, 0x3a, 0x31, 0x37, 0x37, 0x34, 0x38, 0x35, 0x39, 0x38, 0x32, 0x39, 0x2c, 0x22, 0x69, 0x61, 0x74, 0x22, 0x3a, 0x31, 0x37, 0x37, 0x34, 0x38, 0x35, 0x39, 0x38, 0x32, 0x39, 0x7d, 0x3d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7b, 0x22, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x22, 0x3a, 0x22, 0x4c, 0x69, 0x76, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x61, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x6a, 0x6f, 0x68, 0x6e, 0x40, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x22, 0x7d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, - }, - }} - - for _, tc := range listcase { - var msg Message - err := msg.Unpack(`v4.public.`, tc.token, nil) - if err != nil { - test.Assert(t, tc.desc, tc.expError, err.Error()) - continue - } - test.Assert(t, tc.desc, tc.expMsg, msg) - } -} diff --git a/lib/paseto/paseto.go b/lib/paseto/paseto.go index d5b3b569..0d2c1e8d 100644 --- a/lib/paseto/paseto.go +++ b/lib/paseto/paseto.go @@ -17,9 +17,20 @@ package paseto import ( "bytes" "encoding/binary" + "errors" "fmt" ) +// List of errors when unpacking token. +var ( + ErrToken = errors.New(`invalid token`) + ErrTokenFooter = errors.New(`invalid token footer`) + ErrTokenHeader = errors.New(`invalid token header`) + ErrTokenLen = errors.New(`invalid token payload length`) + ErrTokenPayload = errors.New(`invalid token payload`) + ErrTokenSigLen = errors.New(`invalid token signature length`) +) + // DefaultTTL define the time-to-live of a message, by setting ExpiredAt to // current time + [DefaultTTL]. // This value can be changes to increase the message expiration time. diff --git a/lib/paseto/payload.go b/lib/paseto/payload.go index d1086b45..af889d77 100644 --- a/lib/paseto/payload.go +++ b/lib/paseto/payload.go @@ -17,11 +17,11 @@ var DriftSeconds int64 = 5 // List of errors for [Payload.Validate]. var ( - ErrPayloadIssuer = errors.New(`unknown issuer`) - ErrPayloadSubject = errors.New(`unknown subject`) ErrPayloadAudience = errors.New(`invalid audience`) ErrPayloadExpired = errors.New(`expired`) + ErrPayloadIssuer = errors.New(`unknown issuer`) ErrPayloadNotBefore = errors.New(`token cannot be used yet`) + ErrPayloadSubject = errors.New(`unknown subject`) ) // Payload represents the data and claims. diff --git a/lib/paseto/v4/pasetov4.go b/lib/paseto/v4/pasetov4.go index b576aa70..50baf502 100644 --- a/lib/paseto/v4/pasetov4.go +++ b/lib/paseto/v4/pasetov4.go @@ -105,3 +105,54 @@ // // [paseto-v4]: https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version4.md package pasetov4 + +import ( + "crypto/ed25519" + "encoding/base64" + "fmt" + "strings" + + "git.sr.ht/~shulhan/pakakeh.go/lib/paseto" +) + +// UnpackPublicToken unpacks the v4 public token into msg. +func UnpackPublicToken(msg *paseto.Message, token string, implicit []byte) (err error) { + // Step 3: verify the header and token length. + if !strings.HasPrefix(token, PublicHeader) { + return fmt.Errorf(`%w, want %s`, paseto.ErrTokenHeader, PublicHeader) + } + pieces := strings.Split(token, `.`) + if len(pieces) < 3 { + return paseto.ErrToken + } + if len(pieces) >= 4 { + msg.RawFooter, err = base64.RawURLEncoding.DecodeString(pieces[3]) + if err != nil { + return fmt.Errorf(`%w: %w`, paseto.ErrTokenFooter, err) + } + } + + payload, err := base64.RawURLEncoding.DecodeString(pieces[2]) + if err != nil { + return fmt.Errorf(`%w: %w`, paseto.ErrTokenPayload, err) + } + + // Step 4: Decodes the payload. + lenpayload := len(payload) + if lenpayload <= ed25519.SignatureSize { + return fmt.Errorf(`%w %d`, paseto.ErrTokenLen, lenpayload) + } + msg.RawPayload = payload[:lenpayload-64] + msg.Sig = payload[lenpayload-64:] + if len(msg.Sig) != ed25519.SignatureSize { + return fmt.Errorf(`%w %d`, paseto.ErrTokenSigLen, len(msg.Sig)) + } + + // Step 5: Generate PAE. + msg.PAE, err = paseto.PreAuthEncode([]byte(PublicHeader), msg.RawPayload, msg.RawFooter, implicit) + if err != nil { + return err + } + + return nil +} diff --git a/lib/paseto/v4/pasetov4_test.go b/lib/paseto/v4/pasetov4_test.go new file mode 100644 index 00000000..51008608 --- /dev/null +++ b/lib/paseto/v4/pasetov4_test.go @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileCopyrightText: 2026 M. Shulhan + +package pasetov4 + +import ( + "testing" + + "git.sr.ht/~shulhan/pakakeh.go/lib/paseto" + "git.sr.ht/~shulhan/pakakeh.go/lib/test" +) + +func TestUnpackPublicToken(t *testing.T) { + listcase := []struct { + desc string + token string + expError string + expMsg paseto.Message + }{{ + desc: `ErrToken`, + token: `xxx`, + expError: `invalid token header, want v4.public.`, + }, { + desc: `ErrTokenHeader`, + token: `v5.public.xxx.xxx`, + expError: `invalid token header, want v4.public.`, + }, { + desc: `ErrTokenFooter`, + token: `v4.public.xxx.+++`, + expError: `invalid token footer: illegal base64 data at input byte 0`, + }, { + desc: `ErrTokenPayload`, + token: `v4.public.WvLTlMrX9NpYDQlEIFlnDB==`, + expError: `invalid token payload: illegal base64 data at input byte 22`, + }, { + desc: `ErrTokenLen`, + token: `v4.public.WvLTlMrX9NpYDQlEIFlnDB`, + expError: `invalid token payload length 16`, + }, { + desc: `v4.public`, + token: `v4.public.eyJkYXRhIjp7ImVtYWlsIjoiaGVsbG9AZXhhbXBsZS5jb20ifSwiaXNzIjoiam9obkBleGFtcGxlLmNvbSIsInN1YiI6ImhlbGxvIiwiYXVkIjoiamFuZUBleGFtcGxlLm9yZyIsImV4cCI6MTc3NDg1OTg4OSwibmJmIjoxNzc0ODU5ODI5LCJpYXQiOjE3NzQ4NTk4Mjl9eGHMkOlYiVchKl1GqQwSMyTC8eWCpXhNJHGHq_MEJNqlKur-kPpHqY-hWHoh4I1RaBq68MN_TNveqwPIbk9iBQ.eyJkYXRhIjp7InF1b3RlIjoiTGl2ZSB0byBlYXQifSwicGVlcl9pZCI6ImpvaG5AZXhhbXBsZS5jb20ifQ`, + expMsg: paseto.Message{ + RawPayload: []byte(`{"data":{"email":"hello@example.com"},"iss":"john@example.com","sub":"hello","aud":"jane@example.org","exp":1774859889,"nbf":1774859829,"iat":1774859829}`), + RawFooter: []byte(`{"data":{"quote":"Live to eat"},"peer_id":"john@example.com"}`), + Sig: []byte{0x78, 0x61, 0xcc, 0x90, 0xe9, 0x58, 0x89, 0x57, 0x21, 0x2a, 0x5d, 0x46, 0xa9, 0xc, 0x12, 0x33, 0x24, 0xc2, 0xf1, 0xe5, 0x82, 0xa5, 0x78, 0x4d, 0x24, 0x71, 0x87, 0xab, 0xf3, 0x4, 0x24, 0xda, 0xa5, 0x2a, 0xea, 0xfe, 0x90, 0xfa, 0x47, 0xa9, 0x8f, 0xa1, 0x58, 0x7a, 0x21, 0xe0, 0x8d, 0x51, 0x68, 0x1a, 0xba, 0xf0, 0xc3, 0x7f, 0x4c, 0xdb, 0xde, 0xab, 0x3, 0xc8, 0x6e, 0x4f, 0x62, 0x5}, + PAE: []byte{0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x76, 0x34, 0x2e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2e, 0x99, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7b, 0x22, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x3a, 0x22, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x40, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x22, 0x7d, 0x2c, 0x22, 0x69, 0x73, 0x73, 0x22, 0x3a, 0x22, 0x6a, 0x6f, 0x68, 0x6e, 0x40, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x22, 0x3a, 0x22, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x22, 0x2c, 0x22, 0x61, 0x75, 0x64, 0x22, 0x3a, 0x22, 0x6a, 0x61, 0x6e, 0x65, 0x40, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x22, 0x2c, 0x22, 0x65, 0x78, 0x70, 0x22, 0x3a, 0x31, 0x37, 0x37, 0x34, 0x38, 0x35, 0x39, 0x38, 0x38, 0x39, 0x2c, 0x22, 0x6e, 0x62, 0x66, 0x22, 0x3a, 0x31, 0x37, 0x37, 0x34, 0x38, 0x35, 0x39, 0x38, 0x32, 0x39, 0x2c, 0x22, 0x69, 0x61, 0x74, 0x22, 0x3a, 0x31, 0x37, 0x37, 0x34, 0x38, 0x35, 0x39, 0x38, 0x32, 0x39, 0x7d, 0x3d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7b, 0x22, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x22, 0x3a, 0x22, 0x4c, 0x69, 0x76, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x61, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x6a, 0x6f, 0x68, 0x6e, 0x40, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x22, 0x7d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + }, + }} + + for _, tc := range listcase { + var msg paseto.Message + err := UnpackPublicToken(&msg, tc.token, nil) + if err != nil { + test.Assert(t, tc.desc, tc.expError, err.Error()) + continue + } + test.Assert(t, tc.desc, tc.expMsg, msg) + } +} diff --git a/lib/paseto/v4/public_mode.go b/lib/paseto/v4/public_mode.go index 7137b888..e4b281d7 100644 --- a/lib/paseto/v4/public_mode.go +++ b/lib/paseto/v4/public_mode.go @@ -161,15 +161,16 @@ func (pmode *PublicMode) Unpack(token string, implicit []byte, msg *paseto.Messa ) { logp := `Unpack` - err = msg.Unpack(PublicHeader, token, implicit) + err = UnpackPublicToken(msg, token, implicit) if err != nil { return fmt.Errorf(`%s: %w`, logp, err) } err = json.Unmarshal(msg.RawFooter, &msg.Footer) if err != nil { - return fmt.Errorf(`%s: %w`, logp, err) + return fmt.Errorf(`%w: %w`, paseto.ErrTokenFooter, err) } + sender, ok := pmode.GetPeer(msg.Footer.PeerID) if !ok { return fmt.Errorf(`%s: %w %s`, logp, ErrPeerID, msg.Footer.PeerID) @@ -196,7 +197,7 @@ func (pmode *PublicMode) Verify(token string, implicit []byte) ( logp := `Verify` msg := &paseto.Message{} - err = msg.Unpack(PublicHeader, token, implicit) + err = UnpackPublicToken(msg, token, implicit) if err != nil { return nil, nil, fmt.Errorf(`%s: %w`, logp, err) } diff --git a/lib/paseto/v4/public_mode_example_test.go b/lib/paseto/v4/public_mode_example_test.go index 1d24ce69..990cb701 100644 --- a/lib/paseto/v4/public_mode_example_test.go +++ b/lib/paseto/v4/public_mode_example_test.go @@ -22,7 +22,7 @@ func ExamplePublicMode_Sign() { pmode := pasetov4.NewPublicMode(`testsign`, [32]byte(seed)) payload := []byte(`{"data":"signed message!"}`) - footer := []byte(`{"peer_id":1000}`) + footer := []byte(`{"peer_id":"1000"}`) token, err := pmode.Sign(payload, footer, nil) if err != nil { @@ -30,14 +30,17 @@ func ExamplePublicMode_Sign() { } msg := paseto.Message{} - msg.Unpack(pasetov4.PublicHeader, token, nil) + err = pasetov4.UnpackPublicToken(&msg, token, nil) + if err != nil { + log.Fatal(err) + } fmt.Printf("Payload: %s\n", msg.RawPayload) fmt.Printf("Footer: %s\n", msg.RawFooter) // Output: // Payload: {"data":"signed message!"} - // Footer: {"peer_id":1000} + // Footer: {"peer_id":"1000"} } func ExamplePublicMode_Verify() { @@ -48,7 +51,7 @@ func ExamplePublicMode_Verify() { } pmode := pasetov4.NewPublicMode(`testverify`, [32]byte(seed)) - token := `v4.public.eyJkYXRhIjoic2lnbmVkIG1lc3NhZ2UhIn0kqxCoccpjcXj3jNt6Q8cafIIF2JpapJrFNWi0mBJKS-Q3IU4dXZx-_Qx3P7LtSPnHyu6deqdeg72jb6hTCz4E.eyJwZWVyX2lkIjoxMDAwfQ` + token := `v4.public.eyJkYXRhIjoic2lnbmVkIG1lc3NhZ2UhIn2PyAoUJRvIViAgbEn0wVCLClzz26ZuJ7UY8z7rKRDXB0Vlo6i3QzYqmpg75TPJFQe2XX5_DmURV8hJnboNzH0H.eyJwZWVyX2lkIjoiMTAwMCJ9` gotPlain, gotFooter, err := pmode.Verify(token, nil) if err != nil { @@ -59,7 +62,7 @@ func ExamplePublicMode_Verify() { // Output: // {"data":"signed message!"} - // {"peer_id":1000} + // {"peer_id":"1000"} } func ExamplePublicMode_Pack() { @@ -94,7 +97,7 @@ func ExamplePublicMode_Pack() { } msg := paseto.Message{} - msg.Unpack(pasetov4.PublicHeader, token, nil) + pasetov4.UnpackPublicToken(&msg, token, nil) pdata := paseto.Payload{} _ = json.Unmarshal(msg.RawPayload, &pdata) -- cgit v1.3