Giter VIP home page Giter VIP logo

elliptic-php's Introduction

Fast Elliptic Curve Cryptography in PHP

Information

This library is a PHP port of elliptic, a great JavaScript ECC library.

  • Supported curve types: Short Weierstrass, Montgomery, Edwards, Twisted Edwards.
  • Curve 'presets': secp256k1, p192, p224, p256, p384, p521, curve25519, ed25519.

This software is licensed under the MIT License.

Projects which use Fast ECC PHP library: PrivMX WebMail, ...

Benchmarks

+------------------------+----------------+--------+-----+------+
| subject                | mode           | rstdev | its | revs |
+------------------------+----------------+--------+-----+------+
| elliptic#genKeyPair    | 323.682ops/s   | 2.72%  | 5   | 50   |
| mdanter#genKeyPair     | 13.794ops/s    | 3.18%  | 5   | 50   |
+------------------------+----------------+--------+-----+------+
| elliptic#sign          | 307.228ops/s   | 3.82%  | 5   | 50   |
| mdanter#sign           | 14.118ops/s    | 2.12%  | 5   | 50   |
+------------------------+----------------+--------+-----+------+
| elliptic#verify        | 93.913ops/s    | 5.93%  | 5   | 50   |
| mdanter#verify         | 6.859ops/s     | 2.95%  | 5   | 50   |
+------------------------+----------------+--------+-----+------+
| elliptic#dh            | 135.166ops/s   | 1.67%  | 5   | 50   |
| mdanter#dh             | 14.302ops/s    | 0.89%  | 5   | 50   |
+------------------------+----------------+--------+-----+------+
| elliptic#EdDSASign     | 296.756ops/s   | 1.09%  | 5   | 50   |
+------------------------+----------------+--------+-----+------+
| elliptic#EdDSAVerify   | 67.481ops/s    | 2.76%  | 5   | 50   |
+------------------------+----------------+--------+-----+------+

Installation

You can install this library via Composer:

composer require simplito/elliptic-php

Implementation details

ECDSA is using deterministic k value generation as per RFC6979. Most of the curve operations are performed on non-affine coordinates (either projective or extended), various windowing techniques are used for different cases.

NOTE: curve25519 could not be used for ECDSA, use ed25519 instead.

All operations are performed in reduction context using bn-php.

API

ECDSA

<?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');

// Verify signature
echo "Verified: " . (($key->verify($msg, $derSign) == TRUE) ? "true" : "false") . "\n";

// CHECK WITH NO PRIVATE KEY

// Public key as '04 + x + y'
$pub = "049a1eedae838f2f8ad94597dc4368899ecc751342b464862da80c280d841875ab4607fb6ce14100e71dd7648dd6b417c7872a6ff1ff29195dabd99f15eff023e5";

// Signature MUST be either:
// 1) hex-string of DER-encoded signature; or
// 2) DER-encoded signature as byte array; or
// 3) object with two hex-string properties (r and s)

// case 1
$sig = '30450220233f8bab3f5df09e3d02f45914b0b519d2c04d13ac6964495623806a015df1cd022100c0c279c989b79885b3cc0f117643317bc59414bfb581f38e03557b8532f06603';

// case 2
$sig = [48,69,2,32,35,63,139,171,63,93,240,158,61,2,244,89,20,176,181,25,210,192,77,19,172,105,100,73,86,35,128,106,1,93,241,205,2,33,0,192,194,121,201,137,183,152,133,179,204,15,17,118,67,49,123,197,148,20,191,181,129,243,142,3,85,123,133,50,240,102,3];

// case 3
$sig = ['r' => '233f8bab3f5df09e3d02f45914b0b519d2c04d13ac6964495623806a015df1cd', 's' => 'c0c279c989b79885b3cc0f117643317bc59414bfb581f38e03557b8532f06603'];


// Import public key
$key = $ec->keyFromPublic($pub, 'hex');

// Verify signature
echo "Verified: " . (($key->verify($msg, $sig) == TRUE) ? "true" : "false") . "\n";

EdDSA

<?php
use Elliptic\EdDSA;

// Create and initialize EdDSA context
// (better do it once and reuse it)
$ec = new EdDSA('ed25519');

// Create key pair from secret
$key = $ec->keyFromSecret('61233ca4590acd'); // hex string or array of bytes

// Sign message (can be hex sequence or array)
$msg = 'ab4c3451';
$signature = $key->sign($msg)->toHex();

