Skip to content
Open
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions src/Alg/Signature/AbstractSigner.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public function __construct(
$backend = new (static::DEFAULT_BACKEND)();
$this->setBackend($backend);
$this->backend->setDigestAlg($digest);
$this->backend->setSignaturePadding($algId);
}


Expand Down
2 changes: 1 addition & 1 deletion src/Alg/Signature/HMAC.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ final class HMAC extends AbstractSigner implements SignatureAlgorithmInterface
public function __construct(
#[\SensitiveParameter]
SymmetricKey $key,
string $algId = C::SIG_HMAC_SHA256,
string $algId,
) {
parent::__construct($key, $algId, C::$HMAC_DIGESTS[$algId]);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Alg/Signature/RSA.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ final class RSA extends AbstractSigner implements SignatureAlgorithmInterface
public function __construct(
#[\SensitiveParameter]
AsymmetricKey $key,
string $algId = C::SIG_RSA_SHA256,
string $algId,
) {
parent::__construct($key, $algId, C::$RSA_DIGESTS[$algId]);
}
Expand Down
3 changes: 2 additions & 1 deletion src/Alg/Signature/SignatureAlgorithmFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ final class SignatureAlgorithmFactory
/**
* An array of blacklisted algorithms.
*
* Defaults to RSA-SHA1 & HMAC-SHA1 due to the weakness of SHA1.
* Defaults to RSA-SHA1, RSAPSS-SHA1 & HMAC-SHA1 due to the weakness of SHA1.
*
* @var string[]
*/
public const array DEFAULT_BLACKLIST = [
C::SIG_RSA_SHA1,
C::SIG_RSA_PSS_SHA1,
C::SIG_HMAC_SHA1,
];

Expand Down
11 changes: 11 additions & 0 deletions src/Backend/HMAC.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ public function __construct()
}


/**
* Set the padding method to be used by this backend.
*
* @param string $algId The identifier of the signature algorithm.
*/
public function setSignaturePadding(string $algId): void
{
// No-op for HMAC
}


/**
* Set the digest algorithm to be used by this backend.
*
Expand Down
38 changes: 31 additions & 7 deletions src/Backend/OpenSSL.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ final class OpenSSL implements EncryptionBackend, SignatureBackend
// digital signature options
protected string $digest;

// signature padding method
protected int $sig_padding = OPENSSL_PKCS1_PADDING;

// asymmetric encryption options
protected int $padding = OPENSSL_PKCS1_OAEP_PADDING;
protected int $enc_padding = OPENSSL_PKCS1_OAEP_PADDING;

// symmetric encryption options
protected string $cipher;
Expand Down Expand Up @@ -83,7 +86,7 @@ public function encrypt(
}

$ciphertext = '';
if (!$fn($plaintext, $ciphertext, $key->getMaterial(), $this->padding)) {
if (!$fn($plaintext, $ciphertext, $key->getMaterial(), $this->enc_padding)) {
throw new OpenSSLException('Cannot encrypt data');
}
return $ciphertext;
Expand Down Expand Up @@ -139,7 +142,7 @@ public function decrypt(
}

$plaintext = '';
if (!$fn($ciphertext, $plaintext, $key->getMaterial(), $this->padding)) {
if (!$fn($ciphertext, $plaintext, $key->getMaterial(), $this->enc_padding)) {
throw new OpenSSLException('Cannot decrypt data');
}
return $plaintext;
Expand Down Expand Up @@ -192,7 +195,7 @@ public function sign(
KeyInterface $key,
string $plaintext,
): string {
if (!openssl_sign($plaintext, $signature, $key->getMaterial(), $this->digest)) {
if (!openssl_sign($plaintext, $signature, $key->getMaterial(), $this->digest, $this->sig_padding)) {
throw new OpenSSLException('Cannot sign data');
}
return $signature;
Expand All @@ -214,7 +217,7 @@ public function verify(
string $plaintext,
string $signature,
): bool {
return openssl_verify($plaintext, $signature, $key->getMaterial(), $this->digest) === 1;
return openssl_verify($plaintext, $signature, $key->getMaterial(), $this->digest, $this->sig_padding) === 1;
}


Expand All @@ -236,11 +239,11 @@ public function setCipher(string $cipher): void
$this->cipher = $cipher;
switch ($cipher) {
case C::KEY_TRANSPORT_RSA_1_5:
$this->padding = OPENSSL_PKCS1_PADDING;
$this->enc_padding = OPENSSL_PKCS1_PADDING;
break;
case C::KEY_TRANSPORT_OAEP:
case C::KEY_TRANSPORT_OAEP_MGF1P:
$this->padding = OPENSSL_PKCS1_OAEP_PADDING;
$this->enc_padding = OPENSSL_PKCS1_OAEP_PADDING;
break;
case C::BLOCK_ENC_AES128_GCM:
case C::BLOCK_ENC_AES192_GCM:
Expand All @@ -255,6 +258,27 @@ public function setCipher(string $cipher): void
}


/**
* Set the padding method to be used by this backend.
*
* @param string $algId The identifier of the signature algorithm.
*/
public function setSignaturePadding(string $algId): void
{
$padding = match ($algId) {
C::SIG_RSA_PSS_SHA1 => OPENSSL_PKCS1_PSS_PADDING,
C::SIG_RSA_PSS_SHA224 => OPENSSL_PKCS1_PSS_PADDING,
C::SIG_RSA_PSS_SHA256 => OPENSSL_PKCS1_PSS_PADDING,
C::SIG_RSA_PSS_SHA384 => OPENSSL_PKCS1_PSS_PADDING,
C::SIG_RSA_PSS_SHA512 => OPENSSL_PKCS1_PSS_PADDING,

default => OPENSSL_PKCS1_PADDING,
};

$this->sig_padding = $padding;
}


