使用 PHP 生成以太坊錢包和金鑰對

geeker發表於2018-10-29

本文將提供有關如何生成ECDSA私鑰的指南,然後使用PHP7.0++匯出到以太坊錢包地址。

你可以找到以下工作實現:

composer.json

{
    "require": {
        "sop/asn1": "^3.3",
        "sop/crypto-encoding": "^0.2.0",
        "sop/crypto-types": "^0.2.1",
        "kornrunner/keccak": "^1.0",
        "symfony/dotenv": "^4.0",
        "sc0vu/web3.php": "dev-master"
    }
}

GenerateEthereumWallet.php

<?php
require_once "vendor/autoload.php";
use Sop\CryptoTypes\Asymmetric\EC\ECPublicKey;
use Sop\CryptoTypes\Asymmetric\EC\ECPrivateKey;
use Sop\CryptoEncoding\PEM;
use kornrunner\keccak;
$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;
}
// 生成私鑰
openssl_pkey_export($res, $priv_key);
// 獲取公鑰
$key_detail = openssl_pkey_get_details($res);
$pub_key = $key_detail["key"];
$priv_pem = PEM::fromString($priv_key);
// 轉換為橢圓曲線私鑰格式
$ec_priv_key = ECPrivateKey::fromPEM($priv_pem);
// 然後將其轉換為ASN1結構
$ec_priv_seq = $ec_priv_key->toASN1();
// 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;
// 從公鑰匯出以太坊地址
// 每個EC公鑰始終以0x04開頭,
// 我們需要刪除前導0x04才能正確hash它
$pub_key_hex_2 = substr($pub_key_hex, 2);
$pub_key_len_2 = strlen($pub_key_hex_2) / 2;
// Hash
$hash = Keccak::hash(hex2bin($pub_key_hex_2), 256);
// 以太坊地址長度為20個位元組。 (40個十六進位制字元長)
// 我們只需要最後20個位元組作為以太坊地址
$wallet_address = '0x' . substr($hash, -40);
$wallet_private_key = '0x' . $priv_key_hex;
echo "\r\n   ETH Wallet Address: " . $wallet_address;
echo "\r\n   Private Key: " . $wallet_private_key;

程式碼條件

該程式碼需要PHP 7.0++,OpenSSL擴充套件和PHP Composer。需要使用PHP Composer來安裝第三方軟體包。

$ composer install

生成私鑰

以太坊標準是使用secp256k1曲線生成私鑰。在我的教程中,我使用OpenSSL函式生成PEM格式的橢圓曲線私鑰,如下所示:

$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);

之後我需要將私鑰轉換為ASN1序列,下面是ANS1序列的結構。

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

下面的程式碼是我如何從ANS1序列結構中查詢十六進位制字串中的公鑰和私鑰。

// 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;

衍生以太坊錢包地址

以太坊錢包地址來自公鑰。每個EC公鑰始終以0x04開頭。為了獲得以太坊錢包地址的正確雜湊值,我們需要刪除前導0x04。

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

我們繼續使用EC公鑰的Keccak256雜湊。 以太坊錢包地址長度為20個位元組,長度為40個字元,因此我們只需要雜湊資料的最後20個位元組。

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

現在你有$wallter_address儲存你新生成的以太坊錢包地址,$wallet_private_key是你以太坊錢包地址的私鑰。

如何執行程式碼

$ php GenerateEthereumWallet.php

它將輸出以太坊錢包地址及其私鑰,如下所示:

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

安利2個相關的互動式線上程式設計實戰教程:

php以太坊,主要是介紹使用php進行智慧合約開發互動,進行賬號建立、交易、轉賬、代幣開發以及過濾器和交易等內容。

php比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈儲存、去中心化共識機制、金鑰與指令碼、交易與UTXO等,同時也詳細講解如何在Php程式碼中整合比特幣支援功能,例如建立地址、管理錢包、構造裸交易等,是Php工程師不可多得的比特幣開發學習課程。

這裡是原文

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章