如何用Keccak256
密钥对包括ETH、secp256k1 (ECDSA)
散列地址签名在内的Tx数据进行签名,并以十六进制编码DER
格式,并在php中进行验证?
我只想使用随附的php库,openssl和其他库,使secp256k1
私钥和公钥,签名,并转换成DER
格式的hex
,以制作我的密码硬币样本。
以太地址由secp256k1 EDSA
键创建,用Keccak256
(sha-3-256)哈希算法对私钥生成的256 bits/64 character
公开密钥进行哈希运算,然后从十六进制哈希字符串中取出最后40个字符,添加校验和,并在哈希字符串中添加x0
前缀。
该示例在github.com/simplito/elliptic-php
repo中显示为elliptic-php/lib/EC/Signature.php
中的toDER()
函数。这个库正在使用BN-php
,但我只想使用php库、openssl
和其他库。
// https://github.com/simplito/elliptic-php ECDSA sample
<?php
use Elliptic\EC;
// Create and initialize EC context
// (better do it once and reuse it)
$ec = new EC('secp256k1');
// Generate keys
$key = $ec->genKeyPair();
// Sign message (can be hex sequence or array)
$msg = 'ab4c3451';
$signature = $key->sign($msg);
// Export DER encoded signature to hex string
$derSign = $signature->toDER('hex');
secp256k1
和 openssl_sign() 函数可以生成新的openssl_sign()私钥和公钥,但不能将公钥转换为E 231
hex
E 135的公钥,通过散列E 236
keccak256
E 140算法进行寻址。e 241
签名Tx散列需要从JSON字符串Tx数据中的/到ETH地址,需要使用{address:{to:address1,from:address2},amount:0,timestamp:timestamp tx, hash:sha256hash, previousHash:hash, difficulty:2...}和openssl_pkey_new() openssl_pkey_export()生成私钥和公钥才能生成ETH地址。
因为,openssl_pkey_new() openssl_pkey_export() for OPENSSL_KEYTYPE_EC返回DER bin键,我需要将它们转换为十六进制。
我尝试过openssl_pkey_new()和openssl_sign()函数,但不能用简单的函数转换成hex格式的DER格式。
openssl_pkey_new()函数来生成新的secp256k1密钥对,只在
生成256位ECDSA私钥问题
中显示。
$config = [
"config" => getenv('OPENSSL_CONF'),
'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, NULL, $config);
// Get The Public Key
$key_detail = openssl_pkey_get_details($res);
$pub_key = $key_detail["key"];
echo "priv_key:<br>".$priv_key;
echo "<br><br>pub_key:<br>".$pub_key;
用钥匙签字。
openssl_sign($hashdata, $signature, $private_key);
是否有任何方法,使用php库,将密钥转换为DER的十六进制?
发布于 2021-09-18 03:57:16
好吧,现在我知道你想要什么了,我已经调查过了,不幸的是,我觉得你运气不好。首先要澄清的是,您希望在DER和密钥格式中签名,这取决于您的软件,但是对于Ethereum帐户地址,您不想要DER中的密钥。具体而言,地址是通过以下方式计算的:
对于步骤1,OpenSSL所使用的密钥,以及php的内置模块,都是PEM格式,正如您在示例中看到的那样,它由一个ASN.1 (DER或有时BER)主体组成,该主体在base64中编码,带有换行和头/尾线。具体来说,公钥是由RFC7468第13节定义的格式,其内容是X.509和PKIX定义的SubjectPublicKeyInfo结构,即特定算法的内容在其他标准中定义的RFC5280 4.1.2.7;这里的例子X9风格的EC是用RFC3279 2.3.5定义的,并由引用X9.62和SEC1的RFC5480 2.2简化。(呜呜!)虽然这些标准允许多个选项,但OpenSSL在PHP中总是使用X9.62--未压缩的点格式和DER编码,因此对于这条曲线,您所需的Ethereum数据只是从PEM解码的最后64个字节:
$der=base64_decode(str_replace(array("-----BEGIN PUBLIC KEY-----\n","-----END PUBLIC KEY-----\n"),"",$pub_key));
$raw=substr($der,-64);
但是第二步是个问题。虽然在SHA3和FIPS202中标准化的握手是Keccak的实例,但是散列使用是Keccak的一个不同的、非标准的实例,OpenSSL没有实现它,因此php本身也不实现(不添加库)。
https://stackoverflow.com/questions/69149095
复制