博客
10 分钟阅读
|
2024年10月18日

如何解密以太坊、BNB 和 Polygon 的密钥库

本文详细介绍如何仅使用 PHP 语言,从以太坊、BNB 智能链或 Polygon 的密钥库(Keystore)JSON 文件中解密并导出私钥,包含分步说明、代码示例以及一款免费的离线解密工具,内容来自 Chaingateway 官方技术博客。

章节
C
Chaingateway Team
区块链专家

简介

以太坊、币安智能链(BSC)以及其他兼容 EVM 的网络使用密钥库(Keystore)文件来保护用户的私钥。密钥库文件是一个 JSON 文件,其中包含一个用密码保护的加密私钥。出于安全考虑,应用程序通常只存储密钥库文件,而不存储明文私钥。

在这篇博客文章中,我们将演示如何使用 PHP 从密钥库文件中恢复私钥。当您需要导出或恢复私钥以在其他应用程序中使用时,这种方法尤其有用。

警告

如果处理不当,直接操作私钥可能存在风险。请始终确保您的环境安全,并避免不必要地暴露您的私钥。

理解密钥库结构

一个典型的密钥库文件是一个 JSON 对象,其中包含关于私钥的加密信息。以下是该文件中关键部分的概览:

  • crypto:包含与加密相关的信息。
    • ciphertext:加密后的私钥。
    • cipher:加密所使用的密码算法。
    • cipherparams:包含加密过程中使用的初始化向量(iv)。
    • kdf:密钥派生函数(KDF),可以是 pbkdf2scrypt,用于从您的密码中派生出加密密钥。
    • kdfparams:KDF 的参数,例如盐值、迭代次数(c)和密钥长度(dklen)。
    • mac:消息认证码,用于验证密钥派生是否成功。

如何提取私钥

前提条件

要从密钥库文件中提取私钥,您需要以下 PHP 扩展:

  1. php-json:用于解析密钥库文件(因为它是 JSON 格式)。
  2. php-openssl:解密私钥所必需(因为密钥库使用 AES-128-CTR 进行加密)。
  3. php-scrypt:如果密钥库使用 scrypt KDF,则需要此扩展。了解更多信息请点击这里

使用以下命令安装这些扩展:

Terminal window
sudo apt-get install php-json php-openssl
sudo pecl install scrypt

您还需要:

  1. 密钥库文件的内容。
  2. 用于保护密钥库的密码。

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(pbkdf2scrypt)从密码中派生密钥。以太坊密钥库通常使用这两种 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 format
echo 'Private key: ' . bin2hex($privateKey);

介绍我们的免费工具

如果您正在寻找一种简单且完全离线的方式来解密密钥库文件,不妨了解一下我们提供的免费工具,访问我们的密钥库解密工具即可获取。

该工具完全离线运行,让您能够放心处理敏感的私钥数据,而无需任何互联网连接。为确保绝对的安全性,您可以在使用该工具时断开计算机与互联网的连接,从而保证不会暴露任何敏感信息。

您也可以在我们的 Github 仓库中下载它

准备好自己动手构建了吗? 获取你的 API key — 7 天试用,无需信用卡 — 或查看 区块链 API 获取完整的 endpoint 参考。

C
Chaingateway Team
区块链专家

Chaingateway 团队致力于为全球开发者简化区块链集成。