// Verify signature
echo "Verified: " . (($key->verify($msg, $signature) == TRUE) ? "true" : "false") . "\n";

// CHECK WITH NO PRIVATE KEY

// Import public key
$pub = '2763d01c334250d3e2dda459e5e3f949f667c6bbf0a35012c77ad40b00f0374d';
$key = $ec->keyFromPublic($pub, 'hex');

// Verify signature
$signature = '93899915C2919181A3D244AAAC032CE78EF76D2FFC0355D4BE2C70F48202EBC5F2BB0541D236182F55B11AC6346B524150695E5DE1FEA570786E1CC1F7999404';
echo "Verified: " . (($key->verify($msg, $signature) == TRUE) ? "true" : "false") . "\n";

ECDH

<?php
use Elliptic\EC;

$ec = new EC('curve25519');

// Generate keys
$key1 = $ec->genKeyPair();
$key2 = $ec->genKeyPair();

$shared1 = $key1->derive($key2->getPublic());
$shared2 = $key2->derive($key1->getPublic());

echo "Both shared secrets are BN instances\n";
echo $shared1->toString(16) . "\n";
echo $shared2->toString(16) . "\n";

NOTE: .derive() returns a BN instance. The resulting hex string is not zero-padded to constant size. Note that when interoperating with other libraries or using the result in a hash function.

Using EC directly

Use case examples:

Computing public key from private

use Elliptic\EC;

$ec = new EC('secp256k1');

$priv_hex = "751ce088f64404e5889bf7e9e5c280b200b2dc158461e96b921df39a1dbc6635";
$pub_hex  = "03a319a1d10a91ada9a01ab121b81ae5f14580083a976e74945cdb014a4a52bae6";

$priv = $ec->keyFromPrivate($priv_hex);
if ($pub_hex == $priv->getPublic(true, "hex")) {
    echo "Success\n";
} else {
    echo "Fail\n";
}

Verifying Bitcoin Message Signature

use Elliptic\EC;
use StephenHill\Base58;

// see: https://en.bitcoin.it/wiki/List_of_address_prefixes
const MainNetId = "\x00";
const TestNetId = "\x6F";
const PrefixNetIdMap = [ "1" => MainNetId, "m" => TestNetId ];

function pubKeyAddress($pubkey, $netid = MainNetId) {
    $b58 = new Base58();

    $pubenc   = hex2bin($pubkey->encode("hex", true));
    $pubhash  = $netid . hash('ripemd160', hash('sha256', $pubenc, true), true);
    $checksum = substr( hash('sha256', hash('sha256', $pubhash, true), true), 0, 4); 

    return $b58->encode($pubhash . $checksum);
}

function verifySignature($message, $signature, $address) {
    $signbin = base64_decode($signature);

    $signarr  = [ "r" => bin2hex(substr($signbin, 1, 32)), 
                  "s" => bin2hex(substr($signbin, 33, 32)) ];

    $nv = ord(substr($signbin, 0, 1)) - 27; 
    if ($nv != ($nv & 7)) 
        return false;

    $recid = ($nv & 3); 
    $compressed = ($nv & 4) != 0;

    $msglen = strlen($message);
    $hash = hash('sha256', hash('sha256', "\x18Bitcoin Signed Message:\n" . chr($msglen) . $message, true));

    $ec = new EC('secp256k1');
    $pub = $ec->recoverPubKey($hash, $signarr, $recid);

    $result = pubKeyAddress($pub, PrefixNetIdMap[$address[0]]);
    return $result == $address;
}

$message   = "I like signatures";
$signature = "H/zugYITIQTk8ZFWeXkbGCV2MzvMtbh+CnKBctbM9tP2UCb1B4LdyWFQuTZKxLdIDgP8Vsvl+0AEkBlY1HoyVw8=";
$address   = "mxQadqtYQXYeUsSqdMdJxZwkzxbd2tuMdc";

if (verifySignature($message, $signature, $address)) {
    echo "Success\n";
} else {
    echo "Fail\n";
}

Verifying Ethereum Signature

use Elliptic\EC;
use kornrunner\Keccak;

function pubKeyToAddress($pubkey) {
    return "0x" . substr(Keccak::hash(substr(hex2bin($pubkey->encode("hex")), 1), 256), 24);
}

