33namespace Tempest \Cryptography \Tests \Signing ;
44
55use PHPUnit \Framework \TestCase ;
6+ use Tempest \Clock \Clock ;
7+ use Tempest \Clock \GenericClock ;
8+ use Tempest \Clock \MockClock ;
69use Tempest \Cryptography \Signing \Exceptions \SigningKeyWasMissing ;
710use Tempest \Cryptography \Signing \GenericSigner ;
811use Tempest \Cryptography \Signing \SigningAlgorithm ;
912use Tempest \Cryptography \Signing \SigningConfig ;
13+ use Tempest \Cryptography \Timelock ;
14+ use Tempest \DateTime \Duration ;
1015
1116final class SignerTest extends TestCase
1217{
18+ private function createSigner (SigningConfig $ config , ?Clock $ clock = null ): GenericSigner
19+ {
20+ return new GenericSigner (
21+ config: $ config ?? new SigningConfig (
22+ algorithm: SigningAlgorithm::SHA256 ,
23+ key: 'my_secret_key ' ,
24+ minimumExecutionDuration: false ,
25+ ),
26+ timelock: new Timelock ($ clock ?? new GenericClock ()),
27+ );
28+ }
29+
1330 public function test_good_signature (): void
1431 {
15- $ signer = new GenericSigner (new SigningConfig (
32+ $ signer = $ this -> createSigner (new SigningConfig (
1633 algorithm: SigningAlgorithm::SHA256 ,
1734 key: 'my_secret_key ' ,
35+ minimumExecutionDuration: false ,
1836 ));
1937
2038 $ data = 'important data ' ;
@@ -25,9 +43,10 @@ public function test_good_signature(): void
2543
2644 public function test_bad_signature (): void
2745 {
28- $ signer = new GenericSigner (new SigningConfig (
46+ $ signer = $ this -> createSigner (new SigningConfig (
2947 algorithm: SigningAlgorithm::SHA256 ,
3048 key: 'my_secret_key ' ,
49+ minimumExecutionDuration: false ,
3150 ));
3251
3352 $ data = 'important data ' ;
@@ -41,14 +60,16 @@ public function test_bad_signature(): void
4160
4261 public function test_different_algoritms (): void
4362 {
44- $ signer1 = new GenericSigner (new SigningConfig (
63+ $ signer1 = $ this -> createSigner (new SigningConfig (
4564 algorithm: SigningAlgorithm::SHA256 ,
4665 key: 'my_secret_key ' ,
66+ minimumExecutionDuration: false ,
4767 ));
4868
49- $ signer2 = new GenericSigner (new SigningConfig (
69+ $ signer2 = $ this -> createSigner (new SigningConfig (
5070 algorithm: SigningAlgorithm::SHA512 ,
5171 key: 'my_secret_key ' ,
72+ minimumExecutionDuration: false ,
5273 ));
5374
5475 $ data = 'important data ' ;
@@ -71,19 +92,21 @@ public function test_no_signing_key(): void
7192 {
7293 $ this ->expectException (SigningKeyWasMissing::class);
7394
74- $ signer = new GenericSigner (new SigningConfig (
95+ $ signer = $ this -> createSigner (new SigningConfig (
7596 algorithm: SigningAlgorithm::SHA256 ,
7697 key: '' ,
98+ minimumExecutionDuration: false ,
7799 ));
78100
79101 $ signer ->sign ('important data ' );
80102 }
81103
82104 public function test_empty_data (): void
83105 {
84- $ signer = new GenericSigner (new SigningConfig (
106+ $ signer = $ this -> createSigner (new SigningConfig (
85107 algorithm: SigningAlgorithm::SHA256 ,
86108 key: 'my_secret_key ' ,
109+ minimumExecutionDuration: false ,
87110 ));
88111
89112 $ signature = $ signer ->sign ('' );
@@ -94,9 +117,10 @@ public function test_empty_data(): void
94117
95118 public function test_consistent_signature (): void
96119 {
97- $ signer = new GenericSigner (new SigningConfig (
120+ $ signer = $ this -> createSigner (new SigningConfig (
98121 algorithm: SigningAlgorithm::SHA256 ,
99122 key: 'my_secret_key ' ,
123+ minimumExecutionDuration: false ,
100124 ));
101125
102126 $ data = 'important data ' ;
@@ -109,14 +133,16 @@ public function test_consistent_signature(): void
109133
110134 public function test_different_keys (): void
111135 {
112- $ signer1 = new GenericSigner (new SigningConfig (
136+ $ signer1 = $ this -> createSigner (new SigningConfig (
113137 algorithm: SigningAlgorithm::SHA256 ,
114138 key: 'signer1_key_foo ' ,
139+ minimumExecutionDuration: false ,
115140 ));
116141
117- $ signer2 = new GenericSigner (new SigningConfig (
142+ $ signer2 = $ this -> createSigner (new SigningConfig (
118143 algorithm: SigningAlgorithm::SHA512 ,
119144 key: 'signer2_key_bar ' ,
145+ minimumExecutionDuration: false ,
120146 ));
121147
122148 $ data = 'important data ' ;
@@ -134,4 +160,40 @@ public function test_different_keys(): void
134160 $ this ->assertFalse ($ signer1 ->verify ($ data , $ signature2 ));
135161 $ this ->assertFalse ($ signer2 ->verify ($ data , $ signature1 ));
136162 }
163+
164+ public function test_time_protection (): void
165+ {
166+ $ signer = $ this ->createSigner (new SigningConfig (
167+ algorithm: SigningAlgorithm::SHA256 ,
168+ key: 'my_secret_key ' ,
169+ minimumExecutionDuration: Duration::milliseconds (300 ),
170+ ));
171+
172+ $ data = 'important data ' ;
173+ $ signature = $ signer ->sign ($ data );
174+
175+ $ start = microtime (true );
176+ $ this ->assertTrue ($ signer ->verify ($ data , $ signature ));
177+ $ elapsed = microtime (true ) - $ start ;
178+
179+ $ this ->assertGreaterThanOrEqual (0.3 , $ elapsed );
180+ }
181+
182+ public function test_time_protection_with_mock_clock (): void
183+ {
184+ $ signer = $ this ->createSigner (new SigningConfig (
185+ algorithm: SigningAlgorithm::SHA256 ,
186+ key: 'my_secret_key ' ,
187+ minimumExecutionDuration: Duration::second (),
188+ ), $ clock = new MockClock ());
189+
190+ $ data = 'important data ' ;
191+ $ signature = $ signer ->sign ($ data );
192+
193+ $ ms = $ clock ->timestamp ()->getMilliseconds ();
194+ $ this ->assertTrue ($ signer ->verify ($ data , $ signature ));
195+ $ elapsed = $ clock ->timestamp ()->getMilliseconds () - $ ms ;
196+
197+ $ this ->assertSame (1_000 , $ elapsed );
198+ }
137199}
0 commit comments