Generate Ethereum Wallet & Key Pairs using PHP — Ethereum Tutorial

This article is to provide a guide on how to generate ECDSA private key, then derive to Ethereum wallet address by using PHP 7.0++.

You can find the working implementation as below:

Prerequisite

The code requires PHP 7.0++ with OpenSSL extension and PHP Composer. You need to use PHP Composer to install the third party packages

$ composer install

Generate Private Key

Ethereum standard is using secp256k1 curve to generate the private key. In my tutorial, I use OpenSSL functions to generate elliptic curve private key in PEM format as like below:

$config = [
'private_key_type' => OPENSSL_KEYTYPE_EC,
'curve_name' => 'secp256k1'
];
$res = openssl_pkey_new($config);
if (!$res) {
    echo 'ERROR: Fail to generate private key. -> ' . openssl_error_string();
    exit;
}
// Generate Private Key
openssl_pkey_export($res, $priv_key);
// PEM Format
$priv_pem = PEM::fromString($priv_key);

After that I need to convert the private key into ASN1 Sequence, below is the structure of ANS1 Sequence.

ECPrivateKey ::= SEQUENCE {
version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
privateKey OCTET STRING,
parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
publicKey [1] BIT STRING OPTIONAL
}

The code below is how I retrieve the public key & private key in hex string from the ANS1 Sequence Structure.

// Then convert it to ASN1 Structure
$ec_priv_seq = $ec_priv_key->toASN1();
// Private Key & Public Key in HEX
$priv_key_hex = bin2hex($ec_priv_seq->at(1)->asOctetString()->string());
$priv_key_len = strlen($priv_key_hex) / 2;
$pub_key_hex = bin2hex($ec_priv_seq->at(3)->asTagged()->asExplicit()->asBitString()->string());
$pub_key_len = strlen($pub_key_hex) / 2;

Derive Ethereum Wallet Address

The Ethereum Wallet address is derived from the public key. Every EC public key is always started with 0x04. In order to get the correct hash for Ethereum Wallet address, we need to remove the leading 0x04.

$pub_key_hex_2 = substr($pub_key_hex, 2);
$pub_key_len_2 = strlen($pub_key_hex_2) / 2;

We continue with Keccak256 hash of the EC public key. Ethereum Wallet address is 20 bytes length which is 40 characters long, so we only need the last 20 bytes from the hash data.

$hash = Keccak::hash(hex2bin($pub_key_hex_2), 256);
$wallet_address = '0x' . substr($hash, -40);
$wallet_private_key = '0x' . $priv_key_hex;

Now you have $wallter_address which store your new generated Ethereum Wallet address and $wallet_private_key is the private key of your Ethereum Wallet address.

How to run the code

$ php GenerateEthereumWallet.php

It will output Ethereum Wallet address and its private key like below:

ETH Wallet Address: 0xb2...
Private Key: 0x73...