From 6e3d2f12d6617a6caa45b4a2eeec2dc54aa8d17a Mon Sep 17 00:00:00 2001 From: Shulhan Date: Mon, 30 Mar 2026 17:06:21 +0700 Subject: paseto/v4: embed the Peer inside the PublicMode This provides simple operation when working with Pack and Unpack. --- lib/paseto/v4/public_mode.go | 21 +++++++++------ lib/paseto/v4/public_mode_example_test.go | 44 +++++++++++-------------------- lib/paseto/v4/public_mode_test.go | 4 +-- 3 files changed, 31 insertions(+), 38 deletions(-) diff --git a/lib/paseto/v4/public_mode.go b/lib/paseto/v4/public_mode.go index 10e19cd6..551f1a5e 100644 --- a/lib/paseto/v4/public_mode.go +++ b/lib/paseto/v4/public_mode.go @@ -33,19 +33,24 @@ var ( type PublicMode struct { peers map[string]paseto.Peer - PrivateKey ed25519.PrivateKey - PublicKey ed25519.PublicKey + paseto.Peer sync.Mutex } // NewPublicMode returns new instance of public mode from ed25519 seeds. -func NewPublicMode(seed [ed25519.SeedSize]byte) (pmode *PublicMode) { +// The id parameter is required when processing [paseto.Message] with +// [PublicMode.Pack] and [PublicMode.Unpack], but optional when processing +// payload with [PublicMode.Sign] and [PublicMode.Verify]. +func NewPublicMode(id string, seed [ed25519.SeedSize]byte) (pmode *PublicMode) { pmode = &PublicMode{ peers: make(map[string]paseto.Peer), + Peer: paseto.Peer{ + ID: id, + Private: ed25519.NewKeyFromSeed(seed[:]), + }, } - pmode.PrivateKey = ed25519.NewKeyFromSeed(seed[:]) - pmode.PublicKey = pmode.PrivateKey.Public().(ed25519.PublicKey) + pmode.Public = pmode.Private.Public().(ed25519.PublicKey) return pmode } @@ -66,7 +71,7 @@ func (pmode *PublicMode) AddPeer(peer paseto.Peer) (err error) { return nil } -// GetPeer returns the Peer and true if ID found in list of peers. +// GetPeer returns the Peer and true if ID found in list of known peers. func (pmode *PublicMode) GetPeer(id string) (peer paseto.Peer, ok bool) { pmode.Lock() peer, ok = pmode.peers[id] @@ -122,7 +127,7 @@ func (pmode *PublicMode) Sign(payload, footer, implicit []byte) ( } // Step 4: Sign pae. - sig := ed25519.Sign(pmode.PrivateKey, pae) + sig := ed25519.Sign(pmode.Peer.Private, pae) // Step 5: Pack all into token, var buf bytes.Buffer @@ -197,7 +202,7 @@ func (pmode *PublicMode) Verify(token string, implicit []byte) ( } // Step 6: Verify the signature. - if !ed25519.Verify(pmode.PublicKey, msg.PAE, msg.Sig) { + if !ed25519.Verify(pmode.Peer.Public, msg.PAE, msg.Sig) { return nil, nil, fmt.Errorf(`%s: %w`, logp, ErrSignature) } diff --git a/lib/paseto/v4/public_mode_example_test.go b/lib/paseto/v4/public_mode_example_test.go index 49f98ce0..1d24ce69 100644 --- a/lib/paseto/v4/public_mode_example_test.go +++ b/lib/paseto/v4/public_mode_example_test.go @@ -19,7 +19,7 @@ func ExamplePublicMode_Sign() { if err != nil { log.Fatal(err) } - pmode := pasetov4.NewPublicMode([32]byte(seed)) + pmode := pasetov4.NewPublicMode(`testsign`, [32]byte(seed)) payload := []byte(`{"data":"signed message!"}`) footer := []byte(`{"peer_id":1000}`) @@ -46,7 +46,7 @@ func ExamplePublicMode_Verify() { if err != nil { log.Fatal(err) } - pmode := pasetov4.NewPublicMode([32]byte(seed)) + pmode := pasetov4.NewPublicMode(`testverify`, [32]byte(seed)) token := `v4.public.eyJkYXRhIjoic2lnbmVkIG1lc3NhZ2UhIn0kqxCoccpjcXj3jNt6Q8cafIIF2JpapJrFNWi0mBJKS-Q3IU4dXZx-_Qx3P7LtSPnHyu6deqdeg72jb6hTCz4E.eyJwZWVyX2lkIjoxMDAwfQ` @@ -63,31 +63,24 @@ func ExamplePublicMode_Verify() { } func ExamplePublicMode_Pack() { - createPeer := func(id, secret string) ( - peer paseto.Peer, pmode *pasetov4.PublicMode, - ) { + createPeerMode := func(id, secret string) (pmode *pasetov4.PublicMode) { seed, err := hex.DecodeString(secret) if err != nil { log.Fatal(err) } - pmode = pasetov4.NewPublicMode([32]byte(seed)) - peer = paseto.Peer{ - ID: id, - Private: pmode.PrivateKey, - Public: pmode.PublicKey, - } - return peer, pmode + pmode = pasetov4.NewPublicMode(id, [32]byte(seed)) + return pmode } - sender, senderpm := createPeer( + senderpm := createPeerMode( `john@example.com`, `b4cbfb43df4ce210727d953e4a713307fa19bb7d9f85041438d9e11b942a3774`, ) - receiver, _ := createPeer( + receivpm := createPeerMode( `jane@example.org`, `2222222222222222222222222222222222222222222222222222222222222222`, ) - sendMsg := paseto.NewMessage(sender, receiver, `hello`) + sendMsg := paseto.NewMessage(senderpm.Peer, receivpm.Peer, `hello`) sendMsg.Payload.Data = map[string]string{ `email`: `hello@example.com`, } @@ -114,38 +107,33 @@ func ExamplePublicMode_Pack() { } func ExamplePublicMode_Unpack() { - createPeer := func(id, secret string) ( - peer paseto.Peer, pmode *pasetov4.PublicMode, + createPeerMode := func(id, secret string) ( + pmode *pasetov4.PublicMode, ) { seed, err := hex.DecodeString(secret) if err != nil { log.Fatal(err) } - pmode = pasetov4.NewPublicMode([32]byte(seed)) - peer = paseto.Peer{ - ID: id, - Private: pmode.PrivateKey, - Public: pmode.PublicKey, - } - return peer, pmode + pmode = pasetov4.NewPublicMode(id, [32]byte(seed)) + return pmode } - sender, _ := createPeer( + senderpm := createPeerMode( `john@example.com`, `b4cbfb43df4ce210727d953e4a713307fa19bb7d9f85041438d9e11b942a3774`, ) - _, recvpm := createPeer( + receivpm := createPeerMode( `jane@example.org`, `2222222222222222222222222222222222222222222222222222222222222222`, ) // Add the sender to list of receiver's peer. - recvpm.AddPeer(sender) + receivpm.AddPeer(senderpm.Peer) // This is the token send by sender. token := `v4.public.eyJkYXRhIjp7ImVtYWlsIjoiaGVsbG9AZXhhbXBsZS5jb20ifSwiaXNzIjoiam9obkBleGFtcGxlLmNvbSIsInN1YiI6ImhlbGxvIiwiYXVkIjoiamFuZUBleGFtcGxlLm9yZyIsImV4cCI6MTc3NDg1OTg4OSwibmJmIjoxNzc0ODU5ODI5LCJpYXQiOjE3NzQ4NTk4Mjl9eGHMkOlYiVchKl1GqQwSMyTC8eWCpXhNJHGHq_MEJNqlKur-kPpHqY-hWHoh4I1RaBq68MN_TNveqwPIbk9iBQ.eyJkYXRhIjp7InF1b3RlIjoiTGl2ZSB0byBlYXQifSwicGVlcl9pZCI6ImpvaG5AZXhhbXBsZS5jb20ifQ` recvMsg := paseto.Message{} - err := recvpm.Unpack(token, nil, &recvMsg) + err := receivpm.Unpack(token, nil, &recvMsg) if err != nil { log.Fatal(err) } diff --git a/lib/paseto/v4/public_mode_test.go b/lib/paseto/v4/public_mode_test.go index 1231d86b..658facb8 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([32]byte(tc.seed)) + pmode := NewPublicMode(`testsign`, [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([32]byte(tc.seed)) + pmode := NewPublicMode(`testverify`, [32]byte(tc.seed)) gotMsg, gotFooter, err := pmode.Verify(tc.Token, []byte(tc.Implicit)) if err != nil { if tc.ExpectFail { -- cgit v1.3