1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace SimpleSAML\XMLSecurity\Test\Alg\Signature; |
6
|
|
|
|
7
|
|
|
use PHPUnit\Framework\TestCase; |
8
|
|
|
use SimpleSAML\XMLSecurity\Alg\Signature\RSA; |
9
|
|
|
use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; |
10
|
|
|
use SimpleSAML\XMLSecurity\Constants as C; |
11
|
|
|
use SimpleSAML\XMLSecurity\Key\PrivateKey; |
12
|
|
|
use SimpleSAML\XMLSecurity\Key\PublicKey; |
13
|
|
|
use SimpleSAML\XMLSecurity\Key\SymmetricKey; |
14
|
|
|
use SimpleSAML\XMLSecurity\Key\X509Certificate; |
15
|
|
|
use SimpleSAML\XMLSecurity\TestUtils\PEMCertificatesMock; |
16
|
|
|
use TypeError; |
17
|
|
|
|
18
|
|
|
use function bin2hex; |
19
|
|
|
use function hex2bin; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Tests for SimpleSAML\XMLSecurity\Alg\Signature\RSA. |
23
|
|
|
* |
24
|
|
|
* @package SimpleSAML\XMLSecurity\Alg |
25
|
|
|
*/ |
26
|
|
|
final class RSASignatureTest extends TestCase |
27
|
|
|
{ |
28
|
|
|
/** @var string */ |
29
|
|
|
protected const PLAINTEXT = 'plaintext'; |
30
|
|
|
|
31
|
|
|
/** @var \SimpleSAML\XMLSecurity\Key\PrivateKey */ |
32
|
|
|
protected static PrivateKey $privateKey; |
33
|
|
|
|
34
|
|
|
/** @var \SimpleSAML\XMLSecurity\Key\PublicKey */ |
35
|
|
|
protected static PublicKey $publicKey; |
36
|
|
|
|
37
|
|
|
/** @var \SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory */ |
38
|
|
|
protected static SignatureAlgorithmFactory $factory; |
39
|
|
|
|
40
|
|
|
|
41
|
|
|
public static function setUpBeforeClass(): void |
42
|
|
|
{ |
43
|
|
|
self::$publicKey = PEMCertificatesMock::getPublicKey(PEMCertificatesMock::PUBLIC_KEY); |
44
|
|
|
self::$privateKey = PEMCertificatesMock::getPrivateKey(PEMCertificatesMock::PRIVATE_KEY); |
45
|
|
|
self::$factory = new SignatureAlgorithmFactory([]); |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Test RSA signing. |
51
|
|
|
*/ |
52
|
|
|
public function testSign(): void |
53
|
|
|
{ |
54
|
|
|
// test RSA-SHA1 |
55
|
|
|
if (boolval(OPENSSL_VERSION_NUMBER >= hexdec('0x30000000')) === false) { |
56
|
|
|
// OpenSSL 3.0 disabled SHA1 support |
57
|
|
|
$rsa = self::$factory->getAlgorithm(C::SIG_RSA_SHA1, self::$privateKey); |
58
|
|
|
$this->assertEquals( |
59
|
|
|
'75780000a403f4280d361c246a1c23e650d59c8cabbe4064e1848bace35ba8931a7c397caacf8af36c10ead3bed5252109a' . |
60
|
|
|
'3c12a54b3f867950ae75ea29864babef465eabdda826d81c367583725012dfa68a1b51119425e3e6e9490c778db81b5be93' . |
61
|
|
|
'7ae35f4b1393944b7260d4ebd3c100bf59ae42d4506c82cae6550d68b8', |
62
|
|
|
bin2hex($rsa->sign(self::PLAINTEXT)), |
|
|
|
|
63
|
|
|
); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
// test RSA-SHA224 |
67
|
|
|
$rsa = self::$factory->getAlgorithm(C::SIG_RSA_SHA224, self::$privateKey); |
68
|
|
|
$this->assertEquals( |
69
|
|
|
'9f4bda98aefef8d289595e24663c02108d5273208eb9e530a5a2518082b9e357146517cb630dbaba5f9db7ac297e8b9b1b9248b' . |
70
|
|
|
'c4b2fbdf009450f4a0759080055b8d3b944d1781fcb03b1fe5039d59a293c54a3e5e8288ecfab9c3a3127f22816753e4aae835d' . |
71
|
|
|
'e395d52f30768d1d5003e3b124272e89a401909d34c24b9b8f', |
72
|
|
|
bin2hex($rsa->sign(self::PLAINTEXT)), |
73
|
|
|
); |
74
|
|
|
|
75
|
|
|
// test RSA-SHA256 |
76
|
|
|
$rsa = self::$factory->getAlgorithm(C::SIG_RSA_SHA256, self::$privateKey); |
77
|
|
|
$this->assertEquals( |
78
|
|
|
'397f0972d3d52b354298e8f1803efe6b6a77c2213605ab88ff3a38a336e14673c59f69103c1377c5ddf8f9314409ecd865f48b5' . |
79
|
|
|
'63af2e9ad31121846b0f565fa01898d9ab438ea5278734200400e62cc2bdd31ba86c7b98f8c51dbb22241fbe0535fe2291e9421' . |
80
|
|
|
'5450ca7fbe4cc8d18420cacce720ac39e09397019c67b8bb2e', |
81
|
|
|
bin2hex($rsa->sign(self::PLAINTEXT)), |
82
|
|
|
); |
83
|
|
|
|
84
|
|
|
// test RSA-SHA384 |
85
|
|
|
$rsa = self::$factory->getAlgorithm(C::SIG_RSA_SHA384, self::$privateKey); |
86
|
|
|
$this->assertEquals( |
87
|
|
|
'6f281ee29c08fa72aaf4f01b095f004608ed82351a160db91933f24118837d43864449862a60eda305d68169a7af12ebe1055b8' . |
88
|
|
|
'1e5e6a5effca3fd26f0f0db879d83c28a2ef833c021f1b523be2e6947749dbd7daf2d405e341858e95293c724244fc36fccfc05' . |
89
|
|
|
'27ce1d33e4ff9152e8fbe71eafa0867d076315cb8eb41a5fe5', |
90
|
|
|
bin2hex($rsa->sign(self::PLAINTEXT)), |
91
|
|
|
); |
92
|
|
|
|
93
|
|
|
// test RSA-SHA512 |
94
|
|
|
$rsa = self::$factory->getAlgorithm(C::SIG_RSA_SHA512, self::$privateKey); |
95
|
|
|
$this->assertEquals( |
96
|
|
|
'ce7c0840a26d6bb15e2d386aef8338fff631ca4f1fda22d21b19ee928ed87c7de9ea94f546bcace5dc8cd640a164667686cf836' . |
97
|
|
|
'bbcbce0f5bbd7c33d9e4262499a8c5c7d8159d090dd4c02fc49eab7e4522ba46258e50ee3278792bba13321780c64980fdd5034' . |
98
|
|
|
'f79285c07c5f765637950877feb03f94420799bb67b7b9a2ac', |
99
|
|
|
bin2hex($rsa->sign(self::PLAINTEXT)), |
100
|
|
|
); |
101
|
|
|
|
102
|
|
|
// test RSA-RIPEMD160 |
103
|
|
|
if (boolval(OPENSSL_VERSION_NUMBER >= hexdec('0x30000000')) === false) { |
104
|
|
|
// OpenSSL 3.0 disabled RIPEMD160 support |
105
|
|
|
$rsa = self::$factory->getAlgorithm(C::SIG_RSA_RIPEMD160, self::$privateKey); |
106
|
|
|
$this->assertEquals( |
107
|
|
|
'783d2c86bf73b02838be76f832fe1c75e03e9c3ad9055d19737a342c59385744b2332f65f1eac5f5dd0fb88ae7d145ac16d' . |
108
|
|
|
'3e83916a3be078e426a5ef5ed034a7f69f65ef5e62f6aecac9a896fa9edf473e482fd84ccc93c6677f146bf490af320ae41' . |
109
|
|
|
'f4a3fb0fa859e68c130a6d321ead6eb0167d1da24a49d97c030d3e8554', |
110
|
|
|
bin2hex($rsa->sign(self::PLAINTEXT)), |
111
|
|
|
); |
112
|
|
|
} |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Test RSA signature verification. |
118
|
|
|
*/ |
119
|
|
|
public function testVerify(): void |
120
|
|
|
{ |
121
|
|
|
// test RSA-SHA1 |
122
|
|
|
if (boolval(OPENSSL_VERSION_NUMBER >= hexdec('0x30000000')) === false) { |
123
|
|
|
// OpenSSL 3.0 disabled SHA1 support |
124
|
|
|
$rsa = self::$factory->getAlgorithm(C::SIG_RSA_SHA1, self::$publicKey); |
125
|
|
|
$this->assertTrue($rsa->verify( |
126
|
|
|
self::PLAINTEXT, |
127
|
|
|
hex2bin( |
128
|
|
|
'75780000a403f4280d361c246a1c23e650d59c8cabbe4064e1848bace35ba8931a7c397caacf8af36c10ead3bed5252' . |
129
|
|
|
'109a3c12a54b3f867950ae75ea29864babef465eabdda826d81c367583725012dfa68a1b51119425e3e6e9490c778db' . |
130
|
|
|
'81b5be937ae35f4b1393944b7260d4ebd3c100bf59ae42d4506c82cae6550d68b8', |
131
|
|
|
), |
132
|
|
|
)); |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
// test RSA-SHA224 |
136
|
|
|
$rsa = self::$factory->getAlgorithm(C::SIG_RSA_SHA224, self::$publicKey); |
137
|
|
|
$this->assertTrue($rsa->verify( |
138
|
|
|
self::PLAINTEXT, |
139
|
|
|
hex2bin( |
140
|
|
|
'9f4bda98aefef8d289595e24663c02108d5273208eb9e530a5a2518082b9e357146517cb630dbaba5f9db7ac297e8b9b1b9' . |
141
|
|
|
'248bc4b2fbdf009450f4a0759080055b8d3b944d1781fcb03b1fe5039d59a293c54a3e5e8288ecfab9c3a3127f22816753e' . |
142
|
|
|
'4aae835de395d52f30768d1d5003e3b124272e89a401909d34c24b9b8f', |
143
|
|
|
), |
144
|
|
|
)); |
145
|
|
|
|
146
|
|
|
// test RSA-SHA256 |
147
|
|
|
$rsa = self::$factory->getAlgorithm(C::SIG_RSA_SHA256, self::$publicKey); |
148
|
|
|
$this->assertTrue($rsa->verify( |
149
|
|
|
self::PLAINTEXT, |
150
|
|
|
hex2bin( |
151
|
|
|
'397f0972d3d52b354298e8f1803efe6b6a77c2213605ab88ff3a38a336e14673c59f69103c1377c5ddf8f9314409ecd865f' . |
152
|
|
|
'48b563af2e9ad31121846b0f565fa01898d9ab438ea5278734200400e62cc2bdd31ba86c7b98f8c51dbb22241fbe0535fe2' . |
153
|
|
|
'291e94215450ca7fbe4cc8d18420cacce720ac39e09397019c67b8bb2e', |
154
|
|
|
), |
155
|
|
|
)); |
156
|
|
|
|
157
|
|
|
// test RSA-SHA384 |
158
|
|
|
$rsa = self::$factory->getAlgorithm(C::SIG_RSA_SHA384, self::$publicKey); |
159
|
|
|
$this->assertTrue($rsa->verify( |
160
|
|
|
self::PLAINTEXT, |
161
|
|
|
hex2bin( |
162
|
|
|
'6f281ee29c08fa72aaf4f01b095f004608ed82351a160db91933f24118837d43864449862a60eda305d68169a7af12ebe10' . |
163
|
|
|
'55b81e5e6a5effca3fd26f0f0db879d83c28a2ef833c021f1b523be2e6947749dbd7daf2d405e341858e95293c724244fc3' . |
164
|
|
|
'6fccfc0527ce1d33e4ff9152e8fbe71eafa0867d076315cb8eb41a5fe5', |
165
|
|
|
), |
166
|
|
|
)); |
167
|
|
|
|
168
|
|
|
// test RSA-SHA512 |
169
|
|
|
$rsa = self::$factory->getAlgorithm(C::SIG_RSA_SHA512, self::$publicKey); |
170
|
|
|
$this->assertTrue($rsa->verify( |
171
|
|
|
self::PLAINTEXT, |
172
|
|
|
hex2bin( |
173
|
|
|
'ce7c0840a26d6bb15e2d386aef8338fff631ca4f1fda22d21b19ee928ed87c7de9ea94f546bcace5dc8cd640a164667686c' . |
174
|
|
|
'f836bbcbce0f5bbd7c33d9e4262499a8c5c7d8159d090dd4c02fc49eab7e4522ba46258e50ee3278792bba13321780c6498' . |
175
|
|
|
'0fdd5034f79285c07c5f765637950877feb03f94420799bb67b7b9a2ac', |
176
|
|
|
), |
177
|
|
|
)); |
178
|
|
|
|
179
|
|
|
// test RSA-RIPEMD160 |
180
|
|
|
if (boolval(OPENSSL_VERSION_NUMBER >= hexdec('0x30000000')) === false) { |
181
|
|
|
// OpenSSL 3.0 disabled RIPEMD160 support |
182
|
|
|
$rsa = self::$factory->getAlgorithm(C::SIG_RSA_RIPEMD160, self::$publicKey); |
183
|
|
|
$this->assertTrue($rsa->verify( |
184
|
|
|
self::PLAINTEXT, |
185
|
|
|
hex2bin( |
186
|
|
|
'783d2c86bf73b02838be76f832fe1c75e03e9c3ad9055d19737a342c59385744b2332f65f1eac5f5dd0fb88ae7d145a' . |
187
|
|
|
'c16d3e83916a3be078e426a5ef5ed034a7f69f65ef5e62f6aecac9a896fa9edf473e482fd84ccc93c6677f146bf490a' . |
188
|
|
|
'f320ae41f4a3fb0fa859e68c130a6d321ead6eb0167d1da24a49d97c030d3e8554', |
189
|
|
|
), |
190
|
|
|
)); |
191
|
|
|
} |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
|
195
|
|
|
/** |
196
|
|
|
* Test that verification fails properly. |
197
|
|
|
*/ |
198
|
|
|
public function testVerificationFailure(): void |
199
|
|
|
{ |
200
|
|
|
// test wrong plaintext |
201
|
|
|
$rsa = self::$factory->getAlgorithm(C::SIG_RSA_SHA1, self::$publicKey); |
202
|
|
|
$this->assertFalse($rsa->verify( |
203
|
|
|
self::PLAINTEXT . '.', |
204
|
|
|
'002e8007f09d327b48a7393c9e3666c0d0d73a437804d6e71191bc227546d62351cda58173d69dd792c783337c4ed903a59' . |
205
|
|
|
'b6fdfd221a0dd22e8632e66c020e1c07400b02625fcdb3821495593e0e0a776a616a2cdf268b3070f7d02e78fdc531c0275' . |
206
|
|
|
'9ad1fc292ee2f77dcb8a0232cb32e8808c57cb592329d48168bc73936d468421a83446a429cd03bd82aa4a099c2585e0ee6' . |
207
|
|
|
'0e8afc9b7731d07b00ac8e9f8e7e8c0f526506520c717af5926395b49e6644015e166b462649f65a7d9728ce8872d3b6b02' . |
208
|
|
|
'19550b4944cb6286e1278908c516be2391928df8d81298e619d0a8711c58e79e5536d7c39fa1b1ffc81d96be6e1b733a824' . |
209
|
|
|
'8d5fee2866c7f6e48', |
210
|
|
|
)); |
211
|
|
|
|
212
|
|
|
// test wrong signature |
213
|
|
|
$this->assertFalse($rsa->verify( |
214
|
|
|
self::PLAINTEXT, |
215
|
|
|
'002e8007f09d327b48a7393c9e3666c0d0d73a437804d6e71191bc227546d62351cda58173d69dd792c783337c4ed903a59' . |
216
|
|
|
'b6fdfd221a0dd22e8632e66c020e1c07400b02625fcdb3821495593e0e0a776a616a2cdf268b3070f7d02e78fdc531c0275' . |
217
|
|
|
'9ad1fc292ee2f77dcb8a0232cb32e8808c57cb592329d48168bc73936d468421a83446a429cd03bd82aa4a099c2585e0ee6' . |
218
|
|
|
'0e8afc9b7731d07b00ac8e9f8e7e8c0f526506520c717af5926395b49e6644015e166b462649f65a7d9728ce8872d3b6b02' . |
219
|
|
|
'19550b4944cb6286e1278908c516be2391928df8d81298e619d0a8711c58e79e5536d7c39fa1b1ffc81d96be6e1b733a824' . |
220
|
|
|
'8d5fee2866c7f6e48', |
221
|
|
|
)); |
222
|
|
|
|
223
|
|
|
// test wrong key |
224
|
|
|
$rsa = self::$factory->getAlgorithm( |
225
|
|
|
C::SIG_RSA_SHA1, |
226
|
|
|
PEMCertificatesMock::getPublicKey(PEMCertificatesMock::OTHER_PUBLIC_KEY) |
227
|
|
|
); |
228
|
|
|
$this->assertFalse($rsa->verify( |
229
|
|
|
self::PLAINTEXT, |
230
|
|
|
'002e8007f09d327b48a7393c9e3666c0d0d73a437804d6e71191bc227546d62351cda58173d69dd792c783337c4ed903a59' . |
231
|
|
|
'b6fdfd221a0dd22e8632e66c020e1c07400b02625fcdb3821495593e0e0a776a616a2cdf268b3070f7d02e78fdc531c0275' . |
232
|
|
|
'9ad1fc292ee2f77dcb8a0232cb32e8808c57cb592329d48168bc73936d468421a83446a429cd03bd82aa4a099c2585e0ee6' . |
233
|
|
|
'0e8afc9b7731d07b00ac8e9f8e7e8c0f526506520c717af5926395b49e6644015e166b462649f65a7d9728ce8872d3b6b02' . |
234
|
|
|
'19550b4944cb6286e1278908c516be2391928df8d81298e619d0a8711c58e79e5536d7c39fa1b1ffc81d96be6e1b733a824' . |
235
|
|
|
'8d5fee2866c7f6e48', |
236
|
|
|
)); |
237
|
|
|
} |
238
|
|
|
} |
239
|
|
|
|