function verifySignature($message, $signature, $address) {
    $msglen = strlen($message);
    $hash   = Keccak::hash("\x19Ethereum Signed Message:\n{$msglen}{$message}", 256);
    $sign   = ["r" => substr($signature, 2, 64), 
               "s" => substr($signature, 66, 64)];
    $recid  = ord(hex2bin(substr($signature, 130, 2))) - 27; 
    if ($recid != ($recid & 1)) 
        return false;

    $ec = new EC('secp256k1');
    $pubkey = $ec->recoverPubKey($hash, $sign, $recid);

    return $address == pubKeyToAddress($pubkey);
}

$address   = "0x5a214a45585b336a776b62a3a61dbafd39f9fa2a";
$message   = "I like signatures";
// signature returned by eth.sign(address, message)
$signature = "0xacb175089543ac060ed48c3e25ada5ffeed6f008da9eaca3806e4acb707b9481401409ae1f5f9f290f54f29684e7bac1d79b2964e0edcb7f083bacd5fc48882e1b";

if (verifySignature($message, $signature, $address)) {
    echo "Success\n";
} else {
    echo "Fail\n";
}

ECDH (secret based, base58 format)

For usage in ed25519 oriented platforms like e.g. BigChainDB who use base58 encoded public / private keys.

use Elliptic\EdDSA;
use StephenHill\Base58;

$mnemonic = "scheme spot photo card baby mountain device kick cradle pact join borrow";
$secret = hash_pbkdf2('sha512', $mnemonic, 'mnemonic', 2048);

$ec =  new EdDSA('ed25519');
$kp = $ec->keyFromSecret($secret);

assert($secret == $kp->getSecret('hex'));
echo "Secret:  " . $kp->getSecret('hex') . PHP_EOL;

echo "Private: " . $kp->priv()->toString('hex') . PHP_EOL;
echo "Public:  " . $kp->getPublic('hex') .  PHP_EOL;

$b58 = new Base58();
echo PHP_EOL;
echo "B58 Private: " . $b58->encode(hex2bin($kp->priv()->toString('hex'))) . PHP_EOL;
echo "B58 Public:  " . $b58->encode(hex2bin($kp->getPublic('hex'))) .  PHP_EOL;

BIP32 Public Parent Key -> Public Child Key derivation example

<?php
use Elliptic\EC;
use BN\BN;

$ec = new EC('secp256k1');

// See: http://bip32.org using Derive From BIP32 Key
// xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8
$c_par = "873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508";
$K_par = "0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2";

// Derived public child key 
// Derivation path Simple: m/i
// Keypair index i: 2018
// xpub68Gmy5EVb2Begkah8BxugKchT5SExW5p9gEHBLnEvYSuwVppt2TzD3WTjxNk14R8pmHbz3MHB9n75M2zNYgkJUCwV9pYwU9Z21Awj7Cr5U9
$expected_c_child = "a7470737ffde1458292e19e838534f400ad3c0f72e12f08eff79dee4fce11bed";
$expected_K_child = "0376499d06f9e9df71d7ee08d13a91337fa2b92182d4afcddf917b8d9983eb4615";

$i = 2018;
$I_key  = hex2bin($c_par);
$I_data = hex2bin($K_par) . pack("N", $i);
$I = hash_hmac("sha512", $I_data, $I_key);
$I_L = substr($I, 0, 64);
$I_R = substr($I, 64, 64);
$c_i = $I_R;

$K_par_point = $ec->curve->decodePoint($K_par, "hex");
$I_L_point = $ec->g->mul(new BN($I_L, 16));
$K_i = $K_par_point->add($I_L_point);
$K_i = $K_i->encodeCompressed("hex");

if ($expected_c_child == $c_i && $expected_K_child == $K_i) {
    echo "Success!\n";
} else {
    echo "Failure!\n";
}

elliptic-php's People

Contributors

clarkphp avatar dubbathony avatar ldudzsim avatar mattmoosh avatar praveenhkp avatar qqux avatar sisou avatar ssmyczynski avatar stefanvangastel avatar vvoody- avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

elliptic-php's Issues

Collisions when generating addresses

Collisions occur because "rand" is used instead of "random_int" in lib/Utils.php

The code section should be replaced with

  public static function randBytes ($ count)
     {
         $ res = "";
         for ($ i = 0; $ i <$ count; $ i ++)
             $ res. = chr (rand (0, 255));
         return $ res;
     }

