diff options
| author | Shulhan <ms@kilabit.info> | 2026-03-30 15:27:13 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2026-03-30 16:27:50 +0700 |
| commit | cf94a6045d5e06b53101dac4a36d7b26be163b0b (patch) | |
| tree | 88524beb5f8418da9b1d2698544788c946e3ee5d /lib/paseto | |
| parent | b0795552ad0b5f4e57553cc91c887ef32bfa5f70 (diff) | |
| download | pakakeh.go-cf94a6045d5e06b53101dac4a36d7b26be163b0b.tar.xz | |
lib/paseto: predefines errors variables
Instead of fixed strings, predefined the error variables so the caller
can check the actual error.
Diffstat (limited to 'lib/paseto')
| -rw-r--r-- | lib/paseto/message.go | 17 | ||||
| -rw-r--r-- | lib/paseto/payload.go | 20 | ||||
| -rw-r--r-- | lib/paseto/v4/public_mode.go | 13 | ||||
| -rw-r--r-- | lib/paseto/v4/public_mode_example_test.go | 6 | ||||
| -rw-r--r-- | lib/paseto/v4/public_mode_test.go | 4 |
5 files changed, 35 insertions, 25 deletions
diff --git a/lib/paseto/message.go b/lib/paseto/message.go index e9dca297..ef84a84a 100644 --- a/lib/paseto/message.go +++ b/lib/paseto/message.go @@ -6,11 +6,19 @@ 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`) + 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 @@ -52,13 +60,13 @@ func (msg *Message) Unpack(header, token string, implicit []byte) (err error) { // Step 3: verify the header and unpack the footer if it exists. token, found := strings.CutPrefix(token, header) if !found { - return fmt.Errorf(`%s: invalid header, want %s`, logp, header) + 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: invalid footer: %w`, logp, err) + return fmt.Errorf(`%s: %w: %w`, logp, ErrTokenFooter, err) } } @@ -69,14 +77,13 @@ func (msg *Message) Unpack(header, token string, implicit []byte) (err error) { } lenpaysig := len(paysig) if lenpaysig <= ed25519.SignatureSize { - return fmt.Errorf(`%s: invalid payload size %d`, logp, lenpaysig) + 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) + msg.PAE, err = PreAuthEncode([]byte(header), msg.RawPayload, msg.RawFooter, implicit) if err != nil { return fmt.Errorf(`%s: %w`, logp, err) } diff --git a/lib/paseto/payload.go b/lib/paseto/payload.go index b9335afd..a659943a 100644 --- a/lib/paseto/payload.go +++ b/lib/paseto/payload.go @@ -15,11 +15,11 @@ const DriftSeconds = 5 // List of errors for [Payload.Validate]. var ( - ErrUnknownIssuer = errors.New(`unknown issuer`) - ErrUnknownSubject = errors.New(`unknown subject`) - ErrInvalidAudience = errors.New(`invalid audience`) - ErrExpired = errors.New(`expired`) - ErrNotBeforeAfter = errors.New(`not-before is after current time`) + ErrPayloadIssuer = errors.New(`unknown issuer`) + ErrPayloadSubject = errors.New(`unknown subject`) + ErrPayloadAudience = errors.New(`invalid audience`) + ErrPayloadExpired = errors.New(`expired`) + ErrPayloadNotBefore = errors.New(`payload cannot be used yet`) ) // Payload represents the data and claims. @@ -79,16 +79,16 @@ func (pload *Payload) Validate(recvID string, sender Peer) (err error) { now := time.Now().UTC().Unix() if pload.Issuer != sender.ID { - return fmt.Errorf(`%s: %w`, logp, ErrUnknownIssuer) + return fmt.Errorf(`%s: %w`, logp, ErrPayloadIssuer) } if len(sender.AllowedSubjects) != 0 { _, ok := sender.AllowedSubjects[pload.Subject] if !ok { - return fmt.Errorf(`%s: %w`, logp, ErrUnknownSubject) + return fmt.Errorf(`%s: %w`, logp, ErrPayloadSubject) } } if len(recvID) != 0 && pload.Audience != recvID { - return fmt.Errorf(`%s: %w`, logp, ErrInvalidAudience) + return fmt.Errorf(`%s: %w`, logp, ErrPayloadAudience) } if pload.ExpiredAt != 0 { diff := pload.ExpiredAt - now @@ -97,7 +97,7 @@ func (pload *Payload) Validate(recvID string, sender Peer) (err error) { diff *= -1 } if diff > DriftSeconds { - return fmt.Errorf(`%s: %w`, logp, ErrExpired) + return fmt.Errorf(`%s: %w`, logp, ErrPayloadExpired) } } if pload.NotBefore != 0 { @@ -106,7 +106,7 @@ func (pload *Payload) Validate(recvID string, sender Peer) (err error) { diff *= -1 } if diff > DriftSeconds { - return fmt.Errorf(`%s: %w`, logp, ErrNotBeforeAfter) + return fmt.Errorf(`%s: %w`, logp, ErrPayloadNotBefore) } } return nil diff --git a/lib/paseto/v4/public_mode.go b/lib/paseto/v4/public_mode.go index 605be124..776a8f06 100644 --- a/lib/paseto/v4/public_mode.go +++ b/lib/paseto/v4/public_mode.go @@ -21,6 +21,8 @@ const publicHeader = `v4.public.` // List of errors for [PublicMode.Unpack] and [PublicMode.Verify]. var ( ErrSignature = errors.New(`invalid signature`) + ErrPeerID = errors.New(`invalid or empty peer ID`) + ErrPublicKey = errors.New(`invalid or empty public key`) ) // PublicMode contains ed25519 private and public key for signing and @@ -35,11 +37,11 @@ type PublicMode struct { } // NewPublicMode returns new instance of public mode from ed25519 seeds. -func NewPublicMode(seed []byte) (pmode *PublicMode) { +func NewPublicMode(seed [ed25519.SeedSize]byte) (pmode *PublicMode) { pmode = &PublicMode{ peers: make(map[string]paseto.Peer), } - pmode.PrivateKey = ed25519.NewKeyFromSeed(seed) + pmode.PrivateKey = ed25519.NewKeyFromSeed(seed[:]) pmode.PublicKey = pmode.PrivateKey.Public().(ed25519.PublicKey) return pmode } @@ -48,11 +50,12 @@ func NewPublicMode(seed []byte) (pmode *PublicMode) { // token. // The only required fields in [paseto.Peer] is ID and Public. func (pmode *PublicMode) AddPeer(peer paseto.Peer) (err error) { + logp := `AddPeer` if len(peer.ID) == 0 { - return errors.New(`empty peer ID`) + return fmt.Errorf(`%s: %w`, logp, ErrPeerID) } if len(peer.Public) == 0 { - return errors.New(`empty public key`) + return fmt.Errorf(`%s: %w`, logp, ErrPeerID) } pmode.Lock() pmode.peers[peer.ID] = peer @@ -161,7 +164,7 @@ func (pmode *PublicMode) Unpack(token string, implicit []byte, msg *paseto.Messa } sender, ok := pmode.GetPeer(msg.Footer.PeerID) if !ok { - return fmt.Errorf(`%s: unknown peer ID %s`, logp, msg.Footer.PeerID) + return fmt.Errorf(`%s: %w %s`, logp, ErrPeerID, msg.Footer.PeerID) } if !ed25519.Verify(sender.Public, msg.PAE, msg.Sig) { diff --git a/lib/paseto/v4/public_mode_example_test.go b/lib/paseto/v4/public_mode_example_test.go index 7d2ee53a..8ca3536e 100644 --- a/lib/paseto/v4/public_mode_example_test.go +++ b/lib/paseto/v4/public_mode_example_test.go @@ -20,7 +20,7 @@ func ExamplePublicMode() { if err != nil { log.Fatal(err) } - pmode := NewPublicMode(seed) + pmode := NewPublicMode([32]byte(seed)) plain := []byte(`{"data":"signed message!"}`) footer := []byte(`{"kid":1000}`) @@ -54,7 +54,7 @@ func ExamplePublicMode_Pack() { if err != nil { log.Fatal(err) } - pmode = NewPublicMode(seed) + pmode = NewPublicMode([32]byte(seed)) peer = paseto.Peer{ ID: id, Private: pmode.PrivateKey, @@ -110,7 +110,7 @@ func ExamplePublicMode_Unpack() { if err != nil { log.Fatal(err) } - pmode = NewPublicMode(seed) + pmode = NewPublicMode([32]byte(seed)) peer = paseto.Peer{ ID: id, Private: pmode.PrivateKey, diff --git a/lib/paseto/v4/public_mode_test.go b/lib/paseto/v4/public_mode_test.go index 6c960c59..1231d86b 100644 --- a/lib/paseto/v4/public_mode_test.go +++ b/lib/paseto/v4/public_mode_test.go @@ -59,7 +59,7 @@ func TestPublicMode_Sign(t *testing.T) { }() tc.init() - pmode := NewPublicMode(tc.seed) + pmode := NewPublicMode([32]byte(tc.seed)) gotToken, err := pmode.Sign([]byte(tc.Payload), []byte(tc.Footer), []byte(tc.Implicit)) if err != nil { @@ -96,7 +96,7 @@ func TestPublicMode_Verify(t *testing.T) { }() tc.init() - pmode := NewPublicMode(tc.seed) + pmode := NewPublicMode([32]byte(tc.seed)) gotMsg, gotFooter, err := pmode.Verify(tc.Token, []byte(tc.Implicit)) if err != nil { if tc.ExpectFail { |
