5
5
namespace SimpleSAML \XMLSecurity \Alg \Encryption ;
6
6
7
7
use SimpleSAML \Assert \Assert ;
8
- use SimpleSAML \XMLSecurity \Alg \AbstractAlgorithmFactory ;
9
8
use SimpleSAML \XMLSecurity \Constants as C ;
10
9
use SimpleSAML \XMLSecurity \Exception \BlacklistedAlgorithmException ;
11
10
use SimpleSAML \XMLSecurity \Exception \UnsupportedAlgorithmException ;
12
11
use SimpleSAML \XMLSecurity \Key \KeyInterface ;
13
12
13
+ use function array_key_exists ;
14
+ use function in_array ;
15
+ use function sprintf ;
16
+
14
17
/**
15
18
* Factory class to create and configure encryption algorithms.
16
19
*
17
20
* @package simplesamlphp/xml-security
18
21
*/
19
- final class EncryptionAlgorithmFactory extends AbstractAlgorithmFactory
22
+ final class EncryptionAlgorithmFactory
20
23
{
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
+
21
38
/**
22
39
* An array of blacklisted algorithms.
23
40
*
@@ -30,44 +47,92 @@ final class EncryptionAlgorithmFactory extends AbstractAlgorithmFactory
30
47
];
31
48
32
49
/**
33
- * A cache of algorithm implementations indexed by algorithm ID .
50
+ * An array of default algorithms that can be used .
34
51
*
35
- * @var array< string, \SimpleSAML\XMLSecurity\Alg\Encryption\EncryptionAlgorithmInterface>
52
+ * @var class- string[]
36
53
*/
37
- protected static array $ cache = [];
54
+ private const SUPPORTED_DEFAULTS = [
55
+ TripleDES::class,
56
+ AES ::class,
57
+ ];
58
+
38
59
39
60
/**
40
- * Whether the factory has been initialized or not .
61
+ * Build a factory that creates algorithms .
41
62
*
42
- * @var bool
63
+ * @param string[]|null $blacklist A list of algorithms forbidden for their use.
43
64
*/
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
+ }
45
85
46
86
47
87
/**
48
- * Build a factory that creates encryption algorithms .
88
+ * Get a new object implementing the given digital signature algorithm .
49
89
*
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.
51
98
*/
52
- public function __construct ( array $ blacklist = null )
99
+ public function getAlgorithm ( string $ algId , KeyInterface $ key ): EncryptionAlgorithmInterface
53
100
{
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,
60
105
);
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 );
61
114
}
62
115
63
116
64
117
/**
65
- * Get the name of the abstract class our algorithm implementations must extend .
118
+ * Register an implementation of some algorithm(s) for its use .
66
119
*
67
- * @return string
120
+ * @param class- string $className
68
121
*/
69
- protected static function getExpectedParent ( ): string
122
+ public static function registerAlgorithm ( string $ className ): void
70
123
{
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
+ }
72
137
}
73
138
}
0 commit comments