This is v2.0.0 of the PHP implementation of PASETO.
At a glance:
- This library now requires PHP 7.1 or newer.
- This library now requires the GMP extension installed (due to an additional dependency).
- The default protocol has been changed from
Version2
toVersion4
. If you weren't defining this in your code and relying on the default settings, you will need to be explicit before you upgrade.
A lot has changed; please read carefully.
We've moved the PASETO Specification to another repository. In this updated specification, we have defined two new PASETO protocol versions.
- Version 3 is the successor to Version 1 for systems that MUST only use NIST-approved algorithms.
- Version 4 is the successor to Version 2 for systems that want to use the algorithms provided by libsodium over the choices made by NIST and/or the US National Security Agency.
If you'd like to read the full rationale for the design decisions made in Versions 3 and 4, these have been documented clearly here.
Although we strongly recommend migrating to the new versions (v1 -> v3, v2 -> v4), you are fine to continue using v1/v2 if the following assumptions hold true:
- PHP's
random_bytes()
is working correctly (i.e. talking to the kernel's CSPRNG). - For
v1.public
tokens:- You don't require Exclusive Ownership (PDF) for your application
- For
v2.local
tokens:- You will only use one key at a time, and attackers cannot switch between them (i.e. no Key IDs in the footer)
If any of these assumptions are invalid, you MUST use the new versions to get the security properties you need out of PASETO. See the brief yet concise Migration Guide for more information.
Questions and Answers
What if I'm unsure if I should migrate to the newer version?
If you aren't 100% sure you don't need the security properties offered by v3/v4, and have nothing preventing you from making the change (i.e. a hard dependency on RSA keys), then you should lean towards migrating.
It's better to have it and not need it, than need it and not have it.
Is PASETO v1/v2 vulnerable?
Generally, no. That's why we aren't immediately deprecating their use. The complete answer requires a bit of nuance:
-
AEAD modes based on Polynomial MACs, such as AES-GCM and XChaCha20-Poly1305, do not offer message- or key-commitment. This means it's possible to construct two different plaintexts that, under two different keys, yield the same (nonce, ciphertext, tag) tuple. This means that a given PASETO v2 token might decode to two different payloads, under two different keys.
- If you're using v2.local tokens with some sort of homemade key-wrapping scheme that doesn't provide key-commitment, then YES, you SHOULD treat this as a sev:low vulnerability in your application. The relevant attack is complex and usually requires some degree of privileged access to pull off.
- The fix is to migrate to Version4.
- If you're using Key-IDs, then you probably want to migrate just in case, but we're not aware of any actual risks when the attacker can only switch between a finite set of possible keys outside their control.
- If you need an interim mitigation (because, for some reason, you can't just migrate), it's possible to by including a KDF output of your symmetric key. (See below.)
- If you aren't, it's not really a big deal. Carry on.
- If you're using v2.local tokens with some sort of homemade key-wrapping scheme that doesn't provide key-commitment, then YES, you SHOULD treat this as a sev:low vulnerability in your application. The relevant attack is complex and usually requires some degree of privileged access to pull off.
-
@thaidn disclosed an unfortunate failure mode that's unlikely to ever happen: If the CSPRNG returns a predictable output (for example, all
NUL
bytes), then the derived nonce will be the hash of your plaintext payload. RNG failures with PHP 7's CSPRNG are fatal errors, so a silently-failing CSPRNG is very unlikely, but if it ever did happen, attackers could leak your plaintext by brute-forcing the hash that produces the nonce. This is only relevant to v1.local and v2.local.- If it ever did happen in general, it would break the security of key/nonce generation in all cryptographic applications.
-
How RSA signatures are used in PASETO v1.public tokens do not offer Exclusive Ownership. Learn more about why it matters.
Bottom-line: digital signatures yield guarantees about a message for a given public key, not the other way round.
-- Thomas Pornin
These are all nuisances we sought to fix in Version 3 and Version 4. As a result, the new versions offer a more robust argument for their security in a wider range of real-world use cases.
What would a Version2 mitigation look like?
Use this to commit/verify that the same key was used for a given PASETO:
<?php
function v2key_commit(SymmetricKey $key): string {
return sodium_bin2hex(
sodium_crypto_generichash('MITIGATION_COMMIT_KEY', $key->raw())
);
}
function v2key_verify(SymmetricKey $key, string $commitment): bool {
$calc = v2key_commit($key);
return hash_equals($calc, $commitment);
}
Just store the commitment hash inside the footer, then verify it before parsing. Since this will be bundled with the token (and cryptographically bound to it through the Poly1305 authentication tag), even if an attacker can perform some trickery, v2key_verify()
will return false
if the target is decrypting the token with the wrong key.
Is there a CVE identifier for any of those issues?
No, a CVE ID is not appropriate for non-vulnerabilities.
If any system is specifically impacted by the Poly1305 issue in v2.local tokens, and sets up the condition that makes the complex attack possible, then a CVE would be appropriate for that specific application. This generally means "wrote our own key-wrapping scheme based on AES-GCM or ChaCha20-Poly1305".
Although the RNG failure mode sounds scary, the security of your entire system depends on the CSPRNG not failing. This is sort of like getting a DoS attack to work from root. You will almost certainly never be impacted by this.
If any system is affected by the lack of Exclusive Ownership in v1.public tokens, then a) we want to hear about this system and b) a CVE definitely would be appropriate for whatever was built--but EO was never a stated goal for v1.public tokens, so its absence doesn't qualify as a vulnerability in PASETO.
We believe that requesting a CVE identifier out of an abundance of caution will only create alert fatigue for the overwhelming majority of systems that will not be at risk.