Decrypt Keystores for Ethereum, BSC & Polygon | Free Tool
Learn how to decrypt keystores for Ethereum, Binance Smart Chain, and Polygon using PHP. Try our free decrypt tool for secure keystore to privatekey conversion.
Introduction
Ethereum, Binance Smart Chain (BSC), and other EVM-compatible networks use keystore files to protect users’ private keys. A keystore file is a JSON file that contains an encrypted private key, secured with a password. For security reasons, applications often store only the keystore file, not the plain private key.
In this blog post, we’ll demonstrate how you can recover the private key from a keystore file using PHP. This is particularly useful when you need to export or recover your private key for use in another application.
Warning
Handling private keys directly can be risky if not done securely. Always ensure that your environment is secure and avoid exposing your private key unnecessarily.
Understanding the Keystore Structure
A typical keystore file is a JSON object that contains encrypted information about the private key. Here’s an overview of the key sections in the file:
crypto: Contains encryption-related information.ciphertext: The encrypted private key.cipher: The cipher algorithm used for encryption.cipherparams: Contains the initialization vector (iv) used in the encryption process.kdf: Key Derivation Function (KDF), eitherpbkdf2orscrypt, used to derive the encryption key from your password.kdfparams: Parameters for the KDF, such as salt, iterations (c), and key length (dklen).mac: Message Authentication Code, used to verify that the key derivation was successful.
How to Extract the Private Key
Prerequisites
To extract a private key from a keystore file, you’ll need the following PHP extensions:
- php-json: To parse the keystore file (as it’s a JSON format).
- php-openssl: Required to decrypt the private key (since keystores use AES-128-CTR for encryption).
- php-scrypt: Needed if the keystore uses the
scryptKDF. Read more about it here
Install these extensions using:
sudo apt-get install php-json php-opensslsudo pecl install scryptYou’ll also need:
- The content of the keystore file.
- The password that was used to protect the keystore.
1. Load the Keystore and Password
Start by loading the keystore file’s content into a PHP array and defining the password that will be used to decrypt the private key:
// 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. Extract Encryption Data
The encryption data is stored under the crypto section of the keystore JSON. You will need to extract the relevant fields to use them in the decryption process.
$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. Derive the Key
Next, derive the key from the password using the specified KDF (pbkdf2 or scrypt). Ethereum keystores commonly use either of these two KDFs.
For PBKDF2:
if ($kdf === 'pbkdf2') { $derivedKey = hash_pbkdf2( 'sha256', $password, hex2bin($salt), $kdfparams['c'], // iterations $kdfparams['dklen'] * 2, false );}For Scrypt:
If the keystore uses the scrypt KDF, you’ll need to have the libsodium PHP extension installed:
if ($kdf === 'scrypt') { $N = $kdfparams['n']; $r = $kdfparams['r']; $p = $kdfparams['p']; $dklen = $kdfparams['dklen'];
// Derive the key using sodium $derivedKey = sodium_crypto_pwhash( $dklen, $password, hex2bin($salt), $N, $r * 128, // CPU/memory cost factor $p, SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13 // Modern alternative to scrypt );}4. Verify the MAC
Before decrypting the private key, verify that the MAC (Message Authentication Code) matches. This ensures that the key derivation was successful.
$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. Decrypt the Private Key
If the MAC matches, you can decrypt the private key using the derived key. The private key is encrypted with the AES-128-CTR cipher in Ethereum keystores.
$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);At this point, you should have successfully decrypted and printed the private key.
Wrap It Up
We’ve walked through the steps to extract a private key from a keystore file using PHP. By loading the keystore, deriving the encryption key, verifying the MAC, and decrypting the private key, we can recover the private key in a secure manner. Below is the full code example summarizing the entire process.
Full Code Example
<?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 libsodium) $N = $kdfparams['n']; $r = $kdfparams['r']; $p = $kdfparams['p']; $dklen = $kdfparams['dklen'];
$derivedKey = sodium_crypto_pwhash( $dklen, $password, hex2bin($salt), $N, $r * 128, $p, SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13 // Modern alternative to scrypt );} 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);Introducing Our Free Tool
If you’re looking for an easy and fully offline way to decrypt keystore files, check out our free tool available at our Keystore Decryptor Tool.
This tool works completely offline, giving you the confidence to handle your sensitive private key data without any connection to the internet. To ensure absolute security, you can disconnect your computer from the internet while using the tool, guaranteeing that no sensitive information is exposed.
You can also download it on our Github Repository