Skip to content

Commit f7bb0ae

Browse files
committed
Refactor algorithm factories
1 parent b50d025 commit f7bb0ae

11 files changed

+283
-204
lines changed

src/Alg/AbstractAlgorithmFactory.php

-124
This file was deleted.

src/Alg/Encryption/AES.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public function __construct(SymmetricKey $key, string $algId = C::BLOCK_ENC_AES2
2727

2828

2929
/**
30-
* @inheritDoc
30+
* @return string[]
3131
*/
3232
public static function getSupportedAlgorithms(): array
3333
{

src/Alg/Encryption/EncryptionAlgorithmFactory.php

+86-21
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,36 @@
55
namespace SimpleSAML\XMLSecurity\Alg\Encryption;
66

77
use SimpleSAML\Assert\Assert;
8-
use SimpleSAML\XMLSecurity\Alg\AbstractAlgorithmFactory;
98
use SimpleSAML\XMLSecurity\Constants as C;
109
use SimpleSAML\XMLSecurity\Exception\BlacklistedAlgorithmException;
1110
use SimpleSAML\XMLSecurity\Exception\UnsupportedAlgorithmException;
1211
use SimpleSAML\XMLSecurity\Key\KeyInterface;
1312

13+
use function array_key_exists;
14+
use function in_array;
15+
use function sprintf;
16+
1417
/**
1518
* Factory class to create and configure encryption algorithms.
1619
*
1720
* @package simplesamlphp/xml-security
1821
*/
19-
final class EncryptionAlgorithmFactory extends AbstractAlgorithmFactory
22+
final class EncryptionAlgorithmFactory
2023
{
24+
/**
25+
* A cache of algorithm implementations indexed by algorithm ID.
26+
*
27+
* @var array<string, \SimpleSAML\XMLSecurity\Alg\Encryption\EncryptionAlgorithmInterface>
28+
*/
29+
protected static array $cache = [];
30+
31+
/**
32+
* Whether the factory has been initialized or not.
33+
*
34+
* @var bool
35+
*/
36+
protected static bool $initialized = false;
37+
2138
/**
2239
* An array of blacklisted algorithms.
2340
*
@@ -30,44 +47,92 @@ final class EncryptionAlgorithmFactory extends AbstractAlgorithmFactory
3047
];
3148

3249
/**
33-
* A cache of algorithm implementations indexed by algorithm ID.
50+
* An array of default algorithms that can be used.
3451
*
35-
* @var array<string, \SimpleSAML\XMLSecurity\Alg\Encryption\EncryptionAlgorithmInterface>
52+
* @var class-string[]
3653
*/
37-
protected static array $cache = [];
54+
private const SUPPORTED_DEFAULTS = [
55+
TripleDES::class,
56+
AES::class,
57+
];
58+
3859

3960
/**
40-
* Whether the factory has been initialized or not.
61+
* Build a factory that creates algorithms.
4162
*
42-
* @var bool
63+
* @param string[]|null $blacklist A list of algorithms forbidden for their use.
4364
*/
44-
protected static bool $initialized = false;
65+
public function __construct(
66+
protected ?array $blacklist = self::DEFAULT_BLACKLIST,
67+
) {
68+
// initialize the cache for supported algorithms per known implementation
69+
if (!self::$initialized && $blacklist !== null) {
70+
foreach (self::SUPPORTED_DEFAULTS as $algorithm) {
71+
foreach ($algorithm::getSupportedAlgorithms() as $algId) {
72+
if (array_key_exists($algId, self::$cache)) {
73+
/*
74+
* If the key existed before initialization, that means someone registered a handler for this
75+
* algorithm, so we should respect that and skip registering the default here.
76+
*/
77+
continue;
78+
}
79+
self::$cache[$algId] = $algorithm;
80+
}
81+
}
82+
self::$initialized = true;
83+
}
84+
}
4585

4686

4787
/**
48-
* Build a factory that creates encryption algorithms.
88+
* Get a new object implementing the given digital signature algorithm.
4989
*
50-
* @param string[]|null $blacklist A list of algorithms forbidden for their use.
90+
* @param string $algId The identifier of the algorithm desired.
91+
* @param \SimpleSAML\XMLSecurity\Key\KeyInterface $key The key to use with the given algorithm.
92+
*
93+
* @return \SimpleSAML\XMLSecurity\Alg\Encryption\EncryptionAlgorithmInterface An object implementing the given
94+
* algorithm.
95+
*
96+
* @throws \SimpleSAML\XMLSecurity\Exception\UnsupportedAlgorithmException If an error occurs, e.g. the given
97+
* algorithm is blacklisted, unknown or the given key is not suitable for it.
5198
*/
52-
public function __construct(array $blacklist = null)
99+
public function getAlgorithm(string $algId, KeyInterface $key): EncryptionAlgorithmInterface
53100
{
54-
parent::__construct(
55-
$blacklist ?? self::DEFAULT_BLACKLIST,
56-
[
57-
TripleDES::class,
58-
AES::class,
59-
],
101+
Assert::false(
102+
($this->blacklist !== null) && in_array($algId, $this->blacklist, true),
103+
sprintf('Blacklisted algorithm: \'%s\'.', $algId),
104+
BlacklistedAlgorithmException::class,
60105
);
106+
Assert::keyExists(
107+
self::$cache,
108+
$algId,
109+
sprintf('Unknown or unsupported algorithm: \'%s\'.', $algId),
110+
UnsupportedAlgorithmException::class,
111+
);
112+
113+
return new self::$cache[$algId]($key, $algId);
61114
}
62115

63116

64117
/**
65-
* Get the name of the abstract class our algorithm implementations must extend.
118+
* Register an implementation of some algorithm(s) for its use.
66119
*
67-
* @return string
120+
* @param class-string $className
68121
*/
69-
protected static function getExpectedParent(): string
122+
public static function registerAlgorithm(string $className): void
70123
{
71-
return EncryptionAlgorithmInterface::class;
124+
Assert::implementsInterface(
125+
$className,
126+
EncryptionAlgorithmInterface::class,
127+
sprintf(
128+
'Cannot register algorithm "%s", must implement %s.',
129+
$className,
130+
EncryptionAlgorithmInterface::class,
131+
),
132+
);
133+
134+
foreach ($className::getSupportedAlgorithms() as $algId) {
135+
self::$cache[$algId] = $className;
136+
}
72137
}
73138
}

src/Alg/Encryption/TripleDES.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public function __construct(SymmetricKey $key)
2626

2727

2828
/**
29-
* @inheritDoc
29+
* @return string[]
3030
*/
3131
public static function getSupportedAlgorithms(): array
3232
{

src/Alg/KeyTransport/AbstractKeyTransporter.php

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace SimpleSAML\XMLSecurity\Alg\KeyTransport;
66

77
use SimpleSAML\Assert\Assert;
8-
use SimpleSAML\XMLSecurity\Alg\Encryption\EncryptionAlgorithmInterface;
98
use SimpleSAML\XMLSecurity\Backend;
109
use SimpleSAML\XMLSecurity\Backend\EncryptionBackend;
1110
use SimpleSAML\XMLSecurity\Exception\UnsupportedAlgorithmException;
@@ -16,7 +15,7 @@
1615
*
1716
* @package simplesamlphp/xml-security
1817
*/
19-
abstract class AbstractKeyTransporter implements EncryptionAlgorithmInterface
18+
abstract class AbstractKeyTransporter implements KeyTransportAlgorithmInterface
2019
{
2120
/** @var string */
2221
protected const DEFAULT_BACKEND = Backend\OpenSSL::class;

0 commit comments

Comments
 (0)