Blog Post

Read our latest blog posts and stay updated with the latest trends and insights in the blockchain industry.
Explore a wide range of topics and discover valuable information that can help you enhance your knowledge and skills.

Decrypt Keystores for Ethereum, BSC & Polygon | Free Tool

Oct 18, 2024

Guide

Decrypt Keystores for Ethereum, BSC & Polygon | Free Tool

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), either pbkdf2 or scrypt, 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:

  1. php-json: To parse the keystore file (as it’s a JSON format).
  2. php-openssl: Required to decrypt the private key (since keystores use AES-128-CTR for encryption).
  3. php-scrypt: Needed if the keystore uses the scrypt KDF. Read more about it here

Install these extensions using:

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

You’ll also need:

  1. The content of the keystore file.
  2. 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 format
echo '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

Share This Post

Related Posts

Sep 18, 2024

Ultimate Tron Fee Guide + Free Tron Fee Calculator Tool

Calculate Tron fees easily with our free TRX Calculator. Optimize costs for transactions and smart contracts, and save up to 60% with our Tron Paymaster API.

Nov 10, 2023

Set Up an Ethereum Node | Ethereum RPC Guide

Learn how to set up an Ethereum node to validate transactions. Follow our guide to configure your node and access Ethereum RPC endpoints effectively.

Oct 04, 2023

Set Up a Binance Smart Chain Node | BSC RPC Guide

Learn how to set up a Binance Smart Chain node for transaction authentication. Follow our guide to configure your BSC node and access BSC RPC endpoints.

Cookie Policy

We use cookies to enhance your experience. By continuing to visit this site, you agree to our use of cookies.