如何解密以太坊、BNB 和 Polygon 的密钥库
本文详细介绍如何仅使用 PHP 语言,从以太坊、BNB 智能链或 Polygon 的密钥库(Keystore)JSON 文件中解密并导出私钥,包含分步说明、代码示例以及一款免费的离线解密工具,内容来自 Chaingateway 官方技术博客。
简介
以太坊、币安智能链(BSC)以及其他兼容 EVM 的网络使用密钥库(Keystore)文件来保护用户的私钥。密钥库文件是一个 JSON 文件,其中包含一个用密码保护的加密私钥。出于安全考虑,应用程序通常只存储密钥库文件,而不存储明文私钥。
在这篇博客文章中,我们将演示如何使用 PHP 从密钥库文件中恢复私钥。当您需要导出或恢复私钥以在其他应用程序中使用时,这种方法尤其有用。
警告
如果处理不当,直接操作私钥可能存在风险。请始终确保您的环境安全,并避免不必要地暴露您的私钥。
理解密钥库结构
一个典型的密钥库文件是一个 JSON 对象,其中包含关于私钥的加密信息。以下是该文件中关键部分的概览:
crypto:包含与加密相关的信息。ciphertext:加密后的私钥。cipher:加密所使用的密码算法。cipherparams:包含加密过程中使用的初始化向量(iv)。kdf:密钥派生函数(KDF),可以是pbkdf2或scrypt,用于从您的密码中派生出加密密钥。kdfparams:KDF 的参数,例如盐值、迭代次数(c)和密钥长度(dklen)。mac:消息认证码,用于验证密钥派生是否成功。
如何提取私钥
前提条件
要从密钥库文件中提取私钥,您需要以下 PHP 扩展:
- php-json:用于解析密钥库文件(因为它是 JSON 格式)。
- php-openssl:解密私钥所必需(因为密钥库使用 AES-128-CTR 进行加密)。
- php-scrypt:如果密钥库使用
scryptKDF,则需要此扩展。了解更多信息请点击这里
使用以下命令安装这些扩展:
sudo apt-get install php-json php-opensslsudo pecl install scrypt您还需要:
- 密钥库文件的内容。
- 用于保护密钥库的密码。
1. 加载密钥库和密码
首先,将密钥库文件的内容加载到一个 PHP 数组中,并定义将用于解密私钥的密码:
// Load keystore JSON file$keystore = file_get_contents('/path/to/keystore-file.json');$keystore_json = json_decode($keystore, true);
// Define the password$password = "YOUR_PASSWORD";2. 提取加密数据
加密数据存储在密钥库 JSON 的 crypto 部分。您需要提取相关字段,以便在解密过程中使用。
$crypto = $keystore_json['crypto'];$ciphertext = $crypto['ciphertext'];$iv = $crypto['cipherparams']['iv'];$salt = $crypto['kdfparams']['salt'];$kdf = $crypto['kdf'];$kdfparams = $crypto['kdfparams'];$mac = $crypto['mac'];3. 派生密钥
接下来,使用指定的 KDF(pbkdf2 或 scrypt)从密码中派生密钥。以太坊密钥库通常使用这两种 KDF 中的一种。
对于 PBKDF2:
if ($kdf === 'pbkdf2') { $derivedKey = hash_pbkdf2( 'sha256', $password, hex2bin($salt), $kdfparams['c'], // iterations $kdfparams['dklen'] * 2, false );}对于 Scrypt:
如果密钥库使用 scrypt KDF,您需要上文前提条件中提到的 php-scrypt 扩展(pecl install scrypt)。它使用密钥库文件指定的相同 N/r/p 参数实现 scrypt,并且与上文的 hash_pbkdf2() 一样,默认以十六进制字符串形式返回派生密钥:
if ($kdf === 'scrypt') { $N = $kdfparams['n']; $r = $kdfparams['r']; $p = $kdfparams['p']; $dklen = $kdfparams['dklen'];
// Derive the key using the php-scrypt extension $derivedKey = scrypt($password, hex2bin($salt), $N, $r, $p, $dklen);}4. 验证 MAC
在解密私钥之前,请验证 MAC(消息认证码)是否匹配。这可以确保密钥派生过程成功完成。
$derivedKeyPart = substr($derivedKey, 0, 32);$calculatedMac = hash('sha3-256', hex2bin(substr($derivedKey, 32)) . hex2bin($ciphertext));
if ($calculatedMac !== $mac) { die('MAC verification failed. The password may be incorrect or the keystore may be corrupted.');}5. 解密私钥
如果 MAC 匹配,您就可以使用派生出的密钥来解密私钥了。在以太坊密钥库中,私钥是使用 AES-128-CTR 密码进行加密的。
$privateKey = openssl_decrypt( hex2bin($ciphertext), 'aes-128-ctr', hex2bin($derivedKeyPart), OPENSSL_RAW_DATA, hex2bin($iv));
if (!$privateKey) { die('Failed to decrypt the private key.');}
echo 'Private key: ' . bin2hex($privateKey);至此,您应该已经成功解密并打印出了私钥。
总结
我们已经介绍了使用 PHP 从密钥库文件中提取私钥的各个步骤。通过加载密钥库、派生加密密钥、验证 MAC 以及解密私钥,我们能够安全地恢复私钥。下面是总结了整个过程的完整代码示例。
完整代码示例
<?php// Step 1: Load keystore JSON file$keystore = file_get_contents('/path/to/keystore-file.json');$keystore_json = json_decode($keystore, true);
// Step 2: Define the password$password = "YOUR_PASSWORD";
// Step 3: Extract relevant data from the keystore$crypto = $keystore_json['crypto'];$ciphertext = $crypto['ciphertext'];$iv = $crypto['cipherparams']['iv'];$salt = $crypto['kdfparams']['salt'];$kdf = $crypto['kdf'];$kdfparams = $crypto['kdfparams'];$mac = $crypto['mac'];
// Step 4: Derive the key based on the KDF used (pbkdf2 or scrypt)if ($kdf === 'pbkdf2') { // PBKDF2 key derivation $derivedKey = hash_pbkdf2( 'sha256', $password, hex2bin($salt), $kdfparams['c'], // iterations $kdfparams['dklen'] * 2, false );} elseif ($kdf === 'scrypt') { // Scrypt key derivation (requires the php-scrypt PECL extension) $N = $kdfparams['n']; $r = $kdfparams['r']; $p = $kdfparams['p']; $dklen = $kdfparams['dklen'];
$derivedKey = scrypt($password, hex2bin($salt), $N, $r, $p, $dklen);} else { die('Unsupported KDF method.');}
// Step 5: Verify the MAC$derivedKeyPart = substr($derivedKey, 0, 32);$calculatedMac = hash('sha3-256', hex2bin(substr($derivedKey, 32)) . hex2bin($ciphertext));
if ($calculatedMac !== $mac) { die('MAC verification failed. Wrong password or corrupted keystore.');}
// Step 6: Decrypt the private key$privateKey = openssl_decrypt( hex2bin($ciphertext), 'aes-128-ctr', hex2bin($derivedKeyPart), OPENSSL_RAW_DATA, hex2bin($iv));
if (!$privateKey) { die('Failed to decrypt the private key.');}
// Output the private key in hexadecimal formatecho 'Private key: ' . bin2hex($privateKey);介绍我们的免费工具
如果您正在寻找一种简单且完全离线的方式来解密密钥库文件,不妨了解一下我们提供的免费工具,访问我们的密钥库解密工具即可获取。
该工具完全离线运行,让您能够放心处理敏感的私钥数据,而无需任何互联网连接。为确保绝对的安全性,您可以在使用该工具时断开计算机与互联网的连接,从而保证不会暴露任何敏感信息。
您也可以在我们的 Github 仓库中下载它
准备好自己动手构建了吗? 获取你的 API key — 7 天试用,无需信用卡 — 或查看 区块链 API 获取完整的 endpoint 参考。