to the following code or similar

  public static function randBytes ($ count)
     {
         $ res = "";
         for ($ i = 0; $ i <$ count; $ i ++)
             $ res. = chr (random_int(0, 255));
         return $ res;
     }

Always the same sign

i got the same sign for 2 differrent msg

782a3039b478c839e4cb0c941ff4eaeb7df40bdd68bd441afd444b9da763de12909ce62ec5dc1c862a5e0100086775657374313233086c697472626f6f6839707265646c61676179752d697a6d656e69742d616c676f7269746d792d656d69737369692d6762672d692d7679706c61742d6176746f72616d102700

782a3039b478c839e4cb0c941ff4eaeb7df40bdd68bd441afd444b9da763de128b9cf23c3bef13862a5e0100086775657374313233086c697472626f6f6839707265646c61676179752d697a6d656e69742d616c676f7269746d792d656d69737369692d6762672d692d7679706c61742d6176746f72616d102700

Probable problem in signing ethereum transactions by this library

I have problems in sending raw ethereum transactions.

when I want to send most of the times show me 'Invalid sender' error.
but sometimes tx is sent successfully.

I'm using your library for signing transactions.
I think that maybe the problem is from your library.
maybe your library don't sign transaction correctly or maybe I use it incorrectly.

please see my question in:
https://ethereum.stackexchange.com/questions/59881/sending-ethereum-raw-transactions-by-infura-io-gives-me-invalid-sender-error
and if you can help me for finding out the problem.

How encrypt and decrypt

I send text to my friend. How can i encrypt a text from my private key and him public key. And then, how can he decrypt by him private key and my public key ?

is it possible to get a 62 hex characters private key with this library ?

I have been using your library for a long time ( simplito/elliptic-php v1.0)

in order to generate private keys for ethereum.

the size of ethereum private keys is 64 hex characters and the library always gave me private keys with 64 hex characters.

but recently it has given me a private key with 62 hex characters

is it possible?

this is my code:

$ec = new Elliptic\EC('secp256k1');
$key = $ec->genKeyPair();

$eth_privatekey = $key->getPrivate('hex');
$eth_publickey = $key->getPublic('hex');


var_dump($eth_privatekey );
var_dump($eth_publickey );

Modernize: use sensitive parameter for keys

New PHP has #[\SensitiveParameter].
I think it would be great to have it added, for example to ec->keyFromPrivate($key) since handling keys is handling sensitive information.

What this does, is hides key from stack traces and such.

how sign bitcoin raw transactions

hi good man
I was reading this article about how making bitcoin raw transactions.

in the article step3 is result after signing step1 with this privatekey:
0ecd20654c2e2be708495853e8da35c664247040c00bd10b9b13e5e86e6a808d

step1 (raw transaction before signing):

01000000
01
be66e10da854e7aea9338c1f91cd489768d1d6d7189f586d7a3613f2a24d5396
00000000
19 76 a9 14 dd6cce9f255a8cc17bda8ba0373df8e861cb866e 88 ac
ffffffff
01
23ce010000000000
19 76 a9 14 2bc89c2702e0e618db7d59eb5ce2f0f147b40754 88 ac
00000000
01000000

step3 (result after signing double sha256 of step1 raw trx):
3045022100da43201760bda697222002f56266bf65023fef2094519e13077f777baed553b102205ce35d05eabda58cd50a67977a65706347cc25ef43153e309ff210a134722e9e

I signed step1 by your library and got me this result:
30450220587ce0cf0252e2db3a7c3c91b355aa8f3385e128227cd8727c5f7777877ad772022100edc508b7c14891ed15ab38c687019d7ebaf5c12908cf21a83e8ae57e8c47e95c

As you see result of signing message is different from result of signing message in step3.

this is full my code:

use Elliptic\EC;
use StephenHill\Base58;
use BN\BN;


$trx = '0100000001be66e10da854e7aea9338c1f91cd489768d1d6d7189f586d7a3613f2a24d5396000000001976a914dd6cce9f255a8cc17bda8ba0373df8e861cb866e88acffffffff0123ce0100000000001976a9142bc89c2702e0e618db7d59eb5ce2f0f147b4075488ac0000000001000000';

$a = hex2bin($trx);

$privatekey = '0ecd20654c2e2be708495853e8da35c664247040c00bd10b9b13e5e86e6a808d';

