Skip to content

Commit 5ddf5fc

Browse files
committed
Migrate moved to spark command
Test created for new spark command
1 parent 27fee69 commit 5ddf5fc

5 files changed

Lines changed: 200 additions & 96 deletions

File tree

phpunit.xml.dist

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,10 @@
9393
<!-- https://getcomposer.org/xdebug -->
9494
<env name="COMPOSER_DISABLE_XDEBUG_WARN" value="1"/>
9595

96-
<!-- Database configuration -->
96+
<!-- Default HMAC encryption key -->
97+
<env name="authtoken.hmacEncryptionKey" value="hex2bin:178ed94fd0b6d57dd31dd6b22fc601fab8ad191efac165a5f3f30a8ac09d813d"/>
98+
99+
<!-- Database configuration -->
97100
<env name="database.tests.strictOn" value="true"/>
98101
<!-- Uncomment to use alternate testing database configuration
99102
<env name="database.tests.hostname" value="localhost"/>

src/Commands/Hmac.php

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace CodeIgniter\Shield\Commands;
6+
7+
use CodeIgniter\Shield\Authentication\HMAC\HmacEncrypter;
8+
use CodeIgniter\Shield\Commands\Exceptions\BadInputException;
9+
use CodeIgniter\Shield\Models\UserIdentityModel;
10+
use ReflectionException;
11+
12+
class Hmac extends BaseCommand
13+
{
14+
/**
15+
* The Command's name
16+
*
17+
* @var string
18+
*/
19+
protected $name = 'shield:hmac';
20+
21+
/**
22+
* the Command's short description
23+
*
24+
* @var string
25+
*/
26+
protected $description = 'Encrypt/Decrypt secretKey for HMAC tokens. The encryption should only be run on existing raw secret keys (extremely rare).';
27+
28+
/**
29+
* the Command's usage
30+
*
31+
* @var string
32+
*/
33+
protected $usage = <<<'EOL'
34+
shield:hmac <action>
35+
shield:hmac encrypt
36+
shield:hmac decrypt
37+
EOL;
38+
39+
/**
40+
* the Command's Arguments
41+
*
42+
* @var array
43+
*/
44+
protected $arguments = [
45+
'action' => <<<'EOL'
46+
encrypt: Encrypt all raw HMAC Secret Keys
47+
decrypt: Decrypt all encrypted HMAC Secret Keys
48+
EOL,
49+
];
50+
51+
/**
52+
* HMAC Encrypter Object
53+
*/
54+
private HmacEncrypter $encrypter;
55+
56+
/**
57+
* the Command's Options
58+
*
59+
* @var array
60+
*/
61+
protected $options = [];
62+
63+
/**
64+
* Run Encryption Methods
65+
*/
66+
public function run(array $params): int
67+
{
68+
$action = $params[0] ?? null;
69+
70+
$this->encrypter = new HmacEncrypter();
71+
72+
try {
73+
switch ($action) {
74+
case 'encrypt':
75+
$this->encrypt();
76+
break;
77+
78+
case 'decrypt':
79+
$this->decrypt();
80+
break;
81+
82+
default:
83+
throw new BadInputException('Unrecognized Command');
84+
}
85+
} catch (BadInputException|ReflectionException $e) {
86+
$this->write($e->getMessage(), 'red');
87+
88+
return EXIT_ERROR;
89+
}
90+
91+
return EXIT_SUCCESS;
92+
}
93+
94+
/**
95+
* Encrypt all Raw HMAC Secret Keys
96+
*
97+
* @throws ReflectionException
98+
*/
99+
public function encrypt(): void
100+
{
101+
$uIdModel = new UserIdentityModel();
102+
$encrypter = $this->encrypter;
103+
104+
$uIdModel->where('type', 'hmac_sha256')->chunk(
105+
100,
106+
static function ($identity) use ($uIdModel, $encrypter): void {
107+
$identity->secret2 = $encrypter->encrypt($identity->secret2);
108+
109+
$uIdModel->save($identity);
110+
}
111+
);
112+
}
113+
114+
/**
115+
* Decrypt all encrypted HMAC Secret Keys
116+
*
117+
* @throws ReflectionException
118+
*/
119+
public function decrypt(): void
120+
{
121+
$uIdModel = new UserIdentityModel();
122+
$encrypter = $this->encrypter;
123+
124+
$uIdModel->where('type', 'hmac_sha256')->chunk(
125+
100,
126+
static function ($identity) use ($uIdModel, $encrypter): void {
127+
$identity->secret2 = $encrypter->decrypt($identity->secret2);
128+
129+
$uIdModel->save($identity);
130+
}
131+
);
132+
}
133+
}

src/Database/Migrations/2023-10-30-222755_EncryptHmacKeys.php

Lines changed: 0 additions & 93 deletions
This file was deleted.

tests/Commands/HmacTest.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Commands;
6+
7+
use CodeIgniter\Shield\Authentication\HMAC\HmacEncrypter;
8+
use CodeIgniter\Shield\Entities\User;
9+
use CodeIgniter\Shield\Models\UserIdentityModel;
10+
use CodeIgniter\Shield\Models\UserModel;
11+
use Tests\Support\DatabaseTestCase;
12+
13+
/**
14+
* @internal
15+
*/
16+
final class HmacTest extends DatabaseTestCase
17+
{
18+
public function testEncrypt(): void
19+
{
20+
$idModel = new UserIdentityModel();
21+
22+
/** @var User $user */
23+
$user = fake(UserModel::class);
24+
$token = $user->generateHmacToken('foo');
25+
26+
$rawSecretKey = $token->rawSecretKey;
27+
$token->secret2 = $rawSecretKey;
28+
29+
$idModel->save($token);
30+
$tokenCheck = $idModel->find($token->id);
31+
32+
$this->assertSame($rawSecretKey, $tokenCheck->secret2);
33+
34+
$this->assertNotFalse(command('shield:hmac encrypt'));
35+
36+
$tokenCheck = $idModel->find($token->id);
37+
38+
$encrypter = new HmacEncrypter();
39+
$decryptedKey = $encrypter->decrypt($tokenCheck->secret2);
40+
41+
$this->assertSame($rawSecretKey, $decryptedKey);
42+
}
43+
44+
public function testDecrypt(): void
45+
{
46+
$idModel = new UserIdentityModel();
47+
48+
/** @var User $user */
49+
$user = fake(UserModel::class);
50+
$token = $user->generateHmacToken('foo');
51+
52+
$rawSecretKey = $token->rawSecretKey;
53+
54+
$this->assertNotFalse(command('shield:hmac decrypt'));
55+
56+
$token->secret2 = $rawSecretKey;
57+
58+
$idModel->save($token);
59+
$tokenCheck = $idModel->find($token->id);
60+
61+
$this->assertSame($rawSecretKey, $tokenCheck->secret2);
62+
}
63+
}

tests/_support/TestCase.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ abstract class TestCase extends CIUnitTestCase
2525
{
2626
protected function setUp(): void
2727
{
28-
$_ENV['authtoken.hmacEncryptionKey'] = 'hex2bin:178ed94fd0b6d57dd31dd6b22fc601fab8ad191efac165a5f3f30a8ac09d813d';
29-
3028
$this->resetServices();
3129

3230
parent::setUp();

0 commit comments

Comments
 (0)