diff --git a/token.go b/token.go index 9258331..4422288 100644 --- a/token.go +++ b/token.go @@ -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 @@ -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 +} diff --git a/v4.go b/v4.go index 6fdf8c8..862ee60 100644 --- a/v4.go +++ b/v4.go @@ -3,6 +3,7 @@ package paseto import ( "crypto/ed25519" "crypto/hmac" + "errors" "aidanwoods.dev/go-paseto/internal/encoding" "aidanwoods.dev/go-paseto/internal/hashing" @@ -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 +}