$ec = new EC('secp256k1');
$key = $ec->keyFromPrivate($privatekey);
$doubleSha256Trx = hash('sha256', hash('sha256', $a, true));

$mustSign = $doubleSha256Trx;
$signature = $key->sign($mustSign);
$derSign = $signature->toDER('hex');
echo $derSign;

please help me to find out whats my wrong.

thanks

Error in recoverPubKey: Cannot initialize

I am trying to verify the signature, but I got the error: Cannot initialize.
Here is my code:

public static  function verifySignature($hash, $signature, $address) {
    try {
        $sign = [
            "r" => substr($signature, 0, 64),
            "s" => substr($signature, 64, 64),
        ];
        $reCid = ord(hex2bin(substr($signature, 128, 2)));
        if ($reCid != ($reCid & 1)) {
            return false;
        }
        $ec = new EC('secp256k1');
        $publicKey = $ec->recoverPubKey($hash, $sign, $reCid);
         return $address == self::pubKeyToAddress($publicKey);
    }catch (\Exception $exception) {
        throw new HashException($exception->getCode(),$exception->getMessage());
    }
}

verifySignature("c230e229e1e7edd299b4c142ac105a84df7c114ef1d6c538ee9e8461f70b2ad3",""W6AdiMNBTRb/a9oa43CFnL+UjpdhJ4QuxfnVQuTY8EB0RQQ2pvWEeIF9c5oMrokVrCmtBiXe4vW3Fvu+mIZ2bwA=","0x38737be4bb9bdB44Fa4367935E087Dad925CE172");

I traced the error and found it threw out when executed to $ec->recoverPubKey($hash, $sign, $reCid);

Request: Generate keypair for usage in e.g. BigChainDB (doc pub key gen)

Hi there, I'm not a crypto expert so I have a question; Can I use this lib to generate a pub/priv keypair based on a seed or secret (so reproducable) to use with, in my case, BigChainDB? (https://docs.bigchaindb.com/projects/js-driver/en/latest/usage.html#cryptographic-identities-generation)

I can manage to get a private key using the $key->priv() method but the pub() method returns an array I do not know how to use? I''m expecting something like: DGNE3CjqfGoeJYYMzZZVWAw22eqxEZb46xg5zupC63a6

Can this be documented?

bn-php dependency

Hello, I'm not sure if this repository is still maintained, but I want to know, to use this package, if it's necessary to also install your "BN" package with Composer, or if just installing this package is fine.

Edit: I am very new with PHP, sorry if this is a dumb question :)

curve25519 is changing private key

Hi, when I create private key from secret, EC is modifying it

$secret = random_bytes(32);

$ec = new EC('curve25519');

$keyPair = $ec->keyFromPrivate(bin2hex($secret), 16);

$keyPair->getPrivate('hex') !== bin2hex($secret);

and I think this secret should be same

Ethereum Signature failing

I'm trying to use your example "Verifying Ethereum Signature"

In the client, using ethers.js I used this code:

    const Signer = await provider.getSigner();
    const userAddress = await Signer.getAddress();
    const numTokens = await ContractUser.balanceOf(userAddress);
    let currentTime = new Date();
    let month = currentTime.getMonth() + 1;
    let day = currentTime.getDate();
    let year = currentTime.getFullYear();
    let msgToSign = 'Connect: ' + userAddress + ' on ' + year + month + day;
    let messageHash = ethers.utils.solidityKeccak256(['string'],[msgToSign]);
    let signature = await Signer.signMessage(ethers.utils.arrayify(messageHash));

And then to verify it

    let recovered = ethers.utils.verifyMessage(ethers.utils.arrayify(messageHash), signature);

which works, it correctly returns the userAddress.

But then, using your example to verify the signature in php, I get a different address.
I noticed the messageHash is different than the hash calculated in the php. When I removed the $message prefix (string and length) and just hash the message as is, I get the same hash as in javascript. However, in both cases, the address returned is different.

Can you help me?

Calling assert() with a string argument is deprecated in php 7.2

Hello,

Deprecated: assert(): Calling assert() with a string argument is deprecated in E:\Development\WebServer\7.2\xampp\htdocs\webserver.local\projects\blockchain\Elliptic\EdDSA.php on line 16

Deprecated: assert(): Calling assert() with a string argument is deprecated in E:\Development\WebServer\7.2\xampp\htdocs\webserver.local\projects\blockchain\BN\BN.php on line 551

