Closed slashnick closed 2 years ago
Oh, I guess a simpler way to construct duplicate tokens with would be to append ==
. Maybe that should be blocked too?
PASETO doesn't use Base64, PASETO uses Base64url (RFC 4648).
From the relevant section of the specification.
Nearly every component in a Paseto (except for the version, purpose, and the
.
separators) will be encoded using Base64url, without=
padding.
If you'd like us to strengthen the wording ("MUST NOT include padding"; "decoders MUST be strict when decoding", etc.) then that's worth considering.
PHP encoding library updated: https://github.com/paragonie/constant_time_encoding/releases/tag/v2.6.0
Reference implementation updated: https://github.com/paragonie/paseto/releases/tag/v3.0.1
Thanks for reporting this.
If the data in a base64 field of a PASETO token isn't a multiple of 6 bits, the last base64 character will be padded with 2 or 4 "zero" bits. But when decoding, most base64 libraries will ignore those last 4 bits.
eg.
base64_encode(b"\xff")
(11111111) =="_w"
(111111 110000). But during decodingbase64_decode("_w")
(111111 110000) ==base64_decode("_y")
(111111 110001).So given a valid PASETO token, you can construct a slightly different token with the same content but a different base64 representation. For example, these two public tokens both decode to the same content, despite having different final characters.
v4.public.eyJleHAiOiIyMDIyLTA2LTA5VDE4OjI0OjA4LTA0OjAwIiwidXNlciI6Inplcm8gY29vbCJ9CaoTvJwHuqZgEE8bQVpaIo3sTdZMEtuAXicK_mB2km98GkxvHYc_7nAzCsWjsnvI7OiwUW9aVyS5UnPOXYBnCw
v4.public.eyJleHAiOiIyMDIyLTA2LTA5VDE4OjI0OjA4LTA0OjAwIiwidXNlciI6Inplcm8gY29vbCJ9CaoTvJwHuqZgEE8bQVpaIo3sTdZMEtuAXicK_mB2km98GkxvHYc_7nAzCsWjsnvI7OiwUW9aVyS5UnPOXYBnCx
It seems weird for PASETO libraries to accept tokens that they clearly didn't generate.