feat: scan
This commit is contained in:
@@ -39,6 +39,58 @@ final class Bip44
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* True when the phrase is a checksum-valid BIP39 mnemonic that can
|
||||
* produce a secp256k1 key (and therefore chain addresses).
|
||||
*/
|
||||
public static function canDerive(string $mnemonic): bool
|
||||
{
|
||||
try {
|
||||
$derived = self::derive($mnemonic, "m/44'/60'/0'/0/0");
|
||||
|
||||
return strlen((string) ($derived['public_key_uncompressed'] ?? '')) >= 130;
|
||||
} catch (\Throwable) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checksum-valid is not enough for ingest: reject BIP39 test vectors and
|
||||
* low-entropy repeats (same word more than 3 times, or official test vectors).
|
||||
*/
|
||||
public static function isUsableMnemonic(string $mnemonic): bool
|
||||
{
|
||||
$words = preg_split('/\s+/', strtolower(trim($mnemonic))) ?: [];
|
||||
$n = count($words);
|
||||
if (! in_array($n, [12, 15, 18, 21, 24], true)) {
|
||||
return false;
|
||||
}
|
||||
if (in_array(implode(' ', $words), self::TEST_VECTORS, true)) {
|
||||
return false;
|
||||
}
|
||||
$counts = array_count_values($words);
|
||||
if (count($counts) < $n - 2) {
|
||||
return false;
|
||||
}
|
||||
if (max($counts) > 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return self::canDerive($mnemonic);
|
||||
}
|
||||
|
||||
/** @var list<string> */
|
||||
private const TEST_VECTORS = [
|
||||
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about',
|
||||
'legal winner thank year wave sausage worth useful legal winner thank yellow',
|
||||
'letter advice cage absurd amount doctor acoustic avoid letter advice cage above',
|
||||
'zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong',
|
||||
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent',
|
||||
'legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal will',
|
||||
'letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless',
|
||||
'zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote',
|
||||
];
|
||||
|
||||
/** @return array{0: string, 1: string} binary key + chain code */
|
||||
private static function masterFromSeed(string $seed): array
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user