Deprecated: assert(): Calling assert() with a string argument is deprecated in E:\Development\WebServer\7.2\xampp\htdocs\webserver.local\projects\blockchain\BN\BN.php on line 477

Thx

How to get pulickey from a given privatekey?

Hi , based on my current understanding, this elliptic-php can only generates private-public key pairs, and cannot generate public key from a given private key. It that right?

Then how could I get pulickey from a given privatekey?

Many thanks if any information could be provided!

jsonSerialize - php 8.1 patch

Just reporting deprecation when using this with php 8.1

Deprecated: Return type of Elliptic\Curve\ShortCurve\Point::jsonSerialize() should either be compatible with 
JsonSerializable::jsonSerialize(): mixed, or the #[\ReturnTypeWillChange] attribute should be 
used to temporarily suppress the notice in 
[project]/vendor/simplito/elliptic-php/lib/Curve/ShortCurve/Point.php on line 84

Error in _projDbl for ordinary Edwards curves

I'm trying to define and work with an ordinary Edwards curve, but it seems like there's an error in the implementation of the math for ordinary Edwards curves (in comparison, the math for twisted curves doesn't throw any errors).

Undefined property $this->c at
https://github.com/simplito/elliptic-php/blob/master/lib/Curve/EdwardsCurve/Point.php#L143

// H = (c * Z1)^2
$h = $this->curve->_mulC($this->c->redMul($this->z))->redSqr();

This is how the elliptic,js code does it:
https://github.com/indutny/elliptic/blob/475f066aebd14681591f0f0f18a2abc0ded8c390/lib/elliptic/curve/edwards.js#L252

// H = (c * Z1)^2
var h = this.curve._mulC(this.z).redSqr();

I'm not versed at all in the maths for working with Edwards curve, but this looks like a typo in the php version.

PubKey from RAW TX

HI,

Is it possible to recover ethereum PubKey from raw transaction using this lib/scripts, like in
function elliptic.ec.prototype.recoverPubKey (msg, signature, j, enc) ?

Error in verify signature: Cannot initialize

I am trying to verify the signature, but I got the error: Cannot initialize.
Here is my code:

public static function verifySignature($hash, $signature, $address) {
try {
$sign = [
"r" => substr($signature, 0, 64),
"s" => substr($signature, 64, 64),
];
$reCid = ord(hex2bin(substr($signature, 128, 2)));
if ($reCid != ($reCid & 1)) {
return false;
}
$ec = new EC('secp256k1');
$publicKey = $ec->recoverPubKey($hash, $sign, $reCid);
return $address == self::pubKeyToAddress($publicKey);
}catch (\Exception $exception) {
throw new HashException($exception->getCode(),$exception->getMessage());
}
}
verifySignature("c230e229e1e7edd299b4c142ac105a84df7c114ef1d6c538ee9e8461f70b2ad3",""W6AdiMNBTRb/a9oa43CFnL+UjpdhJ4QuxfnVQuTY8EB0RQQ2pvWEeIF9c5oMrokVrCmtBiXe4vW3Fvu+mIZ2bwA=","0x38737be4bb9bdB44Fa4367935E087Dad925CE172");

I traced the error and found it threw out when executed to $ec->recoverPubKey($hash, $sign, $reCid);

Big Issue when recovering a signature of a hashed message

I am trying to verify the signature of a hashed message, and the method used in the description doesn't return the right address :

function verifySignature($message, $signature, $address) {
        $msglen = strlen($message);
        $hash   = Keccak::hash("\x19Ethereum Signed Message:\n{$msglen}{$message}", 256);
        $sign   = ["r" => substr($signature, 2, 64),
            "s" => substr($signature, 66, 64)];
        $recid  = ord(hex2bin(substr($signature, 130, 2))) - 27;
        if ($recid != ($recid & 1))
            return false;

        $ec = new EC('secp256k1');
        $pubkey = $ec->recoverPubKey($hash, $sign, $recid);
        return $address == $this->pubKeyToAddress($pubkey);
    }


$address   = "0xd927a97442c8bce9f18e84de11cac6e54a890ff8";
            $message   = "0xa880c297e04a9a4e1b8856dd4b48c1f6c0b0b82b1da2907b3d16f6ab1357c8b9";
// signature returned by eth.sign(address, message)
            $signature = "0xcd33577b169a3f2a5c835b3ca7dab1d41fa32db4b791c6856319756e7fecc3cb13676706408b019b6dcc3fe28a72f8435390bb0a1572ba241cfd09ae917784511c";

            if ($this->verifySignature($message, $signature, $address)) {
                Log::error("SUCCSS");
            } else {
                Log::error("FAIL");
            }

the address returned by verifySignature (that we try to compare to the original address) is 0xad21644cb255d77dbf4b1ab716cca9797ce3e5bb which is different than the original address.

The problem here is that when not signing the hashed message but the original message it works correctly.

the original message is : "It'sMe MArio". (without the quotes) and the hashing is done by sha3 : web3.utils.sha3(message)

problem in making ethereum wallet address with your library

hi
I'm using your library to generate private key and then public key and then generate ethereum wallet address from it.
this is my code:

use Elliptic\EC;
use kornrunner\Keccak;

$ec = new EC('secp256k1');
$key = $ec->genKeyPair();

$priv = $key->getPrivate('hex');
$pub = substr($key->getPublic('hex'),2);

$hash = Keccak::hash($pub, 256);
$wallet = substr($hash,-40);


var_dump($priv);    // ex:  77a1d1930a78c7ff16a849b519729b67e738ea49c4db19ee8a6f1dea816c7577
var_dump($pub);   // ex:   db93fb7c12b067e2e7794bb49c704159d78a0c4efa5f7e65c5bbb8e343ec602d5ee39169e3a06d4cb0db764445f2772ed5fdb1d3fd18a2f5cdc15b2581b74216
var_dump($hash);  // ex: 5335602cd85aff99e78fdb15cee40b78e358cfb8c4f1a8f1110424401e3febc6
var_dump($wallet);// ex: cee40b78e358cfb8c4f1a8f1110424401e3febc6

but when I use this private key in https://www.myetherwallet.com/ it shows below address as wallet:
B1b71CEc4a07F4EDAc54A620f4Cf4EbC6e7405DD

would you help me to find solution please?

How to use smaller s value in signature and recalculate recoveryParam

    If you talking about [this](https://eklitzke.org/bitcoin-transaction-malleability) and forcing to use smaller s value in signature, we do not have it, because our lib is strict elliptic math, without implementation focused on bitcoin/blockchain or something. But if you need that, you can check this
<?php

require_once("vendor/autoload.php");

use Elliptic\EC;
use Elliptic\EC\Signature;

function getNegativeSignature($ec, $sig) {
    $res = new Signature($sig);
    $res->s = $res->s->neg()->add($ec->n);
    return $res;
}

$ec = new EC('secp256k1');
$key = $ec->genKeyPair();
$msg = 'ab4c3451';
$signature = $key->sign($msg);
$negativeSignature = getNegativeSignature($ec, $signature);

echo "Normal signature:   " . $signature->toDER('hex') . "\n";
echo "Negative signature: " . $negativeSignature->toDER('hex') . "\n";

echo "Verify normal:   " . (($key->verify($msg, $signature) == TRUE) ? "true" : "false") . "\n";
echo "Verify negative: " . (($key->verify($msg, $negativeSignature) == TRUE) ? "true" : "false") . "\n";

if ($signature->s->cmp($negativeSignature->s) < 0) {
    echo "Normal is canonical\n";
}
else {
    echo "Negative is canonical\n";
}

Originally posted by @ldudzsim in #22 (comment)

I use this code to get a smaller s value. But how to recalculate "recoveryParam"?

Bug In Library

I found bug from library. Look at this, how do I found it.
I want sign 2 msg, there are:

  1. 44ab4c3451
  2. 0444ab4c3451 (I put 04 on first string).

and then I compare with the other lib using this lib https://github.com/blockcypher/btcutils/tree/master/signer , the result of signing is different.

Result of msg = 44ab4c3451:
your lib : 3045022100a192e997d87d792304cbe1d8140f72aad11342f92e8bfc881870da43d4df2b2602207d02bf4645e9d89b0549e9c6160a38531bb39e794789ee2b46c7b288e4835d22

golang lib : 3045022100a192e997d87d792304cbe1d8140f72aad11342f92e8bfc881870da43d4df2b2602207d02bf4645e9d89b0549e9c6160a38531bb39e794789ee2b46c7b288e4835d22

Result of msg = 0444ab4c3451:
your lib: 304502202ac6efb8337464a741de1a7ce0ee3bd7bdb2572cc47845964b6f8596fb6aa3aa022100e01dfac253641b2f03030c0c5b66c5f71d329bdc5898e8afd6d3d2f1b500d8fa

Golang lib : 304402202ac6efb8337464a741de1a7ce0ee3bd7bdb2572cc47845964b6f8596fb6aa3aa02201fe2053dac9be4d0fcfcf3f3a4993a079d7c410a56afb78be8fe8b9b1b356847

Maybe your lib cant read zero on first string, could you help me to fix this ?
Sorry my bad english.
Thanks.

about EOS

Thank the author for his selfless dedication. I'm a rookie. I want to know how to use this library to generate EOS private key and EOS signature. Can you give me a simple demo

simplito/elliptic-php[1.0.0, ..., 1.0.9] require ext-gmp * -> it is missing from your system. Install or enable PHP's gmp extension.

Problem 1
- simplito/elliptic-php[1.0.0, ..., 1.0.9] require ext-gmp * -> it is missing from your system. Install or enable PHP's gmp extension.
- Root composer.json requires simplito/elliptic-php ^1.0 -> satisfiable by simplito/elliptic-php[1.0.0, ..., 1.0.9].

To enable extensions, verify that they are enabled in your .ini files:
-
- /usr/local/etc/php/conf.d/docker-php-ext-bcmath.ini
- /usr/local/etc/php/conf.d/docker-php-ext-exif.ini
- /usr/local/etc/php/conf.d/docker-php-ext-gd.ini
- /usr/local/etc/php/conf.d/docker-php-ext-pcntl.ini
- /usr/local/etc/php/conf.d/docker-php-ext-pdo_mysql.ini
- /usr/local/etc/php/conf.d/docker-php-ext-sodium.ini
You can also run php --ini inside terminal to see which files are used by PHP in CLI mode.

PHP Fatal error: Uncaught Error: Class 'Elliptic\EC' not found

It shows me this error when i run this code:

<?php
require 'vendor/autoload.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();

$publicKey = $key->getPublic('hex');
$privateKey = $key->getPrivate('hex');

// Print the keys to the console

echo "The address1 is {$publicKey}. \r\n";
echo "The address1 is {$privateKey}. \r\n";

error:

PHP Fatal error: Uncaught Error: Class 'Elliptic\EC' not found in /home/istabraq/bctest/test2/test2.php:6
Stack trace:
#0 {main}
thrown in /home/istabraq/bctest/test2/test2.php on line 6

any help please?

Lib failed comparison agains trusty native Curve25519

I`ve decided to compare basic calculation of public key based on private key against Curve25519:

$secureRandom = openssl_random_pseudo_bytes ( 32);
// native curve25519.so
$trusty_private = curve25519_private($secureRandom);
$trusty_public = curve25519_public($trusty_private);

// this library
$ec = new EC('curve25519');
$untrusty_keypair = $ec->keyFromPrivate(bin2hex($trusty_private));
$untrusty_public = $untrusty_keypair->getPublic(true, 'hex');

echo $untrusty_public . PHP_EOL;
echo bin2hex($trusty_public) . PHP_EOL;

and this check has failed:

6aa466621807d91ec5a6777544a6796fde5adf8b72a842b23c25f0c479f3aa71
d323bc8387b836dca1cc42fb8f53cb533ff5eaaf2461adc8ef698640bd614a4b

EC recovery without Public key

I'm trying to recover a Message, but I don't understand your params.
Can you document them?

elliptic-php/lib/EC.php

Lines 212 to 214 in be6b14c

public function recoverPubKey($msg, $signature, $j, $enc = false)
{
assert((3 & $j) === $j); //, "The recovery param is more than two bits");

Especially I don't understand what $j is (type and values). In my case I have a recovery param of 27, which wont work.

In your test it seems that you requiring the PubKey in order to recover it.

public function test_should_recover_the_public_key_from_a_signature() {
$ec = new \Elliptic\EC('secp256k1');
$key = $ec->genKeyPair();
$msg = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
$signature = $key->sign($msg);
$recid = $ec->getKeyRecoveryParam($msg, $signature, $key->getPublic());
$r = $ec->recoverPubKey($msg, $signature, $recid);
$this->assertTrue($key->getPublic()->eq($r), 'the keys should match');
}

As you might know in the Ethereum world we don't really have a publicKey, but a derivate of it.

Can you provide a example of PubKey recovery which just requires Message+Signature?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.