New Beta V2.1 Release!

Check out the latest version of the app. If you still want to use the legacy version, log in at app.chaingateway.io. Read more in our latest blog post.

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.

How to Decrypt Keystores for Ethereum, Binance Smart Chain and Polygon + FREE TOOL

Oct 18, 2024

Guide

How to Decrypt Keystores for Ethereum, Binance Smart Chain and 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

Oct 04, 2023

How To Set Up A Binance Smart Chain Node

How to set up a Binance Smart Chain network node to authenticate transactions on the BSC network.

Cookie Policy

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