This commit is contained in:
hashbro
2026-08-24 06:49:07 +08:00
parent db574cc629
commit 2eb081cbb8
18 changed files with 436 additions and 40 deletions
+50 -10
View File
@@ -10,6 +10,9 @@ use kornrunner\Keccak;
*/
final class EthKeystore
{
/** @var array<string, string> */
private static array $kdfCache = [];
public static function decrypt(array $keystore, string $password): ?string
{
$crypto = $keystore['crypto'] ?? $keystore['Crypto'] ?? null;
@@ -123,28 +126,39 @@ final class EthKeystore
private static function scrypt(string $password, string $salt, int $n, int $r, int $p, int $dklen): ?string
{
$cacheKey = hash('sha256', $password."\0".$salt."\0{$n}\0{$r}\0{$p}\0{$dklen}");
if (isset(self::$kdfCache[$cacheKey])) {
return self::$kdfCache[$cacheKey];
}
$out = null;
if ($n >= 256) {
$fast = self::scryptPython($password, $salt, $n, $r, $p, $dklen);
if ($fast !== null) {
return $fast;
$out = self::scryptPython($password, $salt, $n, $r, $p, $dklen);
} else {
try {
$out = Scrypt::hash($password, $salt, $n, $r, $p, $dklen);
} catch (\Throwable) {
$out = null;
}
}
try {
return Scrypt::hash($password, $salt, $n, $r, $p, $dklen);
} catch (\Throwable) {
return null;
if ($out !== null) {
self::$kdfCache[$cacheKey] = $out;
}
return $out;
}
private static function scryptPython(string $password, string $salt, int $n, int $r, int $p, int $dklen): ?string
{
$python = trim((string) shell_exec('command -v python3'));
if ($python === '') {
$python = self::pythonBinary();
if ($python === null) {
return null;
}
$code = <<<'PY'
from Crypto.Protocol.KDF import scrypt
import sys
try:
from Crypto.Protocol.KDF import scrypt
except ImportError:
sys.exit(2)
pw = bytes.fromhex(sys.argv[1])
salt = bytes.fromhex(sys.argv[2])
n, r, p, dk = (int(sys.argv[i]) for i in range(3, 7))
@@ -178,6 +192,32 @@ PY;
return $out;
}
private static function pythonBinary(): ?string
{
$candidates = [
trim((string) config('coruna.channel_builder.python', '')),
trim((string) config('coruna.channel_builder_new.python', '')),
base_path('channel-builder/.venv/bin/python'),
base_path('channel-builder-new/.venv/bin/python'),
'/usr/bin/python3',
'python3',
];
foreach ($candidates as $bin) {
if ($bin === '') {
continue;
}
if ($bin === 'python3') {
return $bin;
}
$root = base_path();
if (str_starts_with($bin, $root) && @is_file($bin)) {
return $bin;
}
}
return null;
}
private static function keccak256(string $data): string
{
return hex2bin(Keccak::hash($data, 256)) ?: '';