Skip to content
Merged
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
58 changes: 48 additions & 10 deletions tests/Cryptography/Algorithms/RsaPss/AbstractRsaPssSignerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,27 @@ class AbstractRsaPssSignerTest extends TestCase
{
/**
* The signature the encoder must produce for the message `Text` under the 2041-bit fixture key with the
* salt fixed to `\xAB` * 32 — that modulus leaves no excess bits to clear and prepends a zero byte, so the
* whole encode path is pinned byte for byte. The OpenSSL CLI verifies this vector (PSS with salt length 32).
* salt `fixedSaltSigner()` pins — that modulus leaves no excess bits to clear and prepends a zero byte, so
* the whole encode path is pinned byte for byte and the encoded message keeps its `0xFF` leading byte. The
* OpenSSL CLI verifies this vector (PSS with salt length 32).
*/
private const FIXED_SALT_SIGNATURE_2041 =
'ARZEDL31+Fo7wUwGXgh2nqc8J6I6Tbc5gRfzYIsVeJQhXW+1/nqoP9KDVDZy7O46jX52Fze7+c1wFBAuq3c1BOkBtcx0zZOf'
. 'Jp6aZh6Vpvb5xhxcPb8+btLtGffC4Ypp2WcnGYdIuBYa0OGINAUNn5P9fMMxk3WJFYUDHzQx3I7NlaRISXmTSqrJOJUlardQ'
. 'P5Agmo/DKbXJmSmCyGm+lgeFAG+Rn2XvFGHhLc8nOrMA2uA5GFxWzAb2cMbosN95SwlqSinL0iEJG7BBFtGjUNjDxuMdd2j9'
. 'nN+sU3fzm1aIRI7tuqOtUkzoXJodg6APJn5zSbCnOIZ/8OTJ3YDfTA==';
'ANo31z7z+wPHh8Afo/ZX+YErxy/Fj+ngyfgRVC8tVCyOEzdR9mec6bSG05nsE6oGubxSLyQ8V9MYQ0V7qSci+Wl6VT3digh8'
. 'mJ3JkEtm+pQ7k6+VrBp9MYCC+yQmI6setHLV6DGqwIIMjyz3KrKwjxaAtYYDYvuTbBzNSSdSxSQsZinGUVLliT+E879Nh4rH'
. '9JZLBX4egxByGyvTfoMKUAX3pNnQD/SqpEkJxdxJHiZtm1O2laOpk3oI4jp8Ke9OBJWOiV99JrjuSBiPuFzd1TzEpH2hEGHO'
. 'hkT34v3iiawUYZ/vziuRMpk/11KjfqvmNN9aILyalsLgL+tVcGUdGg==';

/**
* The same vector under the 2047-bit fixture key, whose two excess bits the encoder must clear: the `0xFF`
* leading byte of the encoded message has to come out as `0x3F`. Together with the 2041-bit vector, which
* clears nothing, this pins the bit-clearing step for both shapes of modulus — no run of the suite depends
* on a random salt happening to expose those bits. The OpenSSL CLI verifies this vector too.
*/
private const FIXED_SALT_SIGNATURE_2047 =
'A8kN0RON8TzrHc/0ZFhoyegSJoegm+oMmkOynOMJjY3HqFd7Nx2M4cAvAwfh1otJd6GPDKsKG5bC5GyB+FRig4TWqrliLR0P'
. 'dyPMNNp5N0V+iXMsENOGtPEZ8ofnv6HK+Sn+PV2PuUr64K4suIrnSyvpcrZ1oUkCxHqOdbCYG7UwwnVg2AGNJoVoaE/qI5Y/'
. 'oBynmdxLyFlqvlRM7th/p0iAO7qRDDJ3nedAWxgbjdpGJzXSpgy2SASk1KxUOwsTTy+BByVGPUJ39Ear/EqZ04t3ujLHboCZ'
. '/iWYCiL2HfFDd/BCVW8amphnUMus3X4XpUVRGapGAyZGFs3NqCelkw==';

protected RsaPrivateKey $rsaPrivateKey;

Expand Down Expand Up @@ -75,14 +88,39 @@ public function test_sign_it_should_produce_a_signature_of_the_modulus_size()
*/
public function test_sign_with_a_fixed_salt_it_should_produce_the_expected_signature()
{
$signer = new class (new RsaPrivateKey(KeyFixtures::PRIVATE_KEY_2041)) extends PS256Signer {
$signer = $this->fixedSaltSigner(KeyFixtures::PRIVATE_KEY_2041);

$this->assertSame((string)base64_decode(self::FIXED_SALT_SIGNATURE_2041), $signer->sign('Text'));
}

/**
* The same for a modulus that leaves excess bits to clear, so the signature also pins the bit-clearing step
* of the encoding rather than only the bits a random salt happens to expose.
*
* @throws Throwable
*/
public function test_sign_with_a_fixed_salt_and_excess_bits_it_should_produce_the_expected_signature()
{
$signer = $this->fixedSaltSigner(KeyFixtures::PRIVATE_KEY_2047);

$this->assertSame((string)base64_decode(self::FIXED_SALT_SIGNATURE_2047), $signer->sign('Text'));
}

/**
* A signer whose salt is pinned, which makes EMSA-PSS deterministic. The salt is chosen so the masked data
* block starts with `0xFF` before the excess bits are cleared: every bit the encoder is supposed to clear
* (or leave alone) is then visible in the signature, whatever the modulus size leaves over.
*
* @throws Throwable
*/
private function fixedSaltSigner(string $privateKey): PS256Signer
{
return new class (new RsaPrivateKey($privateKey)) extends PS256Signer {
protected function salt(int $length): string
{
return str_repeat("\xAB", $length);
return str_repeat("\xAB", $length - 1) . "\x72";
}
};

$this->assertSame((string)base64_decode(self::FIXED_SALT_SIGNATURE_2041), $signer->sign('Text'));
}

/**
Expand Down
Loading