Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions token.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import (
"time"
)

type TokenSigner interface {
SignToken(data []byte) ([]byte, error)
}

// Token is a set of paseto claims, and a footer
type Token struct {
claims map[string]json.RawMessage
Expand Down Expand Up @@ -211,3 +215,20 @@ func (t Token) V4Sign(key V4AsymmetricSecretKey, implicit []byte) string {
func (t Token) V4Encrypt(key V4SymmetricKey, implicit []byte) string {
return v4LocalEncrypt(t.packet(), key, implicit, nil).encoded()
}

// V4SignWith signs the token, using the given token signer and implicit bytes. Implicit
// bytes are bytes used to calculate the signature, but which are not present in
// the final token.
// Implicit must be reprovided for successful verification, and can not be
// recovered.
func (t Token) V4SignWith(signer TokenSigner, implicit []byte) (string, error) {
if signer == nil {
panic("signer must not be nil")
}

sig, err := v4PublicSignWith(t.packet(), implicit, signer)
if err != nil {
return "", err
}
return sig.encoded(), nil
}
21 changes: 21 additions & 0 deletions v4.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package paseto
import (
"crypto/ed25519"
"crypto/hmac"
"errors"

"aidanwoods.dev/go-paseto/internal/encoding"
"aidanwoods.dev/go-paseto/internal/hashing"
Expand Down Expand Up @@ -100,3 +101,23 @@ func v4LocalDecrypt(msg message, key V4SymmetricKey, implicit []byte) result.Res

return result.Ok(packet{plainText, msg.footer})
}

func v4PublicSignWith(packet packet, implicit []byte, signer TokenSigner) (message, error) {
data, footer := packet.content, packet.footer
header := []byte(V4Public.Header())

m2 := encoding.Pae(header, data, footer, implicit)

sig, err := signer.SignToken(m2)
if err != nil {
return message{}, err
}
if len(sig) != 64 {
return message{}, errors.New("bad signature length")
}

var signature [64]byte
copy(signature[:], sig)

return newMessageFromPayloadAndFooter(v4PublicPayload{data, signature}, footer), nil
}