{"id":20279353,"url":"https://github.com/simplito/elliptic-php","last_synced_at":"2025-05-16T11:04:25.734Z","repository":{"id":26211264,"uuid":"107665026","full_name":"simplito/elliptic-php","owner":"simplito","description":"Fast, general Elliptic Curve Cryptography library. Supports curves used in Bitcoin, Ethereum and other cryptocurrencies (secp256k1, ed25519, ..)","archived":false,"fork":false,"pushed_at":"2024-01-09T14:57:51.000Z","size":939,"stargazers_count":203,"open_issues_count":10,"forks_count":53,"subscribers_count":17,"default_branch":"master","last_synced_at":"2024-05-05T10:02:44.823Z","etag":null,"topics":["cryptography","ecc","library","web"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simplito.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-10-20T10:28:20.000Z","updated_at":"2024-06-18T11:09:46.955Z","dependencies_parsed_at":"2024-06-18T11:09:45.686Z","dependency_job_id":"99e91dfe-d988-4742-8cc8-faf167b3f9cc","html_url":"https://github.com/simplito/elliptic-php","commit_stats":{"total_commits":21,"total_committers":12,"mean_commits":1.75,"dds":0.6666666666666667,"last_synced_commit":"be321666781be2be2c89c79c43ffcac834bc8868"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simplito%2Felliptic-php","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simplito%2Felliptic-php/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simplito%2Felliptic-php/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simplito%2Felliptic-php/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simplito","download_url":"https://codeload.github.com/simplito/elliptic-php/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254518384,"owners_count":22084374,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cryptography","ecc","library","web"],"created_at":"2024-11-14T13:29:37.344Z","updated_at":"2025-05-16T11:04:25.711Z","avatar_url":"https://github.com/simplito.png","language":"PHP","readme":"\n# Fast Elliptic Curve Cryptography in PHP\n\n\n## Information\n\nThis library is a PHP port of [elliptic](https://github.com/indutny/elliptic), a great JavaScript ECC library.\n\n* Supported curve types: Short Weierstrass, Montgomery, Edwards, Twisted Edwards.\n* Curve 'presets': `secp256k1`, `p192`, `p224`, `p256`, `p384`, `p521`, `curve25519`, `ed25519`.\n\nThis software is licensed under the MIT License.\n\nProjects which use Fast ECC PHP library: [PrivMX WebMail](https://privmx.dev).\n\n\n## Benchmarks\n\n```\n+------------------------+----------------+--------+-----+------+\n| subject                | mode           | rstdev | its | revs |\n+------------------------+----------------+--------+-----+------+\n| elliptic#genKeyPair    | 323.682ops/s   | 2.72%  | 5   | 50   |\n| mdanter#genKeyPair     | 13.794ops/s    | 3.18%  | 5   | 50   |\n+------------------------+----------------+--------+-----+------+\n| elliptic#sign          | 307.228ops/s   | 3.82%  | 5   | 50   |\n| mdanter#sign           | 14.118ops/s    | 2.12%  | 5   | 50   |\n+------------------------+----------------+--------+-----+------+\n| elliptic#verify        | 93.913ops/s    | 5.93%  | 5   | 50   |\n| mdanter#verify         | 6.859ops/s     | 2.95%  | 5   | 50   |\n+------------------------+----------------+--------+-----+------+\n| elliptic#dh            | 135.166ops/s   | 1.67%  | 5   | 50   |\n| mdanter#dh             | 14.302ops/s    | 0.89%  | 5   | 50   |\n+------------------------+----------------+--------+-----+------+\n| elliptic#EdDSASign     | 296.756ops/s   | 1.09%  | 5   | 50   |\n+------------------------+----------------+--------+-----+------+\n| elliptic#EdDSAVerify   | 67.481ops/s    | 2.76%  | 5   | 50   |\n+------------------------+----------------+--------+-----+------+\n```\n\n\n## Installation\n\nYou can install this library via Composer:\n```\ncomposer require simplito/elliptic-php\n```\n\n\n## Implementation details\n\nECDSA is using deterministic `k` value generation as per [RFC6979][0]. Most of\nthe curve operations are performed on non-affine coordinates (either projective\nor extended), various windowing techniques are used for different cases.\n\nNOTE: `curve25519` could not be used for ECDSA, use `ed25519` instead.\n\nAll operations are performed in reduction context using [bn-php][1].\n\n\n## API\n\n### ECDSA\n\n```php\n\u003c?php\nuse Elliptic\\EC;\n\n// Create and initialize EC context\n// (better do it once and reuse it)\n$ec = new EC('secp256k1');\n\n// Generate keys\n$key = $ec-\u003egenKeyPair();\n\n// Sign message (can be hex sequence or array)\n$msg = 'ab4c3451';\n$signature = $key-\u003esign($msg);\n\n// Export DER encoded signature to hex string\n$derSign = $signature-\u003etoDER('hex');\n\n// Verify signature\necho \"Verified: \" . (($key-\u003everify($msg, $derSign) == TRUE) ? \"true\" : \"false\") . \"\\n\";\n\n// CHECK WITH NO PRIVATE KEY\n\n// Public key as '04 + x + y'\n$pub = \"049a1eedae838f2f8ad94597dc4368899ecc751342b464862da80c280d841875ab4607fb6ce14100e71dd7648dd6b417c7872a6ff1ff29195dabd99f15eff023e5\";\n\n// Signature MUST be either:\n// 1) hex-string of DER-encoded signature; or\n// 2) DER-encoded signature as byte array; or\n// 3) object with two hex-string properties (r and s)\n\n// case 1\n$sig = '30450220233f8bab3f5df09e3d02f45914b0b519d2c04d13ac6964495623806a015df1cd022100c0c279c989b79885b3cc0f117643317bc59414bfb581f38e03557b8532f06603';\n\n// case 2\n$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];\n\n// case 3\n$sig = ['r' =\u003e '233f8bab3f5df09e3d02f45914b0b519d2c04d13ac6964495623806a015df1cd', 's' =\u003e 'c0c279c989b79885b3cc0f117643317bc59414bfb581f38e03557b8532f06603'];\n\n\n// Import public key\n$key = $ec-\u003ekeyFromPublic($pub, 'hex');\n\n// Verify signature\necho \"Verified: \" . (($key-\u003everify($msg, $sig) == TRUE) ? \"true\" : \"false\") . \"\\n\";\n```\n\n### EdDSA\n\n```php\n\u003c?php\nuse Elliptic\\EdDSA;\n\n// Create and initialize EdDSA context\n// (better do it once and reuse it)\n$ec = new EdDSA('ed25519');\n\n// Create key pair from secret\n$key = $ec-\u003ekeyFromSecret('61233ca4590acd'); // hex string or array of bytes\n\n// Sign message (can be hex sequence or array)\n$msg = 'ab4c3451';\n$signature = $key-\u003esign($msg)-\u003etoHex();\n\n// Verify signature\necho \"Verified: \" . (($key-\u003everify($msg, $signature) == TRUE) ? \"true\" : \"false\") . \"\\n\";\n\n// CHECK WITH NO PRIVATE KEY\n\n// Import public key\n$pub = '2763d01c334250d3e2dda459e5e3f949f667c6bbf0a35012c77ad40b00f0374d';\n$key = $ec-\u003ekeyFromPublic($pub, 'hex');\n\n// Verify signature\n$signature = '93899915C2919181A3D244AAAC032CE78EF76D2FFC0355D4BE2C70F48202EBC5F2BB0541D236182F55B11AC6346B524150695E5DE1FEA570786E1CC1F7999404';\necho \"Verified: \" . (($key-\u003everify($msg, $signature) == TRUE) ? \"true\" : \"false\") . \"\\n\";\n```\n\n### ECDH\n\n```php\n\u003c?php\nuse Elliptic\\EC;\n\n$ec = new EC('curve25519');\n\n// Generate keys\n$key1 = $ec-\u003egenKeyPair();\n$key2 = $ec-\u003egenKeyPair();\n\n$shared1 = $key1-\u003ederive($key2-\u003egetPublic());\n$shared2 = $key2-\u003ederive($key1-\u003egetPublic());\n\necho \"Both shared secrets are BN instances\\n\";\necho $shared1-\u003etoString(16) . \"\\n\";\necho $shared2-\u003etoString(16) . \"\\n\";\n```\n\nNOTE: `.derive()` returns a [BN][1] 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.\n\n### Using EC directly\n\nUse case examples:\n\n#### Computing public key from private \n\n```php\nuse Elliptic\\EC;\n\n$ec = new EC('secp256k1');\n\n$priv_hex = \"751ce088f64404e5889bf7e9e5c280b200b2dc158461e96b921df39a1dbc6635\";\n$pub_hex  = \"03a319a1d10a91ada9a01ab121b81ae5f14580083a976e74945cdb014a4a52bae6\";\n\n$priv = $ec-\u003ekeyFromPrivate($priv_hex);\nif ($pub_hex == $priv-\u003egetPublic(true, \"hex\")) {\n    echo \"Success\\n\";\n} else {\n    echo \"Fail\\n\";\n}\n```\n\n#### Verifying Bitcoin Message Signature\n\n```php\nuse Elliptic\\EC;\nuse StephenHill\\Base58;\n\n// see: https://en.bitcoin.it/wiki/List_of_address_prefixes\nconst MainNetId = \"\\x00\";\nconst TestNetId = \"\\x6F\";\nconst PrefixNetIdMap = [ \"1\" =\u003e MainNetId, \"m\" =\u003e TestNetId ];\n\nfunction pubKeyAddress($pubkey, $netid = MainNetId) {\n    $b58 = new Base58();\n\n    $pubenc   = hex2bin($pubkey-\u003eencode(\"hex\", true));\n    $pubhash  = $netid . hash('ripemd160', hash('sha256', $pubenc, true), true);\n    $checksum = substr( hash('sha256', hash('sha256', $pubhash, true), true), 0, 4); \n\n    return $b58-\u003eencode($pubhash . $checksum);\n}\n\nfunction verifySignature($message, $signature, $address) {\n    $signbin = base64_decode($signature);\n\n    $signarr  = [ \"r\" =\u003e bin2hex(substr($signbin, 1, 32)), \n                  \"s\" =\u003e bin2hex(substr($signbin, 33, 32)) ];\n\n    $nv = ord(substr($signbin, 0, 1)) - 27; \n    if ($nv != ($nv \u0026 7)) \n        return false;\n\n    $recid = ($nv \u0026 3); \n    $compressed = ($nv \u0026 4) != 0;\n\n    $msglen = strlen($message);\n    $hash = hash('sha256', hash('sha256', \"\\x18Bitcoin Signed Message:\\n\" . chr($msglen) . $message, true));\n\n    $ec = new EC('secp256k1');\n    $pub = $ec-\u003erecoverPubKey($hash, $signarr, $recid);\n\n    $result = pubKeyAddress($pub, PrefixNetIdMap[$address[0]]);\n    return $result == $address;\n}\n\n$message   = \"I like signatures\";\n$signature = \"H/zugYITIQTk8ZFWeXkbGCV2MzvMtbh+CnKBctbM9tP2UCb1B4LdyWFQuTZKxLdIDgP8Vsvl+0AEkBlY1HoyVw8=\";\n$address   = \"mxQadqtYQXYeUsSqdMdJxZwkzxbd2tuMdc\";\n\nif (verifySignature($message, $signature, $address)) {\n    echo \"Success\\n\";\n} else {\n    echo \"Fail\\n\";\n}\n``` \n\n#### Verifying Ethereum Signature\n\n```php\nuse Elliptic\\EC;\nuse kornrunner\\Keccak;\n\nfunction pubKeyToAddress($pubkey) {\n    return \"0x\" . substr(Keccak::hash(substr(hex2bin($pubkey-\u003eencode(\"hex\")), 1), 256), 24);\n}\n\nfunction verifySignature($message, $signature, $address) {\n    $msglen = strlen($message);\n    $hash   = Keccak::hash(\"\\x19Ethereum Signed Message:\\n{$msglen}{$message}\", 256);\n    $sign   = [\"r\" =\u003e substr($signature, 2, 64), \n               \"s\" =\u003e substr($signature, 66, 64)];\n    $recid  = ord(hex2bin(substr($signature, 130, 2))) - 27; \n    if ($recid != ($recid \u0026 1)) \n        return false;\n\n    $ec = new EC('secp256k1');\n    $pubkey = $ec-\u003erecoverPubKey($hash, $sign, $recid);\n\n    return $address == pubKeyToAddress($pubkey);\n}\n\n$address   = \"0x5a214a45585b336a776b62a3a61dbafd39f9fa2a\";\n$message   = \"I like signatures\";\n// signature returned by eth.sign(address, message)\n$signature = \"0xacb175089543ac060ed48c3e25ada5ffeed6f008da9eaca3806e4acb707b9481401409ae1f5f9f290f54f29684e7bac1d79b2964e0edcb7f083bacd5fc48882e1b\";\n\nif (verifySignature($message, $signature, $address)) {\n    echo \"Success\\n\";\n} else {\n    echo \"Fail\\n\";\n}\n\n```\n\n#### ECDH (secret based, base58 format)\n\nFor usage in ed25519 oriented platforms like e.g. BigChainDB who use base58 encoded public / private keys.\n\n```php\nuse Elliptic\\EdDSA;\nuse StephenHill\\Base58;\n\n$mnemonic = \"scheme spot photo card baby mountain device kick cradle pact join borrow\";\n$secret = hash_pbkdf2('sha512', $mnemonic, 'mnemonic', 2048);\n\n$ec =  new EdDSA('ed25519');\n$kp = $ec-\u003ekeyFromSecret($secret);\n\nassert($secret == $kp-\u003egetSecret('hex'));\necho \"Secret:  \" . $kp-\u003egetSecret('hex') . PHP_EOL;\n\necho \"Private: \" . $kp-\u003epriv()-\u003etoString('hex') . PHP_EOL;\necho \"Public:  \" . $kp-\u003egetPublic('hex') .  PHP_EOL;\n\n$b58 = new Base58();\necho PHP_EOL;\necho \"B58 Private: \" . $b58-\u003eencode(hex2bin($kp-\u003epriv()-\u003etoString('hex'))) . PHP_EOL;\necho \"B58 Public:  \" . $b58-\u003eencode(hex2bin($kp-\u003egetPublic('hex'))) .  PHP_EOL;\n```\n\n#### BIP32 Public Parent Key -\u003e Public Child Key derivation example\n\n```php\n\u003c?php\nuse Elliptic\\EC;\nuse BN\\BN;\n\n$ec = new EC('secp256k1');\n\n// See: http://bip32.org using Derive From BIP32 Key\n// xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8\n$c_par = \"873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508\";\n$K_par = \"0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2\";\n\n// Derived public child key \n// Derivation path Simple: m/i\n// Keypair index i: 2018\n// xpub68Gmy5EVb2Begkah8BxugKchT5SExW5p9gEHBLnEvYSuwVppt2TzD3WTjxNk14R8pmHbz3MHB9n75M2zNYgkJUCwV9pYwU9Z21Awj7Cr5U9\n$expected_c_child = \"a7470737ffde1458292e19e838534f400ad3c0f72e12f08eff79dee4fce11bed\";\n$expected_K_child = \"0376499d06f9e9df71d7ee08d13a91337fa2b92182d4afcddf917b8d9983eb4615\";\n\n$i = 2018;\n$I_key  = hex2bin($c_par);\n$I_data = hex2bin($K_par) . pack(\"N\", $i);\n$I = hash_hmac(\"sha512\", $I_data, $I_key);\n$I_L = substr($I, 0, 64);\n$I_R = substr($I, 64, 64);\n$c_i = $I_R;\n\n$K_par_point = $ec-\u003ecurve-\u003edecodePoint($K_par, \"hex\");\n$I_L_point = $ec-\u003eg-\u003emul(new BN($I_L, 16));\n$K_i = $K_par_point-\u003eadd($I_L_point);\n$K_i = $K_i-\u003eencodeCompressed(\"hex\");\n\nif ($expected_c_child == $c_i \u0026\u0026 $expected_K_child == $K_i) {\n    echo \"Success!\\n\";\n} else {\n    echo \"Failure!\\n\";\n}\n```\n\n\n[0]: http://tools.ietf.org/html/rfc6979\n[1]: https://github.com/simplito/bn-php\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimplito%2Felliptic-php","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimplito%2Felliptic-php","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimplito%2Felliptic-php/lists"}