[php-src] PR #24033: openssl_sign - restore default salt length without passing salt_length parameter
| From: | adapik | Date: | Thu, 01 Oct 2026 05:51:16 +0000 |
| Subject: | [php-src] PR #24033: openssl_sign - restore default salt length without passing salt_length parameter | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-39022@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/24033
Author: adapik
I found this while testing the new RSA-PSS bits in 8.6. After upgrading from 8.5 to 8.6,
openssl_sign() with OPENSSL_PKCS1_PSS_PADDING produces a different
signature. Same code, same OpenSSL (>= 3.1), but the salt length went from 32 (digest length) to
222 (max for RSA-2048/SHA-256).
```php
openssl_sign('data', $sig, $key, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING);
file_put_contents('sig.bin', $sig);
```
```
openssl dgst -sha256 -verify pub.pem -signature sig.bin \
-sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:digest data.txt
```
- PHP 8.5 + OpenSSL 4.0.2: Verified OK
- PHP 8.6 + OpenSSL 4.0.2: salt length check failed ... expected: 32 retrieved: 222,
Verification failure
### Why it happens
#20681 added $salt_length with default OPENSSL_RSA_PSS_SALTLEN_AUTO and
always passes it to EVP_PKEY_CTX_set_rsa_pss_saltlen(). For signing, an explicit
AUTO means "max". Before 8.6, PHP didn't set the salt length at all, so
OpenSSL's default was used, and since OpenSSL 3.1 that's the digest lenght.
### Why it's a BC break and why it matters
Apps signing with PSS on 8.5 get digest-length salts. After upgrading to 8.6 they silently start
producing max-length salts, with no error and no warning. Anything on the other side that pins salt
= hash length will start rejecting these signatures:
- JWT PS256/PS384/PS512 (RFC 7518 §3.5 requires salt = hash length)
- WebCrypto (saltLength is explicit)
- Go rsa.VerifyPSS with PSSSaltLengthEqualsHash
- FIPS 186-5 (salt <= hash length)
So an upgrade that looks harmless can break auth/tokens in production, and PHP-side tests won't
catch it.
### Suggested Fix
When $salt_length is AUTO, don't set it and let OpenSSL decide, same
as 8.5. DIGEST,ork as before. Nothing changes for openssl_verify(), since
AUTO is already OpenSSL'sdefault for verification. If you want max salt
explicitly, use OPENSSL_RSA_PSS_SALTLEN_MAX.
### Test
openssl_sign_pss_default_salt_length.phpt (OpenSSL >= 3.1): a default PSS signature
must verify with OPENSSL_RSA_PSS_SALTLEN_DIGEST. It fails without the fix.