PHP 中带有 ED25519 的 Blake2b-512 和 NanoSalt 库(Nano Crypto)
Blake2b-512 with ED25519 in PHP with NanoSalt library (Nano Crypto)
我正在尝试在 PHP 中生成 Nano 私钥、public 密钥和地址(这是一种加密货币)。我成功生成了私钥,但无法生成 public 密钥,因此无法生成校验和和整数地址。为此,我必须通过 blake2b-512 算法和 ED25119 曲线加密私钥,然后我必须通过加密 public 密钥通过 blake2b-40 算法获得校验和。那是我的代码:
$privatekey = strtoupper(bin2hex(random_bytes(32)));
$publickey = sodium_crypto_sign_ed25519_pk_to_curve25519($private_key);
$checksum = hash(blake2b-40, $publickey);
我没有得到我需要的东西。为什么?
2021 年 12 月 30 日更新 13:36
我正在尝试使用 NanoSalt 库解决更新问题,但出现此错误:
index.php
<?php
use MikeRow\Salt\NanoSalt;
$nanoSalt = new NanoSalt();
$public_key = $nanoSalt->crypto_sign_public_from_secret_key(hex2bin("781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3"));
print(strtoupper($public_key->toHex()) . PHP_EOL);
?>
这就是错误:
Fatal error: Uncaught Error: Class "MikeRow\Salt\NanoSalt" not found in C:\xampp\htdocs\Peppe\index.php:4 Stack trace: #0 {main} thrown in C:\xampp\htdocs\Peppe\index.php on line 4
PHP 7 >= 7.2.0 和 PHP 8 确实有一个内置的加密库“sodium”,可让您从给定的秘密中导出 ED25519 public 密钥(私钥):https://www.php.net/manual/en/function.sodium-crypto-sign-publickey-from-secretkey.php
下面是此任务的完整运行示例:
<?php
function generateEd25519KeyPair()
{
return sodium_crypto_sign_keypair();
}
function deriveEd25519PublicKey($privateKey)
{
return sodium_crypto_sign_publickey_from_secretkey ($privateKey);
}
function base64Encoding($input)
{
return base64_encode($input);
}
echo 'Generate ED25519 private and public key and derive public key from private key' . PHP_EOL;
$keyPair = generateEd25519KeyPair();
$privateKey = sodium_crypto_sign_secretkey($keyPair);
$publicKey = sodium_crypto_sign_publickey($keyPair);
echo'privateKey (Base64): ' . base64Encoding($privateKey) . PHP_EOL;
echo'publicKey (Base64): ' . base64Encoding($publicKey) . PHP_EOL;
echo PHP_EOL . 'derive the publicKey from the privateKey' . PHP_EOL;
$publicKeyDerived = deriveEd25519PublicKey($privateKey);
echo'publicKey (Base64): ' . base64Encoding($publicKeyDerived) . PHP_EOL;
?>
Nano 不使用标准的 Ed25519,而是使用摘要 Blake2b-512 而不是通常的 SHA-512 的变体,请参阅 standard variant vs Nano variant。 =22=]
因此,通常无法使用标准 Libsodium 库,例如其他答案中提出的 sodium_crypto_sign_publickey_from_secretkey()
函数。除此之外,此函数需要一个 64 字节的密钥(由种子和 public 密钥组成),而在 Nano 中,私钥只有 32 字节(由种子组成)。
Nano 文档中的以下 example 显示了私钥、public 密钥和 public 地址:
"private": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3",
"public": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039",
"account": "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx"
使用 PHP 获取 public 密钥的一种方法是使用支持 Nano 的库。这样的图书馆例如Salt, which also contains the Nano variant。使用此库,public 键的确定很简单:
use MikeRow\Salt\NanoSalt;
$nanoSalt = new NanoSalt();
$public_key = $nanoSalt->crypto_sign_public_from_secret_key(hex2bin("781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3"));
print(strtoupper($public_key->toHex()) . PHP_EOL); // 3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039
使用示例中的私钥生成示例中的 public 密钥。
另一种获取public键的方法是使用支持Ed25519算法的库,这样就可以通过基点相乘得到public键。这样的图书馆例如phpseclib(虽然坦白说我没有测试过这种方式)。
public 地址是通过使用特殊的 Base32 变体对 public 密钥进行编码并附加同样采用 Base32 编码的校验和来获得的。校验和是 public 密钥的 Blake2b-40 散列,参见 here.
支持特殊 Base32 变体和 Blake2b 的库 NanoPHP. Since the Blake2b implementation is a bit cumbersome, this Blake2b 库可以替代使用。一个可能的实现是:
require "Uint.php";
require "Blake2b.php";
// publick key
$public_key = "3068bb1ca04525bb0e416c485fe6a67fd52540227d267cc8b6e8da958a7fa039";
$key = Uint::fromHex('0' . $public_key);
$key_base32 = $key->toString();
print($key_base32 . PHP_EOL);
// checksum
$blake40 = new Blake2b(5);
$hash = $blake40->hash(hex2bin($public_key));
$check = Uint::fromHex(bin2hex($hash))->reverse();
$check_base32 = $check->toString();
print($check_base32 . PHP_EOL);
print('nano_' . $key_base32 . $check_base32 . PHP_EOL); // nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx
其中 Uint.php 提供 Base32 编码并来自 NanoPHP 库,而 Blake2b.php 是更方便的 Blake2b 替代方案。
使用示例中的 public 键给出正确的地址。
要测试其他私钥,this site很有用。
关于安全性:请注意,所有使用的库都相当小,可能包含漏洞。
我正在尝试在 PHP 中生成 Nano 私钥、public 密钥和地址(这是一种加密货币)。我成功生成了私钥,但无法生成 public 密钥,因此无法生成校验和和整数地址。为此,我必须通过 blake2b-512 算法和 ED25119 曲线加密私钥,然后我必须通过加密 public 密钥通过 blake2b-40 算法获得校验和。那是我的代码:
$privatekey = strtoupper(bin2hex(random_bytes(32)));
$publickey = sodium_crypto_sign_ed25519_pk_to_curve25519($private_key);
$checksum = hash(blake2b-40, $publickey);
我没有得到我需要的东西。为什么?
2021 年 12 月 30 日更新 13:36
我正在尝试使用 NanoSalt 库解决更新问题,但出现此错误:
index.php
<?php
use MikeRow\Salt\NanoSalt;
$nanoSalt = new NanoSalt();
$public_key = $nanoSalt->crypto_sign_public_from_secret_key(hex2bin("781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3"));
print(strtoupper($public_key->toHex()) . PHP_EOL);
?>
这就是错误:
Fatal error: Uncaught Error: Class "MikeRow\Salt\NanoSalt" not found in C:\xampp\htdocs\Peppe\index.php:4 Stack trace: #0 {main} thrown in C:\xampp\htdocs\Peppe\index.php on line 4
PHP 7 >= 7.2.0 和 PHP 8 确实有一个内置的加密库“sodium”,可让您从给定的秘密中导出 ED25519 public 密钥(私钥):https://www.php.net/manual/en/function.sodium-crypto-sign-publickey-from-secretkey.php
下面是此任务的完整运行示例:
<?php
function generateEd25519KeyPair()
{
return sodium_crypto_sign_keypair();
}
function deriveEd25519PublicKey($privateKey)
{
return sodium_crypto_sign_publickey_from_secretkey ($privateKey);
}
function base64Encoding($input)
{
return base64_encode($input);
}
echo 'Generate ED25519 private and public key and derive public key from private key' . PHP_EOL;
$keyPair = generateEd25519KeyPair();
$privateKey = sodium_crypto_sign_secretkey($keyPair);
$publicKey = sodium_crypto_sign_publickey($keyPair);
echo'privateKey (Base64): ' . base64Encoding($privateKey) . PHP_EOL;
echo'publicKey (Base64): ' . base64Encoding($publicKey) . PHP_EOL;
echo PHP_EOL . 'derive the publicKey from the privateKey' . PHP_EOL;
$publicKeyDerived = deriveEd25519PublicKey($privateKey);
echo'publicKey (Base64): ' . base64Encoding($publicKeyDerived) . PHP_EOL;
?>
Nano 不使用标准的 Ed25519,而是使用摘要 Blake2b-512 而不是通常的 SHA-512 的变体,请参阅 standard variant vs Nano variant。 =22=]
因此,通常无法使用标准 Libsodium 库,例如其他答案中提出的 sodium_crypto_sign_publickey_from_secretkey()
函数。除此之外,此函数需要一个 64 字节的密钥(由种子和 public 密钥组成),而在 Nano 中,私钥只有 32 字节(由种子组成)。
Nano 文档中的以下 example 显示了私钥、public 密钥和 public 地址:
"private": "781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3",
"public": "3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039",
"account": "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx"
使用 PHP 获取 public 密钥的一种方法是使用支持 Nano 的库。这样的图书馆例如Salt, which also contains the Nano variant。使用此库,public 键的确定很简单:
use MikeRow\Salt\NanoSalt;
$nanoSalt = new NanoSalt();
$public_key = $nanoSalt->crypto_sign_public_from_secret_key(hex2bin("781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3"));
print(strtoupper($public_key->toHex()) . PHP_EOL); // 3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039
使用示例中的私钥生成示例中的 public 密钥。
另一种获取public键的方法是使用支持Ed25519算法的库,这样就可以通过基点相乘得到public键。这样的图书馆例如phpseclib(虽然坦白说我没有测试过这种方式)。
public 地址是通过使用特殊的 Base32 变体对 public 密钥进行编码并附加同样采用 Base32 编码的校验和来获得的。校验和是 public 密钥的 Blake2b-40 散列,参见 here.
支持特殊 Base32 变体和 Blake2b 的库 NanoPHP. Since the Blake2b implementation is a bit cumbersome, this Blake2b 库可以替代使用。一个可能的实现是:
require "Uint.php";
require "Blake2b.php";
// publick key
$public_key = "3068bb1ca04525bb0e416c485fe6a67fd52540227d267cc8b6e8da958a7fa039";
$key = Uint::fromHex('0' . $public_key);
$key_base32 = $key->toString();
print($key_base32 . PHP_EOL);
// checksum
$blake40 = new Blake2b(5);
$hash = $blake40->hash(hex2bin($public_key));
$check = Uint::fromHex(bin2hex($hash))->reverse();
$check_base32 = $check->toString();
print($check_base32 . PHP_EOL);
print('nano_' . $key_base32 . $check_base32 . PHP_EOL); // nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx
其中 Uint.php 提供 Base32 编码并来自 NanoPHP 库,而 Blake2b.php 是更方便的 Blake2b 替代方案。
使用示例中的 public 键给出正确的地址。
要测试其他私钥,this site很有用。
关于安全性:请注意,所有使用的库都相当小,可能包含漏洞。