/**
* Set the digest algorithm to be used by this backend.
*
Expand Down
8 changes: 8 additions & 0 deletions src/Backend/SignatureBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ interface SignatureBackend
public function setDigestAlg(string $digest): void;


/**
* Set the padding method to be used by this backend.
*
* @param string $algId The identifier of the signature algorithm.
*/
public function setSignaturePadding(string $algId): void;


/**
* Sign a given plaintext with this cipher and a given key.
*
Expand Down
23 changes: 22 additions & 1 deletion src/Constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class Constants extends \SimpleSAML\XML\Constants
public const string C14N11_INCLUSIVE_WITHOUT_COMMENTS = 'http://www.w3.org/2006/12/xml-c14n11#WithComments';

/**
* Signature algorithms
* RSA Signature algorithms
*/
public const string SIG_RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';

Expand All @@ -116,6 +116,9 @@ class Constants extends \SimpleSAML\XML\Constants

public const string SIG_RSA_RIPEMD160 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-ripemd160';

/**
* HMAC Signature algorithms
*/
public const string SIG_HMAC_SHA1 = 'http://www.w3.org/2000/09/xmldsig#hmac-sha1';

public const string SIG_HMAC_SHA224 = 'http://www.w3.org/2001/04/xmldsig-more#hmac-sha224';
Expand All @@ -128,6 +131,19 @@ class Constants extends \SimpleSAML\XML\Constants

public const string SIG_HMAC_RIPEMD160 = 'http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160';

/**
* RSA-PSS Signature algorithms
*/
public const string SIG_RSA_PSS_SHA1 = 'http://www.w3.org/2007/05/xmldsig-more#sha1-rsa-MGF1';

public const string SIG_RSA_PSS_SHA224 = 'http://www.w3.org/2007/05/xmldsig-more#sha224-rsa-MGF1';

public const string SIG_RSA_PSS_SHA256 = 'http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1';

public const string SIG_RSA_PSS_SHA384 = 'http://www.w3.org/2007/05/xmldsig-more#sha384-rsa-MGF1';

public const string SIG_RSA_PSS_SHA512 = 'http://www.w3.org/2007/05/xmldsig-more#sha512-rsa-MGF1';

/**
* Encoding algorithms
*/
Expand Down Expand Up @@ -232,6 +248,11 @@ class Constants extends \SimpleSAML\XML\Constants
self::SIG_RSA_SHA384 => self::DIGEST_SHA384,
self::SIG_RSA_SHA512 => self::DIGEST_SHA512,
self::SIG_RSA_RIPEMD160 => self::DIGEST_RIPEMD160,
self::SIG_RSA_PSS_SHA1 => self::DIGEST_SHA1,
self::SIG_RSA_PSS_SHA224 => self::DIGEST_SHA224,
self::SIG_RSA_PSS_SHA256 => self::DIGEST_SHA256,
self::SIG_RSA_PSS_SHA384 => self::DIGEST_SHA384,
self::SIG_RSA_PSS_SHA512 => self::DIGEST_SHA512,
];

/** @var array<string, string> */
Expand Down
2 changes: 1 addition & 1 deletion src/XML/SignedElementTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ public function verify(?SignatureAlgorithmInterface $verifier = null): SignedEle
$verifier->getAlgorithmId(),
$algId,
'Algorithm provided in key does not match algorithm used in signature.',
SignatureVerificationFailedException::class,
);

return $this->verifyInternal($verifier);
Expand All @@ -303,7 +304,6 @@ public function verify(?SignatureAlgorithmInterface $verifier = null): SignedEle
"-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----",
strval($data->getContent()),
);

$cert = new Key\X509Certificate(PEM::fromString($cert));
$verifier = $factory->getAlgorithm($algId->getValue(), $cert->getPublicKey());

Expand Down
53 changes: 53 additions & 0 deletions tests/XML/SignableElementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -261,4 +261,57 @@ public function testSigningWithDifferentRoot(): void
);
$customSignable->toXML($doc->documentElement);
}


/**
* This test ensures we can sign using RSA-PSS algorithms and verify the signed element again.
*/
public function testSigningAndVerifyingRsaPssSha256(): void
{
$customSignable = CustomSignable::fromXML(
self::$xmlRepresentation->documentElement,
);

$factory = new SignatureAlgorithmFactory();

$signer = $factory->getAlgorithm(
C::SIG_RSA_PSS_SHA256,
self::$key,
);

$keyInfo = new KeyInfo([
new X509Data([
new X509Certificate(
Base64BinaryValue::fromString(self::$certificate),
),
]),
]);

$customSignable->sign(
$signer,
C::C14N_EXCLUSIVE_WITHOUT_COMMENTS,
$keyInfo,
);

$verified = CustomSignable::fromXML($customSignable->toXML())->verify();

$signature = $customSignable->getSignature();
$this->assertEquals(
C::SIG_RSA_PSS_SHA256,
$signature
->getSignedInfo()
->getSignatureMethod()
->getAlgorithm()
->getValue(),
);

$this->assertInstanceOf(CustomSignable::class, $verified);
$this->assertFalse($verified->isSigned());

$this->assertEquals(
'<ssp:CustomSignable xmlns:ssp="urn:x-simplesamlphp:namespace">'
. '<ssp:Chunk>Some</ssp:Chunk></ssp:CustomSignable>',
strval($verified),
);
}
}
Loading