phpseclib: Convert ECDSA PrivateKey to 64 character hexadecimal

324 Views Asked by At

I'm trying to generate an Ethereum address in PHP and part of the requirements is generating a 64 character hex private key. I'm using phpseclib already in my project, and decided to use it's classes for generating a private key. The recommended is the secp256k1 curve and I used that as well

$privateKey = EC::createKey('secp256k1');

$privateKeyString = $privateKey->toString('PKCS8');

The output I get is something like this(in PEM format)

-----BEGIN PRIVATE KEY-----\r\n
MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgDknmmpdnS+MvAylQDbXl\r\n
WECAG51RuIViJFLw/0aR40yhRANCAARpIut7yqacMbI9TW/aT5frWKpjoDOAL15l\r\n
A/5rE+6+o/AbWES5bHej1U/ygxyqlwVizCABCSeWZf5CNoTy8nMt\r\n
-----END PRIVATE KEY-----

I have tried so many ways to get the required 64 character(256bits) hex code but none has worked. I tried decoding the PEM using base64_decode and then using the bin2hex function, but the output string is almost 310 characters. Removing the header and footer, i got an output of 268 characters.However, if i check the length using $privateKey->getLength(), I get an output of 256. The problem now is, how do I get the 64 character hex string???

Can someone please help me with how to achieve this with the library?

2

There are 2 best solutions below

1
neubert On

The problem now is, how do I get the 64 character hex string???

Does this do what you're wanting?:

$key = json_decode($key->toString('JWK'))->keys[0];
$pub = $key->x . $key->y;

I'm trying to generate an Ethereum address in PHP

Like this?:

$key = \phpseclib3\Crypt\PublicKeyLoader::load("-----BEGIN PRIVATE KEY-----
MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgDknmmpdnS+MvAylQDbXl
WECAG51RuIViJFLw/0aR40yhRANCAARpIut7yqacMbI9TW/aT5frWKpjoDOAL15l
A/5rE+6+o/AbWES5bHej1U/ygxyqlwVizCABCSeWZf5CNoTy8nMt
-----END PRIVATE KEY-----");

$key = json_decode($key->toString('JWK'))->keys[0];
$pub = $key->x . $key->y;

$hash = new \phpseclib3\Crypt\Hash('keccak256');
$hash = $hash->hash($pub);
$address = substr($hash, -20);
$address = '0x' . strtolower(bin2hex($address));

echo $address;
1
CodeWithKyrian On

Alright, I have found a solution. I'll leave it here for anyone who encounter's the same problem, My solution was inspired by @neubert's response.

 $privateKey = EC::createKey('secp256k1');
 $jwk = JWK::load($privateKey->toString('JWK'));

 $publicKeyHex = $jwk['QA'][0]->toHex() . $jwk['QA'][1]->toHex();
 $privateKeyHex = $jwk['dA']->toHex();

 $hashGenerator = new \phpseclib3\Crypt\Hash('keccak256');
 $hash = $hash->hash($pub);

 $walletAddress = self::toChecksum(substr($hash, -40));
 $walletPrivateKey = '0x' . $privateKeyHex;

I hope this helps someone out there.