feat: app
This commit is contained in:
@@ -11,6 +11,7 @@ use App\Models\WalletMnemonic;
|
||||
use App\Services\EthKeystore;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use kornrunner\Keccak;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use Tests\TestCase;
|
||||
|
||||
@@ -89,8 +90,7 @@ class KeystoreAdminTest extends TestCase
|
||||
$this->actingAs($admin, 'admin')
|
||||
->get(route('admin.devices.show', [$device, 'tab' => 'keystores']))
|
||||
->assertOk()
|
||||
->assertSee('钥匙串')
|
||||
->assertSee('lay-event="decrypt">密码解密</a>', false);
|
||||
->assertSee('钥匙串');
|
||||
|
||||
$this->actingAs($admin, 'admin')
|
||||
->getJson(route('admin.devices.tabData', [$device, 'tab' => 'keystores']))
|
||||
@@ -399,6 +399,44 @@ class KeystoreAdminTest extends TestCase
|
||||
$this->assertSame(1, (int) $row->fresh()->decrypted);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function imtoken_web3_keystore_without_needs_password_flag_uses_password_decrypt(): void
|
||||
{
|
||||
Http::fake();
|
||||
$admin = Admin::query()->create(['username' => 'admin', 'password' => 'admin123']);
|
||||
$phrase = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
|
||||
$password = 'imtoken-password';
|
||||
$device = Device::query()->create(['device_id' => 'DEVKSIMTOKEN']);
|
||||
$row = WalletKeystore::query()->create([
|
||||
'device_id' => $device->id,
|
||||
'source' => 'imToken',
|
||||
'decrypted' => 0,
|
||||
'raw_json' => $this->makeImTokenPbkdf2Keystore($phrase, $password),
|
||||
]);
|
||||
|
||||
$this->actingAs($admin, 'admin')
|
||||
->get(route('admin.devices.show', [$device, 'tab' => 'keystores']))
|
||||
->assertOk()
|
||||
->assertSee('lay-event="decryptPassword">密码解密</a>', false);
|
||||
|
||||
$this->actingAs($admin, 'admin')
|
||||
->getJson(route('admin.devices.tabData', [$device, 'tab' => 'keystores']))
|
||||
->assertOk()
|
||||
->assertJsonPath('data.0.needs_password', null)
|
||||
->assertJsonPath('data.0.has_web3_keystore', true)
|
||||
->assertJsonPath('data.0.password_decrypt_url', route('admin.keystores.decryptPassword', $row));
|
||||
|
||||
$this->actingAs($admin, 'admin')
|
||||
->postJson(route('admin.keystores.decryptPassword', $row), ['password' => $password])
|
||||
->assertOk()
|
||||
->assertJsonPath('code', 0)
|
||||
->assertJsonPath('data.added', 1);
|
||||
|
||||
$mnemonic = WalletMnemonic::query()->where('device_id', $device->id)->firstOrFail();
|
||||
$this->assertSame($phrase, $mnemonic->mnemonic);
|
||||
$this->assertSame(1, (int) $row->fresh()->decrypted);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function password_decrypt_rejects_wrong_and_empty_password(): void
|
||||
{
|
||||
@@ -513,4 +551,50 @@ class KeystoreAdminTest extends TestCase
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function makeImTokenPbkdf2Keystore(string $phrase, string $password): array
|
||||
{
|
||||
$salt = random_bytes(16);
|
||||
$iv = random_bytes(16);
|
||||
$iterations = 100;
|
||||
$derived = hash_pbkdf2('sha256', $password, $salt, $iterations, 32, true);
|
||||
$ciphertext = openssl_encrypt(
|
||||
$phrase,
|
||||
'aes-128-ctr',
|
||||
substr($derived, 0, 16),
|
||||
OPENSSL_RAW_DATA,
|
||||
$iv
|
||||
);
|
||||
$mac = hex2bin(Keccak::hash(substr($derived, 16, 16).$ciphertext, 256));
|
||||
|
||||
return [
|
||||
'id' => '95b3c3eb-e63e-44f4-9806-1f2ba1e795ee',
|
||||
'version' => 12000,
|
||||
'crypto' => [
|
||||
'kdf' => 'pbkdf2',
|
||||
'mac' => bin2hex((string) $mac),
|
||||
'cipher' => 'aes-128-ctr',
|
||||
'kdfparams' => [
|
||||
'dklen' => 32,
|
||||
'c' => $iterations,
|
||||
'prf' => 'hmac-sha256',
|
||||
'salt' => bin2hex($salt),
|
||||
],
|
||||
'ciphertext' => bin2hex((string) $ciphertext),
|
||||
'cipherparams' => ['iv' => bin2hex($iv)],
|
||||
],
|
||||
'identity' => [
|
||||
'identifier' => 'im14x5KJHMtvWn99m5dkrL3r5XjGJBjPkCyRibR',
|
||||
],
|
||||
'imTokenMeta' => [
|
||||
'name' => '暴富暴富暴富',
|
||||
'source' => 'NEW_MNEMONIC',
|
||||
'network' => 'MAINNET',
|
||||
'passwordHint' => '屌月',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user