├── .distignore
├── .github
└── workflows
│ └── wordpress-new-version.yml
├── .gitignore
├── .wordpress-org
├── banner-1544x500.png
├── banner-772x250.png
├── icon-128x128.png
├── icon-256x256.png
├── icon.svg
├── screenshot-1.png
├── screenshot-2.png
├── screenshot-3.png
├── screenshot-4.png
├── screenshot-5.png
├── screenshot-6.png
└── screenshot-7.png
├── LICENSE
├── README.md
├── css
└── settings.css
├── dev
├── docker-compose.yml
├── i18n-extract.sh
├── rsync-exclude
└── rsync.sh
├── includes
├── address_deriver.php
├── bulk_actions.php
├── crypto_manager.php
├── nimiq_currency.php
├── order_utils.php
├── validation_scheduler.php
└── webhook.php
├── index.php
├── js
├── HubApi.standalone.umd.js
├── checkout.js
└── settings.js
├── languages
├── wc-gateway-nimiq-es_ES.mo
├── wc-gateway-nimiq-es_ES.po
├── wc-gateway-nimiq-fil_PH.mo
├── wc-gateway-nimiq-fil_PH.po
├── wc-gateway-nimiq-fr_FR.mo
├── wc-gateway-nimiq-fr_FR.po
├── wc-gateway-nimiq-nl_NL.mo
├── wc-gateway-nimiq-nl_NL.po
├── wc-gateway-nimiq-pt_PT.mo
├── wc-gateway-nimiq-pt_PT.po
├── wc-gateway-nimiq-ru_RU.mo
├── wc-gateway-nimiq-ru_RU.po
├── wc-gateway-nimiq-uk_UA.mo
├── wc-gateway-nimiq-uk_UA.po
├── wc-gateway-nimiq-zh_CN.mo
├── wc-gateway-nimiq-zh_CN.po
└── wc-gateway-nimiq.pot
├── nimiq-utils
├── JSONUtils.php
└── RpcUtils.php
├── nimiq-xpub
├── README.md
├── composer.json
├── src
│ └── XPub.php
└── vendor
│ ├── autoload.php
│ ├── bitwasp
│ └── bech32
│ │ ├── CONTRIBUTING.md
│ │ ├── README.md
│ │ ├── composer.json
│ │ └── src
│ │ ├── Exception
│ │ └── Bech32Exception.php
│ │ └── bech32.php
│ ├── composer
│ ├── ClassLoader.php
│ ├── LICENSE
│ ├── autoload_classmap.php
│ ├── autoload_files.php
│ ├── autoload_namespaces.php
│ ├── autoload_psr4.php
│ ├── autoload_real.php
│ ├── autoload_static.php
│ └── installed.json
│ ├── kornrunner
│ └── keccak
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── composer.json
│ │ └── src
│ │ └── Keccak.php
│ ├── simplito
│ ├── bigint-wrapper-php
│ │ ├── LICENSE.md
│ │ ├── README.md
│ │ ├── composer.json
│ │ └── lib
│ │ │ └── BigInteger.php
│ ├── bn-php
│ │ ├── LICENSE.md
│ │ ├── README.md
│ │ ├── composer.json
│ │ └── lib
│ │ │ ├── BN.php
│ │ │ └── Red.php
│ └── elliptic-php
│ │ ├── LICENSE.md
│ │ ├── README.md
│ │ ├── composer.json
│ │ └── lib
│ │ ├── Curve
│ │ ├── BaseCurve.php
│ │ ├── BaseCurve
│ │ │ └── Point.php
│ │ ├── EdwardsCurve.php
│ │ ├── EdwardsCurve
│ │ │ └── Point.php
│ │ ├── MontCurve.php
│ │ ├── MontCurve
│ │ │ └── Point.php
│ │ ├── PresetCurve.php
│ │ ├── ShortCurve.php
│ │ └── ShortCurve
│ │ │ ├── JPoint.php
│ │ │ └── Point.php
│ │ ├── Curves.php
│ │ ├── EC.php
│ │ ├── EC
│ │ ├── KeyPair.php
│ │ └── Signature.php
│ │ ├── EdDSA.php
│ │ ├── EdDSA
│ │ ├── KeyPair.php
│ │ └── Signature.php
│ │ ├── HmacDRBG.php
│ │ └── Utils.php
│ ├── stephenhill
│ └── base58
│ │ ├── composer.json
│ │ ├── contributing.md
│ │ ├── license
│ │ ├── readme.md
│ │ └── src
│ │ ├── BCMathService.php
│ │ ├── Base58.php
│ │ ├── GMPService.php
│ │ └── ServiceInterface.php
│ └── symfony
│ └── polyfill-mbstring
│ ├── LICENSE
│ ├── Mbstring.php
│ ├── README.md
│ ├── Resources
│ └── unidata
│ │ ├── lowerCase.php
│ │ ├── titleCaseRegexp.php
│ │ └── upperCase.php
│ ├── bootstrap.php
│ └── composer.json
├── price_services
├── coingecko.php
├── fastspot.php
├── interface.php
└── nimiqx.php
├── readme.txt
├── settings.php
├── styles.css
├── validation_services
├── blockstream.php
├── etherscan.php
├── interface.php
├── json_rpc_nim.php
├── nimiq_watch.php
└── nimiqx.php
└── woo-nimiq-gateway.php
/.distignore:
--------------------------------------------------------------------------------
1 | /.wordpress-org
2 | /.git
3 | /.github
4 | /dev
5 |
6 | .distignore
7 | .gitignore
8 |
--------------------------------------------------------------------------------
/.github/workflows/wordpress-new-version.yml:
--------------------------------------------------------------------------------
1 | name: Deploy to WordPress.org
2 | on:
3 | push:
4 | tags:
5 | - "*"
6 | jobs:
7 | tag:
8 | name: New tag
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@master
12 | # - name: Build
13 | # run: |
14 | # npm install
15 | # npm run build
16 | - name: WordPress Plugin Deploy
17 | uses: 10up/action-wordpress-plugin-deploy@master
18 | env:
19 | SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
20 | SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
21 | SLUG: woo-nimiq-gateway
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | database
2 | html
3 |
--------------------------------------------------------------------------------
/.wordpress-org/banner-1544x500.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/.wordpress-org/banner-1544x500.png
--------------------------------------------------------------------------------
/.wordpress-org/banner-772x250.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/.wordpress-org/banner-772x250.png
--------------------------------------------------------------------------------
/.wordpress-org/icon-128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/.wordpress-org/icon-128x128.png
--------------------------------------------------------------------------------
/.wordpress-org/icon-256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/.wordpress-org/icon-256x256.png
--------------------------------------------------------------------------------
/.wordpress-org/icon.svg:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/.wordpress-org/screenshot-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/.wordpress-org/screenshot-1.png
--------------------------------------------------------------------------------
/.wordpress-org/screenshot-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/.wordpress-org/screenshot-2.png
--------------------------------------------------------------------------------
/.wordpress-org/screenshot-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/.wordpress-org/screenshot-3.png
--------------------------------------------------------------------------------
/.wordpress-org/screenshot-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/.wordpress-org/screenshot-4.png
--------------------------------------------------------------------------------
/.wordpress-org/screenshot-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/.wordpress-org/screenshot-5.png
--------------------------------------------------------------------------------
/.wordpress-org/screenshot-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/.wordpress-org/screenshot-6.png
--------------------------------------------------------------------------------
/.wordpress-org/screenshot-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/.wordpress-org/screenshot-7.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Cryptocurrency Checkout by Nimiq for WooCommerce
4 |
5 | A plugin for Wordpress to handle WooCommerce payments in the Nimiq (NIM), Bitcoin (BTC), and Ethereum (ETH) cryptocurrency.
6 |
7 | **Features Include:**
8 |
9 | * Bitcoin, Ethereum and Nimiq support
10 | * Automatic conversion from supported store currencies like USD or EUR to crypto at latest market prices
11 | * Full order status feedback in your WooCommerce panel
12 | * Decentralized and non-proprietary
13 | * Configurable conversion and validation service providers
14 | * Configurable confirmation times with sensible defaults
15 |
16 | ## Installation
17 |
18 | 1. Be sure you're running WooCommerce 3.5 or higher in your shop.
19 | 2. Search for "nimiq" in your Wordpress plugin section
20 | 3. Activate the plugin through the **Plugins** menu in WordPress.
21 | 4. Go to **WooCommerce > Settings > Payments** and select the "Nimiq" method to configure this plugin.
22 |
23 | [Check this in-depth tutorial for support.](https://nimiq.github.io/tutorials/wordpress-payment-plugin-installation)
24 |
25 | ## Changelog
26 |
27 | Please see the Changelog section in [readme.txt](readme.txt).
28 |
29 | ## Development
30 |
31 | ### Adding A New Validation Service
32 |
33 | Validation services are defined under [`./validation_services/`](./validation_services/). Each service class must implement the `WC_Gateway_Nimiq_Validation_Service_Interface`, defined in [`./validation_services/interface.php`](./validation_services/interface.php). The easiest way to start is to take an existing service (e.g. [`nimiq_watch.php`](./validation_services/nimiq_watch.php)) and rename and adapt it to the new service. The new service then also needs to be registered in the respective `validation_service_` setting. The value of the setting must match the file name (without the `.php` extension) of the service definition. If the new service requires additional setting fields, [`settings.js`](./js/settings.js) also needs to be adapted to show/hide those fields conditionally.
34 |
35 | ## Acknowledgement
36 |
37 | This Nimiq gateway is based on skyverge's [WooCommerce Offline Gateway](https://github.com/bekarice/woocommerce-gateway-offline), which in turn forks the WooCommerce core "Cheque" payment gateway.
38 |
--------------------------------------------------------------------------------
/css/settings.css:
--------------------------------------------------------------------------------
1 | .wc-settings-sub-title.section-nimiq,
2 | .wc-settings-sub-title.section-bitcoin,
3 | .wc-settings-sub-title.section-bitcoin-disabled,
4 | .wc-settings-sub-title.section-ethereum,
5 | .wc-settings-sub-title.section-ethereum-disabled,
6 | .wc-settings-sub-title.section-advanced {
7 | margin-top: 2rem;
8 | padding-top: 1rem;
9 | border-top: solid 1px rgba(35, 40, 45, 0.1);
10 | }
11 |
12 | .wc-settings-sub-title.section-nimiq::after,
13 | .wc-settings-sub-title.section-bitcoin::after,
14 | .wc-settings-sub-title.section-bitcoin-disabled::after,
15 | .wc-settings-sub-title.section-ethereum::after,
16 | .wc-settings-sub-title.section-ethereum-disabled::after {
17 | content: '';
18 | display: inline-block;
19 | width: 20px;
20 | height: 21px;
21 | background-size: contain;
22 | margin-left: 8px;
23 | margin-bottom: -5px;
24 | background-repeat: no-repeat;
25 | }
26 |
27 | .wc-settings-sub-title.section-nimiq::after {
28 | background-image: url('data:image/svg+xml,');
29 | }
30 |
31 | .wc-settings-sub-title.section-bitcoin::after,
32 | .wc-settings-sub-title.section-bitcoin-disabled::after {
33 | background-image: url('data:image/svg+xml,');
34 | }
35 |
36 | .wc-settings-sub-title.section-ethereum::after,
37 | .wc-settings-sub-title.section-ethereum-disabled::after {
38 | width: 14px;
39 | background-image: url('data:image/svg+xml, ');
40 | }
41 |
42 | .wc-settings-sub-title.section-bitcoin-disabled + p + table,
43 | .wc-settings-sub-title.section-ethereum-disabled + p + table {
44 | display: none;
45 | }
46 |
47 | .wc-settings-sub-title.section-advanced {
48 | cursor: pointer;
49 | margin-bottom: 0;
50 | padding-bottom: 1em;
51 | }
52 |
53 | .wc-settings-sub-title.section-advanced::after {
54 | content: '▼';
55 | margin-left: 8px;
56 | font-weight: 900;
57 | opacity: 0.6;
58 | font-size: 0.9em;
59 | }
60 |
61 | .wc-settings-sub-title.section-advanced + p {
62 | margin-top: 0;
63 | }
64 |
65 | .wc-settings-sub-title.section-advanced + p + table {
66 | display: none;
67 | }
68 |
69 | .required + span {
70 | margin-left: 8px;
71 | color: red;
72 | vertical-align: top;
73 | }
74 |
75 | #nimiq_shop_logo_preview {
76 | display: inline-block;
77 | width: 50px;
78 | height: 50px;
79 | margin: -8px 0 -8px 16px;
80 | }
81 |
--------------------------------------------------------------------------------
/dev/docker-compose.yml:
--------------------------------------------------------------------------------
1 | wordpress:
2 | image: wordpress
3 | links:
4 | - mariadb:mysql
5 | environment:
6 | - WORDPRESS_DB_PASSWORD=not-my-password
7 | - WORDPRESS_DB_USER=root
8 | ports:
9 | - "8083:80"
10 | volumes:
11 | - ./html:/var/www/html
12 |
13 | mariadb:
14 | image: mariadb
15 | environment:
16 | - MYSQL_ROOT_PASSWORD=not-my-password
17 | - MYSQL_DATABASE=wordpress
18 | volumes:
19 | - ./database:/var/lib/mysql
20 |
--------------------------------------------------------------------------------
/dev/i18n-extract.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/sh
2 |
3 | wp i18n make-pot . --exclude=database,html --slug=wc-gateway-nimiq
4 |
--------------------------------------------------------------------------------
/dev/rsync-exclude:
--------------------------------------------------------------------------------
1 | .*
2 | !.wordpress-org
3 | database
4 | html
5 | dev
6 |
--------------------------------------------------------------------------------
/dev/rsync.sh:
--------------------------------------------------------------------------------
1 | sudo rsync -av --exclude-from=dev/rsync-exclude --chown=33:tape . html/wp-content/plugins/woo-nimiq-checkout
2 |
--------------------------------------------------------------------------------
/includes/address_deriver.php:
--------------------------------------------------------------------------------
1 | gateway = $gateway;
10 | }
11 |
12 | public function get_next_address( $currency ) {
13 | if ( $currency === 'nim' ) return null; // TODO: Throw here instead?
14 |
15 | $reuse_eth_addresses = $this->gateway->get_option( 'reuse_eth_addresses', 'no' );
16 |
17 | // Derive a new address for BTC and, if the re-use setting is disabled, for ETH
18 | if ( $currency === 'btc' || ( $currency === 'eth' && $reuse_eth_addresses == 'no' ) ) {
19 | return $this->derive_new_address( $currency );
20 | }
21 |
22 | // Search for a re-usable address
23 |
24 | // 1. Find all orders that
25 | // - have an 'order_eth_address' (an ETH address was already assigned)
26 | // - have no 'transaction_hash' (no transaction was matched yet)
27 | // - are still 'pending' (order is still waiting for a matching transaction, e.g. was not cancelled)
28 | $posts = get_posts( [
29 | 'post_type' => 'shop_order',
30 | 'post_status' => [ 'wc-pending' ],
31 | 'meta_query' => [
32 | 'relation' => 'AND',
33 | [
34 | 'key' => 'order_eth_address',
35 | 'compare' => 'EXISTS',
36 | ],
37 | [
38 | 'key' => 'transaction_hash',
39 | 'compare' => 'NOT EXISTS',
40 | 'value' => 'bug #23268', // For Wordpress < 3.9, just in case
41 | ],
42 | ],
43 | ] );
44 |
45 | if ( empty( $posts ) ) {
46 | // Use the first address
47 | return $this->derive_new_address( $currency, 0 );
48 | };
49 |
50 | // 2. Find the first derived address that is not used in any of the above orders
51 | $index = 0;
52 | $numderive = 5;
53 | while (true) {
54 | $indices = range($index, $index + $numderive - 1, 1); // Track indices of the derived addresses
55 | $addresses = $this->derive_addresses( $currency, $index, $numderive );
56 |
57 | // Remove all currently used addresses from the derived $addresses
58 | foreach ( $posts as $post ) {
59 | $order = new WC_Order( (int) $post->ID );
60 | $i = array_search( $order->get_meta( 'order_eth_address' ), $addresses );
61 | if ( $i !== false ) {
62 | array_splice( $indices, $i, 1 );
63 | array_splice( $addresses, $i, 1 );
64 | }
65 | }
66 |
67 | // If unused addresses are found, return the first
68 | if ( count( $addresses ) > 0 ) {
69 | $this->maybe_update_address_index( $currency, $indices[ 0 ] );
70 | return $addresses[ 0 ];
71 | }
72 |
73 | // If no address of this batch is unused, increase the start index and rerun the loop
74 | $index += $numderive;
75 | }
76 | }
77 |
78 | private function maybe_update_address_index( $currency, $index, $current_index = null ) {
79 | $current_index = is_int( $current_index )
80 | ? $current_index
81 | : $this->gateway->get_option( 'current_address_index_' . $currency, -1 );
82 |
83 | if ( $index > $current_index ) {
84 | $this->gateway->update_option( 'current_address_index_' . $currency, $index );
85 | }
86 | }
87 |
88 | public function derive_new_address( $currency, $index = null ) {
89 | $current_index = null;
90 |
91 | if ( !is_int( $index ) ) {
92 | $current_index = $this->gateway->get_option( 'current_address_index_' . $currency, -1 );
93 | $index = $current_index + 1;
94 | }
95 |
96 | $address = $this->derive_addresses( $currency, $index, 1 )[ 0 ];
97 |
98 | if ( !empty( $address ) ) {
99 | $this->maybe_update_address_index( $currency, $index, $current_index );
100 | }
101 |
102 | return $address;
103 | }
104 |
105 | public function derive_addresses( $currency, $startindex, $numderive ) {
106 | $qualified_currency_name = Crypto_Manager::iso_to_name( $currency );
107 |
108 | $xpub = $this->gateway->get_option( $qualified_currency_name . '_xpub' );
109 |
110 | $xpub_type = $currency === 'btc' ? $this->gateway->get_option( $qualified_currency_name . '_xpub_type' ) : '';
111 | $xpub_type = [
112 | 'bip-44' => XPub::BIP44,
113 | 'bip-84' => XPub::BIP84,
114 | '' => '',
115 | ][ $xpub_type ];
116 |
117 | if ( empty( $xpub ) ) {
118 | return null;
119 | }
120 |
121 | // Path 'm/0' from account xpub to external address space (BIP-44 for both BTC and ETH)
122 | $xpub_0 = XPub::fromString( $xpub, $xpub_type )->derive( 0 );
123 |
124 | $addresses = [];
125 |
126 | for ($i = $startindex; $i < $startindex + $numderive; $i++) {
127 | $addresses[] = $xpub_0->derive( $i )->toAddress( $currency );
128 | }
129 |
130 | return $addresses;
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/includes/crypto_manager.php:
--------------------------------------------------------------------------------
1 | 5,
6 | 'btc' => 8,
7 | 'eth' => 18,
8 | ];
9 |
10 | public static function iso_to_name( $iso ) {
11 | return [
12 | 'nim' => 'nimiq',
13 | 'btc' => 'bitcoin',
14 | 'eth' => 'ethereum',
15 | ][ $iso ];
16 | }
17 |
18 | public static function name_to_iso( $name ) {
19 | return [
20 | 'nimiq' => 'nim',
21 | 'bitcoin' => 'btc',
22 | 'ethereum' => 'eth',
23 | ][ $name ];
24 | }
25 |
26 | public static function coins_to_units( $values ) {
27 | $units = [];
28 | foreach ( $values as $crypto => $value ) {
29 | // Convert to smallest unit string
30 |
31 | // 1. Format as string without exponent
32 | $pad_length = self::DECIMALS[ $crypto ];
33 | $coins = is_string( $value ) ? $value : number_format($value, $pad_length, '.', '');
34 |
35 | // 2. Split by decimal dot
36 | $split = explode( '.', $coins, 2 );
37 | $integers = $split[0];
38 | $decimals = count( $split ) > 1 ? $split[1] : '';
39 |
40 | // 3.1. Extend decimals with 0s until number of crypto-specific decimals is reached
41 | $decimals = str_pad( $decimals, $pad_length, '0', STR_PAD_RIGHT );
42 | // 3.2. Ensure decimals are not too long
43 | $decimals = substr( $decimals, 0, $pad_length );
44 |
45 | // 4. Join integers with decimals to create value string
46 | $unit = implode( '', [ $integers, $decimals ] );
47 |
48 | // 5. Remove leading zeros
49 | $units[ $crypto ] = ltrim($unit, '0') ?: '0';
50 | }
51 | return $units;
52 | }
53 |
54 | public static function required_decimals( $crypto, $price = 1000000 ) {
55 | // Find number of required significant decimals based on price, can be negative
56 | return min( ceil( log10( $price ) ) + 2, self::DECIMALS[ $crypto ] );
57 | }
58 |
59 | public static function calculate_quotes( $value, $prices ) {
60 | $quotes = [];
61 | foreach ( $prices as $crypto => $price ) {
62 | $quotes[ $crypto ] = $value / $price;
63 | }
64 | return self::format_quotes( $value, $quotes, $prices );
65 | }
66 |
67 | public static function format_quotes( $value, $quotes, $prices = null ) {
68 | foreach ( $quotes as $crypto => $quote ) {
69 | $price = !empty( $prices ) ? $prices[ $crypto ] : $value / $quote;
70 | $decimals = self::required_decimals( $crypto, $price );
71 | $quotes[ $crypto ] = number_format( $quote, $decimals, '.', '' );
72 | }
73 | return $quotes;
74 | }
75 |
76 | /**
77 | * Returns 1 if $a > $b, -1 if $b > $a, 0 if equal
78 | */
79 | public static function unit_compare( $a, $b ) {
80 | $a = ltrim($a, '0');
81 | $b = ltrim($b, '0');
82 |
83 | $a_length = strlen( $a );
84 | $b_length = strlen( $b );
85 |
86 | if ( $a_length > $b_length ) return 1;
87 | if ( $a_length < $b_length ) return -1;
88 |
89 | return strcmp( $a, $b );
90 | }
91 |
92 | public function __construct( $gateway ) {
93 | $this->gateway = $gateway;
94 | }
95 |
96 | public function get_accepted_cryptos() {
97 | $accepted_cryptos = [ 'nim' ];
98 | if ( !empty( $this->gateway->get_option( 'bitcoin_xpub' ) ) ) $accepted_cryptos[] = 'btc';
99 | if ( !empty( $this->gateway->get_option( 'ethereum_xpub' ) ) ) $accepted_cryptos[] = 'eth';
100 | return $accepted_cryptos;
101 | }
102 |
103 | public function get_fees_per_byte() {
104 | return [
105 | 'nim' => $this->gateway->get_setting( 'fee_nim' ),
106 | 'btc' => $this->gateway->get_setting( 'fee_btc' ),
107 | 'eth' => strval( $this->gateway->get_setting( 'fee_eth' ) * 1e9 ), // Option is in Gwei
108 | ];
109 | }
110 |
111 | public function get_fees( $message_length ) {
112 | $perFees = $this->get_fees_per_byte();
113 | return [
114 | 'nim' => ( 166 + $message_length ) * $perFees[ 'nim' ],
115 | 'btc' => 250 * $perFees[ 'btc' ],
116 | 'eth' => [
117 | 'gas_limit' => 21000,
118 | 'gas_price' => $perFees[ 'eth' ],
119 | ],
120 | ];
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/includes/nimiq_currency.php:
--------------------------------------------------------------------------------
1 | get_meta( 'order_crypto_currency' ) ?: ( $fallback_to_nim ? 'nim' : null );
6 | }
7 |
8 | public static function get_order_total_crypto( $order ) {
9 | // 1. Get order crypto currency
10 | $currency = self::get_order_currency( $order );
11 |
12 | // 2. Get order crypto total
13 | $order_total = $order->get_meta( 'order_total_' . $currency );
14 |
15 | return Crypto_Manager::coins_to_units( [ $currency => $order_total ] )[ $currency ];
16 | }
17 |
18 | public static function get_order_sender_address( $order ) {
19 | $currency = self::get_order_currency( $order );
20 | return $order->get_meta( 'customer_' . $currency . '_address' );
21 | }
22 |
23 | public static function get_order_recipient_address( $order, $gateway ) {
24 | $currency = self::get_order_currency( $order );
25 | switch( $currency ) {
26 | case 'nim': return $gateway->get_option( 'nimiq_address' );
27 | case 'btc': return $order->get_meta( 'order_' . $currency . '_address' );
28 | case 'eth': return strtolower( $order->get_meta( 'order_' . $currency . '_address' ) );
29 | }
30 | }
31 |
32 | public static function get_order_recipient_addresses( $order, $gateway ) {
33 | return [
34 | 'nim' => $gateway->get_option( 'nimiq_address' ),
35 | 'btc' => $order->get_meta( 'order_btc_address' ),
36 | 'eth' => strtolower( $order->get_meta( 'order_eth_address' ) ),
37 | ];
38 | }
39 |
40 | /**
41 | * @param {WC_Order} $order
42 | * @return {number|boolean} A timestamp or false if the order does not expire
43 | */
44 | public static function get_order_hold_expiry( $order ) {
45 | // TODO: Respect $gateway->get_setting( 'tx_wait_duration' ) here?
46 |
47 | $order_hold_minutes = get_option( 'woocommerce_hold_stock_minutes' );
48 | if ( empty( $order_hold_minutes ) ) return false;
49 |
50 | $order_date = $order->get_data()[ 'date_created' ]->getTimestamp();
51 | return $order_date + $order_hold_minutes * 60;
52 | }
53 |
54 | public static function get_payment_state( $comparison ) {
55 | return $comparison > 0 ? 'OVERPAID' : ( $comparison < 0 ? 'UNDERPAID' : 'PAID' );
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/includes/validation_scheduler.php:
--------------------------------------------------------------------------------
1 | get_setting( 'validation_interval' ) ) ?: 30;
18 | $interval = $interval_minutes * 60; // Convert to seconds
19 |
20 | as_schedule_recurring_action( $next_quarter_hour, $interval, 'wc_nimiq_scheduled_validation' );
21 | }
22 | }
23 |
24 | function wc_nimiq_end_validation_schedule() {
25 | as_unschedule_action( 'wc_nimiq_scheduled_validation' );
26 | }
27 |
28 | function wc_nimiq_validate_orders() {
29 | $logger = wc_get_logger();
30 | $log_context = array( 'source' => 'wc-gateway-nimiq' );
31 |
32 | // Get all orders that are on-hold or pending, and have a crypto currency set
33 | $posts = get_posts( [
34 | 'post_type' => 'shop_order',
35 | 'post_status' => [ 'wc-on-hold', 'wc-pending' ],
36 | 'meta_key' => 'order_crypto_currency',
37 | 'meta_compare' => '!=',
38 | 'meta_value' => '',
39 | ] );
40 |
41 | /* translators: %d: Number of orders to process */
42 | $logger->info( sprintf( _n( 'Processing %d order', 'Processing %d orders', count( $posts ), 'wc-gateway-nimiq' ), count( $posts ) ), $log_context );
43 |
44 | if ( empty( $posts ) ) return;
45 |
46 | $ids = array_reduce( $posts, function( $acc, $post ) {
47 | $acc[] = $post->ID;
48 | return $acc;
49 | }, [] );
50 |
51 | // $logger->info( 'Processing IDs [' . implode( ', ', $ids ) . ']', $log_context );
52 |
53 | $gateway = new WC_Gateway_Nimiq();
54 | $validation_results = _do_bulk_validate_transactions( $gateway, $ids );
55 |
56 | if ( ! empty( $validation_results[ 'errors' ] ) ) {
57 | foreach ( $validation_results[ 'errors' ] as $error ) {
58 | $logger->error( $error, $log_context );
59 | }
60 | // TODO: Send error email to admin?
61 | }
62 |
63 | $count_orders_updated = intval( $validation_results[ 'changed' ] ?: 0 );
64 | $logger->info( sprintf( _n( 'Updated %d order', 'Updated %d orders', $count_orders_updated, 'wc-gateway-nimiq' ), $count_orders_updated ) . '.', $log_context );
65 | }
66 |
--------------------------------------------------------------------------------
/includes/webhook.php:
--------------------------------------------------------------------------------
1 | $message,
18 | 'status' => $status,
19 | ], $status );
20 | }
21 |
22 | function woo_nimiq_checkout_get_param( $key, $method = 'get' ) {
23 | $data = $method === 'get' ? $_GET : $_POST;
24 |
25 | if ( !isset( $data[ $key ] ) ) return null;
26 | return sanitize_text_field( $data[ $key ] );
27 | }
28 |
29 | /**
30 | * @param array $request Options for the function.
31 | */
32 | function woo_nimiq_checkout_callback() {
33 | $request = [
34 | 'id' => woo_nimiq_checkout_get_param( 'id' ),
35 | 'csrf' => woo_nimiq_checkout_get_param( 'csrf', 'post' ),
36 | 'command' => woo_nimiq_checkout_get_param( 'command', 'post' ),
37 | 'currency' => woo_nimiq_checkout_get_param( 'currency', 'post' ),
38 | ];
39 |
40 | $gateway = new WC_Gateway_Nimiq();
41 |
42 | // Set headers
43 | $cors_origin = $gateway->get_option( 'network' ) === 'main' ? 'https://hub.nimiq.com' : $_SERVER['HTTP_ORIGIN'];
44 | header( 'Access-Control-Allow-Origin: ' . $cors_origin );
45 | header( 'Access-Control-Allow-Credentials: true');
46 |
47 | $order = wc_get_order( $request[ 'id' ] );
48 |
49 | // Validate that the order exists
50 | if ( !$order ) {
51 | return woo_nimiq_checkout_error( 'Invalid order ID', 404 );
52 | }
53 |
54 | // Validate that the order's payment method is this plugin and that the order is currently 'pending'
55 | if ( $order->get_payment_method() !== $gateway->id || $order->get_status() !== 'pending' ) {
56 | return woo_nimiq_checkout_error( 'Bad order', 406 );
57 | }
58 |
59 | // Validate CSRF token
60 | $order_csrf_token = $order->get_meta( 'checkout_csrf_token' );
61 | if ( empty( $request[ 'csrf' ] ) || $order_csrf_token !== $request[ 'csrf' ] ) {
62 | return woo_nimiq_checkout_error( 'Invalid CSRF token', 403 );
63 | }
64 |
65 | try {
66 | // Call handler depending on command
67 | switch ( strtolower( $request[ 'command' ] ) ) {
68 | case 'set_currency':
69 | return woo_nimiq_checkout_callback_set_currency( $request, $order, $gateway );
70 | case 'get_state':
71 | return woo_nimiq_checkout_callback_get_state( $request, $order, $gateway );
72 | default:
73 | return woo_nimiq_checkout_callback_unknown( $request, $order, $gateway );
74 | }
75 | } catch (Exception $error) {
76 | return woo_nimiq_checkout_error( $error->getMessage(), 500 );
77 | }
78 | }
79 |
80 | function woo_nimiq_checkout_array_find($function, $array) {
81 | foreach ($array as $item) {
82 | if (call_user_func($function, $item) === true) return $item;
83 | }
84 | return null;
85 | }
86 |
87 | function woo_nimiq_checkout_callback_set_currency( $request, $order, $gateway ) {
88 | $currency = strtolower( $request[ 'currency' ] );
89 |
90 | $cryptoman = new Crypto_Manager( $gateway );
91 | $accepted_currencies = $cryptoman->get_accepted_cryptos();
92 |
93 | // Validate that the submitted currency is valid
94 | if ( !in_array( $currency, $accepted_currencies, true ) ) {
95 | return woo_nimiq_checkout_error( 'Bad currency', 406 );
96 | }
97 |
98 | $order->update_meta_data( 'order_crypto_currency', $currency );
99 |
100 | // Get payment option for the selected currency from stored request
101 | $stored_request = $order->get_meta( 'nc_payment_request' ) ?: null;
102 | if ( !$stored_request ) return woo_nimiq_checkout_error( 'Original request not found in order', 500 );
103 |
104 | $request = json_decode( $stored_request, true );
105 |
106 | $payment_option = woo_nimiq_checkout_array_find( function( $option ) use ( $currency ) {
107 | return $option[ 'currency' ] === $currency;
108 | }, $request[ 'paymentOptions' ] );
109 | if ( !$payment_option ) return woo_nimiq_checkout_error( 'Selected currency not found in original request', 500 );
110 |
111 | // Get the order address, or derive a new one
112 | $address = Order_Utils::get_order_recipient_address( $order, $gateway );
113 | if ( empty( $address ) && ( $currency === 'btc' || $currency === 'eth' ) ) {
114 | include_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'address_deriver.php' );
115 | $deriver = new Address_Deriver( $gateway );
116 | $address = $deriver->get_next_address( $currency );
117 | if ( !empty( $address ) ) {
118 | $order->update_meta_data( 'order_' . $currency . '_address', $address );
119 | }
120 | }
121 |
122 | $order->save();
123 |
124 | $payment_option[ 'protocolSpecific' ][ 'recipient' ] = $address;
125 |
126 | return woo_nimiq_checkout_reply( $payment_option );
127 |
128 | // // Rebuild the payment option for the selected currency from stored data
129 | // $protocolSpecific = [
130 | // 'recipient' => $address,
131 | // ];
132 |
133 | // $tx_message = ( !empty( $gateway->get_option( 'message' ) ) ? $gateway->get_option( 'message' ) . ' ' : '' )
134 | // . '(' . $gateway->get_short_order_key( $order->get_order_key() ) . ')';
135 | // $tx_message_bytes = unpack('C*', $tx_message); // Convert to byte array
136 |
137 | // // Get fees from order meta
138 | // $fee = $order->get_meta( 'crypto_fee_' . $currency ) ?: $cryptoman->get_fees( count( $tx_message_bytes ) )[ $currency ];
139 |
140 | // if ( $currency === 'eth' ) {
141 | // // For ETH, the fee stored in the order is the gas_price, but the Crypto_Manager fallback returns a keyed array
142 | // $gas_price = is_array( $fee ) ? $fee[ 'gas_price' ] : $fee;
143 | // $protocolSpecific[ 'gasLimit' ] = 21000;
144 | // $protocolSpecific[ 'gasPrice' ] = $gas_price;
145 | // } else {
146 | // $protocolSpecific[ 'fee' ] = intval( $fee );
147 | // }
148 |
149 | // return woo_nimiq_checkout_reply( [
150 | // 'type' => 0, // DIRECT
151 | // 'currency' => $currency,
152 | // 'expires' => intval( $order->get_meta( 'crypto_rate_expires' ) ),
153 | // 'amount' => Order_Utils::get_order_total_crypto( $order ),
154 | // 'protocolSpecific' => $protocolSpecific,
155 | // ] );
156 | }
157 |
158 | function woo_nimiq_checkout_callback_get_state( $request, $order, $gateway ) {
159 | $currency = Order_Utils::get_order_currency( $order, false );
160 |
161 | if ( empty( $currency ) ) {
162 | // When no currency was selected, respond with the time only.
163 | return woo_nimiq_checkout_reply( [
164 | 'time' => time(),
165 | 'payment_accepted' => false,
166 | 'payment_state' => 'NOT_FOUND',
167 | ] );
168 | }
169 |
170 | $transaction_hash = $order->get_meta( 'transaction_hash' );
171 |
172 | if ( !empty( $transaction_hash ) ) {
173 | return woo_nimiq_checkout_reply( [
174 | 'time' => time(),
175 | 'payment_accepted' => true,
176 | 'payment_state' => $order->get_meta( 'nc_payment_state' ) ?: 'PAID',
177 | ] );
178 | }
179 |
180 | // Init validation service
181 | $services = [];
182 | $service_slug = $gateway->get_option( 'validation_service_' . $currency );
183 | include_once( dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR . 'validation_services' . DIRECTORY_SEPARATOR . $service_slug . '.php' );
184 | $service = $services[ $currency ];
185 |
186 | $payment_state = $service->load_transaction( $transaction_hash, $order, $gateway );
187 | if ( is_wp_error( $payment_state ) ) {
188 | return woo_nimiq_checkout_error( $payment_state->get_error_message(), 500 );
189 | }
190 |
191 | $payment_accepted = $service->transaction_found();
192 |
193 | $order->update_meta_data( 'nc_payment_state', $payment_state );
194 | $order->save();
195 |
196 | return woo_nimiq_checkout_reply( [
197 | 'time' => time(),
198 | 'payment_accepted' => $payment_accepted,
199 | 'payment_state' => $payment_state,
200 | ] );
201 | }
202 |
203 | function woo_nimiq_checkout_callback_unknown( $request, $order, $gateway ) {
204 | return woo_nimiq_checkout_error( 'Bad command', 406 );
205 | }
206 |
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 | ');
120 | }
121 | }
122 | $shop_logo_url.on('input', update_shop_logo_preview);
123 | update_shop_logo_preview();
124 |
125 | // Add change listener for Bitcoin xpub
126 | const $bitcoin_xpub = $('#woocommerce_nimiq_gateway_bitcoin_xpub');
127 | $bitcoin_xpub.on('input', function() {
128 | const xpub = $bitcoin_xpub.val();
129 | if (!xpub) return;
130 | let type;
131 | switch (xpub.substr(0, 4)) {
132 | case 'xpub':
133 | case 'tpub':
134 | type = 'bip-44';
135 | break;
136 | case 'zpub':
137 | case 'vpub':
138 | type = 'bip-84';
139 | break;
140 | default: break; // TODO Show error feedback to user
141 | }
142 | $('#woocommerce_nimiq_gateway_bitcoin_xpub_type').val(type);
143 | });
144 |
145 | // Add asterix to required fields
146 | $('.required').after('*');
147 |
148 | })(jQuery);
149 |
--------------------------------------------------------------------------------
/languages/wc-gateway-nimiq-es_ES.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/languages/wc-gateway-nimiq-es_ES.mo
--------------------------------------------------------------------------------
/languages/wc-gateway-nimiq-fil_PH.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/languages/wc-gateway-nimiq-fil_PH.mo
--------------------------------------------------------------------------------
/languages/wc-gateway-nimiq-fr_FR.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/languages/wc-gateway-nimiq-fr_FR.mo
--------------------------------------------------------------------------------
/languages/wc-gateway-nimiq-nl_NL.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/languages/wc-gateway-nimiq-nl_NL.mo
--------------------------------------------------------------------------------
/languages/wc-gateway-nimiq-pt_PT.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/languages/wc-gateway-nimiq-pt_PT.mo
--------------------------------------------------------------------------------
/languages/wc-gateway-nimiq-ru_RU.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/languages/wc-gateway-nimiq-ru_RU.mo
--------------------------------------------------------------------------------
/languages/wc-gateway-nimiq-uk_UA.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/languages/wc-gateway-nimiq-uk_UA.mo
--------------------------------------------------------------------------------
/languages/wc-gateway-nimiq-zh_CN.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nimiq/woocommerce-gateway-nimiq/512ed0168870cbe9996c7f43df29e302d18c64ec/languages/wc-gateway-nimiq-zh_CN.mo
--------------------------------------------------------------------------------
/nimiq-utils/JSONUtils.php:
--------------------------------------------------------------------------------
1 | $id,
19 | 'returnURL' => $returnURL,
20 | 'command' => $command,
21 | 'responseMethod' => $responseMethod,
22 | ];
23 |
24 | if (is_array($args)) {
25 | $fragment['args'] = JSONUtils::stringify($args);
26 | }
27 |
28 | // Test if we need to add a trailing slash
29 | $targetUrlComponents = parse_url($targetUrl);
30 | if(empty($targetUrlComponents['path']) && empty($targetUrlComponents['query']) && substr($targetUrl, -1) !== '/') {
31 | $targetUrl .= '/';
32 | }
33 |
34 | // Append fragment
35 | $targetUrl .= '#' . http_build_query($fragment);
36 |
37 | return $targetUrl;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/nimiq-xpub/README.md:
--------------------------------------------------------------------------------
1 | # Nimiq XPub
2 |
3 | [](https://travis-ci.com/nimiq/php-xpub)
4 |
5 | A simple class to derive BTC and ETH extended public keys and addresses without GMP.
6 | Only the BCMath extension is required (but GMP is still used for faster calculations when available).
7 |
8 | Supports `xpub`, `tpub`, `zpub` and `vpub` formats.
9 |
10 | ## Installation
11 |
12 | The Nimiq PHP Utilities are availabe via the [Packagist package registry](https://packagist.org/packages/nimiq/xpub) and can be installed with [Composer](https://getcomposer.org):
13 |
14 | ```bash
15 | composer require nimiq/xpub
16 | ```
17 |
18 | ### Requirements
19 |
20 | * PHP >= 7.1
21 | * BCMath or GMP extension
22 |
23 | ## Usage
24 |
25 | ```php
26 | # PSR-4 autoloading with composer
27 | use Nimiq\XPub;
28 |
29 | # Create an XPub class instance from an xpub/tpub/zpub/vpub string.
30 | $xpub = XPub::fromString( 'xpub...' );
31 |
32 | # Derive a child extended public key from it.
33 | $xpub_i = $xpub->derive( $i );
34 | # You can also pass an array to derive a path.
35 | $xpub_i_k = $xpub->derive( [$i, $k]);
36 |
37 | # An XPub can be serialized back into a string.
38 | # Pass $asHex = true to serialize into a HEX string, base58 is the default.
39 | $xpub_string = $xpub_i->toString( $asHex = false );
40 |
41 | # An XPub can be converted into an address.
42 | # Pass $coin = 'eth' to convert into an ETH address.
43 | # (xpubs are converted into regular addresses, zpubs are converted into segwit addresses.)
44 | $address = $xpub_i->toAddress( $coin = 'btc' );
45 | ```
46 |
47 | _[See the tests](test/test.php) for example usage._
48 |
49 | The `XPub` class also exposes two common hashing methods:
50 |
51 | ```php
52 | # Get a hash160
53 | $hashed_hex = XPub::hash160( $input_hex );
54 |
55 | # Get a double sha256
56 | $hashed_hex = XPub::doubleSha256( $input_hex );
57 | ```
58 |
59 | ## Development
60 |
61 | ### Testing
62 |
63 | To execute the test suite run:
64 |
65 | ```bash
66 | composer run-script test
67 | # or
68 | php test/test.php
69 | ```
70 |
--------------------------------------------------------------------------------
/nimiq-xpub/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nimiq/xpub",
3 | "version": "1.1.1",
4 | "description": "A simple class to derive BTC and ETH extended public keys and addresses without GMP.",
5 | "keywords": ["nimiq", "blockchain", "bitcoin", "ethereum", "address", "derivation", "bcmath"],
6 | "homepage": "https://github.com/nimiq/php-xpub",
7 | "type": "library",
8 | "license": "Apache-2.0",
9 | "authors": [
10 | {
11 | "name": "Sören Schwert",
12 | "email": "soeren@nimiq.com"
13 | }
14 | ],
15 | "minimum-stability": "stable",
16 | "scripts": {
17 | "test": "php test/test.php"
18 | },
19 | "require": {
20 | "php": "^7.1",
21 | "ext-bcmath": "*",
22 | "simplito/elliptic-php": "^1.0",
23 | "stephenhill/base58": "^1.1",
24 | "kornrunner/keccak": "^1.0",
25 | "bitwasp/bech32": "^0.0.1"
26 | },
27 | "autoload": {
28 | "psr-4": {
29 | "Nimiq\\": "src/"
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/nimiq-xpub/src/XPub.php:
--------------------------------------------------------------------------------
1 | '0488b21e',
17 | 'tpub' => '043587cf',
18 | 'zpub' => '04b24746',
19 | 'vpub' => '045f1cf6',
20 | ];
21 |
22 | // https://en.bitcoin.it/wiki/List_of_address_prefixes
23 | public const NETWORK_ID = [
24 | 'xpub' => '00',
25 | 'tpub' => '6f',
26 | ];
27 |
28 | public const SEGWIT_HRP = [
29 | 'zpub' => 'bc',
30 | 'vpub' => 'tc',
31 | ];
32 |
33 | public const SEGWIT_VERSION = 0;
34 |
35 | public static function fromString(string $xpub_base58, string $bip = ''): XPub {
36 | $version = self::bip2version($bip, substr($xpub_base58, 0, 4));
37 |
38 | if (!array_key_exists($version, self::HEX_VERSION)) {
39 | throw new \Exception('Invalid version!');
40 | }
41 |
42 | $xpub_bin = (new Base58())->decode($xpub_base58);
43 |
44 | // Validate length
45 | if (strlen($xpub_bin) !== 78 && strlen($xpub_bin) !== 82) {
46 | throw new \Exception('Invalid length!');
47 | }
48 |
49 | $depth = self::bin2dec(substr($xpub_bin, 4, 1));
50 | $fpr_par = bin2hex(substr($xpub_bin, 5, 4));
51 | $i = self::bin2dec(substr($xpub_bin, 9, 4));
52 | $c = bin2hex(substr($xpub_bin, 13, 32));
53 | $K = bin2hex(substr($xpub_bin, 45, 33));
54 |
55 | // Validate checksum if available
56 | $checksum = substr($xpub_bin, 78, 4);
57 | if (!empty($checksum)) {
58 | $base_xpub_hex = bin2hex(substr($xpub_bin, 0, 78));
59 | if (substr(self::doubleSha256($base_xpub_hex), 0, 8) !== bin2hex($checksum)) {
60 | throw new \Exception('Invalid checksum!');
61 | }
62 | }
63 |
64 | return new self(
65 | $version,
66 | $depth,
67 | $fpr_par,
68 | $i,
69 | $c,
70 | $K
71 | );
72 | }
73 |
74 | public static function bin2dec(string $bin): int {
75 | return unpack('C', $bin)[1];
76 | }
77 |
78 | public static function hash160(string $hex): string {
79 | return hash('ripemd160', hash('sha256', hex2bin($hex), TRUE));
80 | }
81 |
82 | public static function doubleSha256(string $hex): string {
83 | return hash('sha256', hash('sha256', hex2bin($hex), TRUE));
84 | }
85 |
86 | private static function bip2version(string $bip, string $prefix): string {
87 | switch($bip) {
88 | case self::BIP44: return in_array($prefix, ['xpub', 'zpub']) ? 'xpub' : 'tpub';
89 | case self::BIP84: return in_array($prefix, ['xpub', 'zpub']) ? 'zpub' : 'vpub';
90 | default: return $bip ?: $prefix;
91 | }
92 | }
93 |
94 | public function __construct(
95 | string $version,
96 | int $depth,
97 | string $parent_fingerprint,
98 | int $index,
99 | string $c,
100 | string $K
101 | ) {
102 | $this->version = $version;
103 | $this->depth = $depth;
104 | $this->parent_fingerprint = $parent_fingerprint;
105 | $this->index = $index;
106 | $this->c = $c;
107 | $this->K = $K;
108 | }
109 |
110 | public function derive($indices): XPub {
111 | if (!is_array($indices)) $indices = [$indices];
112 | $i = array_shift($indices);
113 |
114 | $ec = new EC('secp256k1'); // BTC Elliptic Curve
115 |
116 | $I_key = hex2bin($this->c);
117 | $I_data = hex2bin($this->K) . pack('N', $i);
118 | $I = hash_hmac('sha512', $I_data, $I_key);
119 | $I_L = substr($I, 0, 64);
120 | $I_R = substr($I, 64, 64);
121 | $c_i = $I_R; // Child Chain Code
122 |
123 | $K_par_point = $ec->curve->decodePoint($this->K, 'hex');
124 | $I_L_point = $ec->g->mul(new BN($I_L, 16));
125 | $K_i = $K_par_point->add($I_L_point);
126 | $K_i = $K_i->encodeCompressed('hex'); // Child Public Key
127 |
128 | $fpr_par = substr(self::hash160($this->K), 0, 8); // Parent Fingerprint
129 |
130 | $child = new self(
131 | $this->version,
132 | $this->depth + 1,
133 | $fpr_par,
134 | $i,
135 | $c_i,
136 | $K_i
137 | );
138 |
139 | // Recursive derivation
140 | if (count($indices) > 0) return $child->derive($indices);
141 |
142 | return $child;
143 | }
144 |
145 | public function toString(bool $asHex = false): string {
146 | $xpub_hex = self::HEX_VERSION[$this->version];
147 | $xpub_hex .= str_pad(dechex($this->depth), 2, '0', STR_PAD_LEFT);
148 | $xpub_hex .= $this->parent_fingerprint;
149 | $xpub_hex .= str_pad(dechex($this->index), 8, '0', STR_PAD_LEFT);
150 | $xpub_hex .= $this->c;
151 | $xpub_hex .= $this->K;
152 |
153 | // Checksum
154 | $xpub_hex .= substr(self::doubleSha256($xpub_hex), 0, 8);
155 |
156 | if ($asHex) return $xpub_hex;
157 |
158 | return (new Base58())->encode(hex2bin($xpub_hex));
159 | }
160 |
161 | public function toAddress(string $coin = 'btc'): string {
162 | switch ($coin) {
163 | case 'btc': return $this->toBTCAddress();
164 | case 'eth': return $this->toETHAddress();
165 | default: throw new \Exception('Coin type "' . $coin . '" not supported!');
166 | }
167 | }
168 |
169 | private function toBTCAddress(): string {
170 | switch ($this->version) {
171 | case 'xpub': case 'tpub': return $this->toBTCP2PKHAddress();
172 | case 'zpub': case 'vpub': return $this->toBTCP2WPKHAddress();
173 | default: throw new \Exception('Version "' . $this->version . '" not supported!');
174 | }
175 | }
176 |
177 | private function toBTCP2PKHAddress(): string {
178 | $base_address = self::NETWORK_ID[$this->version] . self::hash160($this->K);
179 | $checksum = substr(self::doubleSha256($base_address), 0, 8);
180 |
181 | $address_hex = $base_address . $checksum;
182 |
183 | return (new Base58())->encode(hex2bin($address_hex));
184 | }
185 |
186 | private function toBTCP2WPKHAddress(): string {
187 | $programm = self::hash160($this->K);
188 | $version = self::SEGWIT_VERSION;
189 | $hrp = self::SEGWIT_HRP[$this->version];
190 | return Bech32\encodeSegwit($hrp, $version, hex2bin($programm));
191 | }
192 |
193 | private function toETHAddress(): string {
194 | $ec = new EC('secp256k1'); // ETH Elliptic Curve
195 | $K_full = $ec->keyFromPublic($this->K, 'hex')->getPublic('hex');
196 |
197 | $K_bin = hex2bin(substr($K_full, 2));
198 | $hash_hex = Keccak::hash($K_bin, 256);
199 | $base_address = substr($hash_hex, 24, 40);
200 |
201 | return '0x' . $this->encodeETHChecksum($base_address);
202 | }
203 |
204 | private function encodeETHChecksum(string $base_address): string {
205 | $binary = $this->hex2binary(Keccak::hash($base_address, 256));
206 |
207 | $encoded = '';
208 | foreach (str_split($base_address) as $i => $char) {
209 | if (strpos('abcdef', $char) !== false) {
210 | $encoded .= $binary[$i * 4] === '1' ? strtoupper($char) : strtolower($char);
211 | } else {
212 | $encoded .= $char;
213 | }
214 | }
215 | return $encoded;
216 | }
217 |
218 | private function hex2binary($hex): string {
219 | $binary = '';
220 | foreach (str_split($hex, 2) as $hexit) {
221 | $binary .= str_pad(decbin(hexdec($hexit)), 8, '0', STR_PAD_LEFT);
222 | }
223 | return $binary;
224 | }
225 | }
226 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/autoload.php:
--------------------------------------------------------------------------------
1 | $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
10 | 'a626201e4406003b96eee958a069f504' => $vendorDir . '/bitwasp/bech32/src/bech32.php',
11 | );
12 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/composer/autoload_namespaces.php:
--------------------------------------------------------------------------------
1 | array($vendorDir . '/kornrunner/keccak/src'),
10 | 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
11 | 'StephenHill\\Benchmarks\\' => array($vendorDir . '/stephenhill/base58/benchmarks'),
12 | 'StephenHill\\' => array($vendorDir . '/stephenhill/base58/src'),
13 | 'Nimiq\\' => array($baseDir . '/src'),
14 | 'Elliptic\\' => array($vendorDir . '/simplito/elliptic-php/lib'),
15 | 'BitWasp\\Bech32\\' => array($vendorDir . '/bitwasp/bech32/src'),
16 | 'BN\\' => array($vendorDir . '/simplito/bn-php/lib'),
17 | 'BI\\' => array($vendorDir . '/simplito/bigint-wrapper-php/lib'),
18 | );
19 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/composer/autoload_real.php:
--------------------------------------------------------------------------------
1 | = 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27 | if ($useStaticLoader) {
28 | require_once __DIR__ . '/autoload_static.php';
29 |
30 | call_user_func(\Composer\Autoload\ComposerStaticInitf38dd7bf910ade5fd72e09ef3328f74b::getInitializer($loader));
31 | } else {
32 | $map = require __DIR__ . '/autoload_namespaces.php';
33 | foreach ($map as $namespace => $path) {
34 | $loader->set($namespace, $path);
35 | }
36 |
37 | $map = require __DIR__ . '/autoload_psr4.php';
38 | foreach ($map as $namespace => $path) {
39 | $loader->setPsr4($namespace, $path);
40 | }
41 |
42 | $classMap = require __DIR__ . '/autoload_classmap.php';
43 | if ($classMap) {
44 | $loader->addClassMap($classMap);
45 | }
46 | }
47 |
48 | $loader->register(true);
49 |
50 | if ($useStaticLoader) {
51 | $includeFiles = Composer\Autoload\ComposerStaticInitf38dd7bf910ade5fd72e09ef3328f74b::$files;
52 | } else {
53 | $includeFiles = require __DIR__ . '/autoload_files.php';
54 | }
55 | foreach ($includeFiles as $fileIdentifier => $file) {
56 | composerRequiref38dd7bf910ade5fd72e09ef3328f74b($fileIdentifier, $file);
57 | }
58 |
59 | return $loader;
60 | }
61 | }
62 |
63 | function composerRequiref38dd7bf910ade5fd72e09ef3328f74b($fileIdentifier, $file)
64 | {
65 | if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66 | require $file;
67 |
68 | $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/composer/autoload_static.php:
--------------------------------------------------------------------------------
1 | __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
11 | 'a626201e4406003b96eee958a069f504' => __DIR__ . '/..' . '/bitwasp/bech32/src/bech32.php',
12 | );
13 |
14 | public static $prefixLengthsPsr4 = array (
15 | 'k' =>
16 | array (
17 | 'kornrunner\\' => 11,
18 | ),
19 | 'S' =>
20 | array (
21 | 'Symfony\\Polyfill\\Mbstring\\' => 26,
22 | 'StephenHill\\Benchmarks\\' => 23,
23 | 'StephenHill\\' => 12,
24 | ),
25 | 'N' =>
26 | array (
27 | 'Nimiq\\' => 6,
28 | ),
29 | 'E' =>
30 | array (
31 | 'Elliptic\\' => 9,
32 | ),
33 | 'B' =>
34 | array (
35 | 'BitWasp\\Bech32\\' => 15,
36 | 'BN\\' => 3,
37 | 'BI\\' => 3,
38 | ),
39 | );
40 |
41 | public static $prefixDirsPsr4 = array (
42 | 'kornrunner\\' =>
43 | array (
44 | 0 => __DIR__ . '/..' . '/kornrunner/keccak/src',
45 | ),
46 | 'Symfony\\Polyfill\\Mbstring\\' =>
47 | array (
48 | 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
49 | ),
50 | 'StephenHill\\Benchmarks\\' =>
51 | array (
52 | 0 => __DIR__ . '/..' . '/stephenhill/base58/benchmarks',
53 | ),
54 | 'StephenHill\\' =>
55 | array (
56 | 0 => __DIR__ . '/..' . '/stephenhill/base58/src',
57 | ),
58 | 'Nimiq\\' =>
59 | array (
60 | 0 => __DIR__ . '/../..' . '/src',
61 | ),
62 | 'Elliptic\\' =>
63 | array (
64 | 0 => __DIR__ . '/..' . '/simplito/elliptic-php/lib',
65 | ),
66 | 'BitWasp\\Bech32\\' =>
67 | array (
68 | 0 => __DIR__ . '/..' . '/bitwasp/bech32/src',
69 | ),
70 | 'BN\\' =>
71 | array (
72 | 0 => __DIR__ . '/..' . '/simplito/bn-php/lib',
73 | ),
74 | 'BI\\' =>
75 | array (
76 | 0 => __DIR__ . '/..' . '/simplito/bigint-wrapper-php/lib',
77 | ),
78 | );
79 |
80 | public static function getInitializer(ClassLoader $loader)
81 | {
82 | return \Closure::bind(function () use ($loader) {
83 | $loader->prefixLengthsPsr4 = ComposerStaticInitf38dd7bf910ade5fd72e09ef3328f74b::$prefixLengthsPsr4;
84 | $loader->prefixDirsPsr4 = ComposerStaticInitf38dd7bf910ade5fd72e09ef3328f74b::$prefixDirsPsr4;
85 |
86 | }, null, ClassLoader::class);
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/kornrunner/keccak/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Boris Momčilović
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/kornrunner/keccak/README.md:
--------------------------------------------------------------------------------
1 | # php-keccak [](https://travis-ci.org/kornrunner/php-keccak) [](https://coveralls.io/github/kornrunner/php-keccak?branch=master)
2 | Pure PHP implementation of Keccak (SHA-3)
3 |
4 | ## Usage
5 |
6 | ```php
7 | =7.1.0",
14 | "symfony/polyfill-mbstring": "^1.8"
15 | },
16 | "autoload": {
17 | "psr-4": {
18 | "kornrunner\\": "src"
19 | }
20 | },
21 | "autoload-dev": {
22 | "psr-4": {
23 | "kornrunner\\": "test"
24 | }
25 | },
26 | "require-dev": {
27 | "phpunit/phpunit": "~7",
28 | "php-coveralls/php-coveralls": "^2.1"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/bigint-wrapper-php/LICENSE.md:
--------------------------------------------------------------------------------
1 |
2 | ## MIT LICENSE
3 |
4 | Copyright (C) 2018 Simplito
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a
7 | copy of this software and associated documentation files (the
8 | "Software"), to deal in the Software without restriction, including
9 | without limitation the rights to use, copy, modify, merge, publish,
10 | distribute, sublicense, and/or sell copies of the Software, and to permit
11 | persons to whom the Software is furnished to do so, subject to the
12 | following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included
15 | in all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
20 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 | USE OR OTHER DEALINGS IN THE SOFTWARE.
24 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/bigint-wrapper-php/README.md:
--------------------------------------------------------------------------------
1 |
2 | # BigInteger wrapper library for PHP
3 |
4 | ## Information
5 |
6 | This library is a common interface for php_gmp and php_bcmath modules. It automatically detects supported modules and uses the best of them (gmp>bcmath). Gmp is a lot faster, but is also missing on many hosting services -- that is why this wrapper has been created. It is used for example in encryption functions of the [PrivMX WebMail](https://privmx.com) software.
7 |
8 | ## Installation
9 |
10 | You can install this library via Composer:
11 | ```
12 | composer require simplito/bigint-wrapper-php
13 | ```
14 |
15 | ## Documentation
16 |
17 | If you want to force using a specific implementation, then define constant S_MATH_BIGINTEGER_MODE - set it to "gmp" or "bcmath". If you do not do this, mode of operation and the constant will be set automatically.
18 |
19 | If there are no gmp and bcmath modules, an exception will be thrown. If you want to prevent this, then simply define S_MATH_BIGINTEGER_QUIET constant.
20 |
21 | All functions of this library are implemented as members of class BigInteger, which is located under BI namespace. Instances of BigInteger are immutable - member functions usually return new instances of the BigInteger class.
22 |
23 |
24 | ### ConvertibleToBi - a placeholder type
25 |
26 | To make the below documentation more readable we use the "ConvertibleToBi" type symbol, which in reality can be one of the following types:
27 | - an instance of the BigInteger class
28 | - an integer
29 | - a decimal string
30 | - a gmp resource or class (only when you are in gmp mode)
31 |
32 | If you have a non-decimal string and want to use it -- first you have to convert it to BigInteger class using:
33 | ```
34 | new BigInteger($myNonDecimalString, $baseOfMyNonDecimalString)
35 | ```
36 |
37 | ### BI\BigInteger class members
38 |
39 | #### construct(ConvertibleToBi $value = 0, int $base = 10)
40 | Creates a new instance of BigInteger. If you pass an invalid value, an exception will be thrown. If $base === true then passed $value will be used without any check and conversion. Supported bases: 2, 10, 16, 256.
41 | - **GMP implementation:** gmp_init + bin2hex for 256 base
42 | - **Bcmath implementation:** custom(bcadd + bcmul)
43 |
44 | #### static BigInteger|false createSafe(ConvertibleToBi $value = 0, int $base = 10)
45 | Creates a new BigInteger instance in the same way as constructor, but if there is an error, false will be returned instead of throwing an exception.
46 |
47 | #### BigInteger add(ConvertibleToBi $x)
48 | Adds numbers
49 | - **GMP implementation:** gmp_add
50 | - **Bcmath implementation:** bcadd
51 |
52 | #### BigInteger sub(ConvertibleToBi $x)
53 | Subtracts numbers
54 | - **GMP implementation:** gmp_sub
55 | - **Bcmath implementation:** bcsub
56 |
57 | #### BigInteger mul(ConvertibleToBi $x)
58 | Multiplies numbers
59 | - **GMP implementation:** gmp_mul
60 | - **Bcmath implementation:** bcmul
61 |
62 | #### BigInteger div(ConvertibleToBi $x)
63 | Divides numbers
64 | - **GMP implementation:** gmp_div_q
65 | - **Bcmath implementation:** bcdiv
66 |
67 | #### BigInteger divR(ConvertibleToBi $x)
68 | Returns a remainder of the division of numbers. The remainder has the sign of the divided number.
69 | - **GMP implementation:** gmp_div_r
70 | - **Bcmath implementation:** bcmod
71 |
72 | #### array(BigInteger, BigInteger) divQR(ConvertibleToBi $x)
73 | Divides numbers and returns quotient and remainder. Returns an array(), with the first element being quotient, and the second being remainder.
74 | - **GMP implementation:** gmp_div_qr
75 | - **Bcmath implementation:** div + divR
76 |
77 | #### BigInteger mod(ConvertibleToBi $x)
78 | The "division modulo" operation. The result is always non-negative, the sign of divider is ignored.
79 | - **GMP implementation:** gmp_mod
80 | - **Bcmath implementation:** custom (bcmod + bcadd)
81 |
82 | #### BigInteger gcd(ConvertibleToBi $x)
83 | Calculates greatest common divisor
84 | - **GMP implementation:** gmp_gcd
85 | - **Bcmath implementation:** custom (bccomp + bcdiv + bcsub + bcmul)
86 |
87 | #### BigInteger|false modInverse(ConvertibleToBi $x)
88 | Inverses by modulo, returns false if inversion does not exist.
89 | - **GMP implementation:** gmp_invert
90 | - **Bcmath implementation:** custom (gcd)
91 |
92 | #### BigInteger pow(ConvertibleToBi $x)
93 | The power function.
94 | - **GMP implementation:** gmp_pow
95 | - **Bcmath implementation:** bcpow
96 |
97 | #### BigInteger powMod(ConvertibleToBi $x, ConvertibleToBi $n)
98 | The modular power function.
99 | - **GMP implementation:** gmp_powm
100 | - **Bcmath implementation:** bcpowmod
101 |
102 | #### BigInteger abs()
103 | Returns absolute value.
104 | - **GMP implementation:** gmp_abs
105 | - **Bcmath implementation:** check first character
106 |
107 | #### BigInteger neg()
108 | Negates the number
109 | - **GMP implementation:** gmp_neg
110 | - **Bcmath implementation:** check first character
111 |
112 | #### BigInteger binaryAnd(ConvertibleToBi $x)
113 | Bitwise AND.
114 | - **GMP implementation:** gmp_and
115 | - **Bcmath implementation:** custom (toBytes + php string and)
116 |
117 | #### BigInteger binaryOr(ConvertibleToBi $x)
118 | Bitwise OR
119 | - **GMP implementation:** gmp_or
120 | - **Bcmath implementation:** custom (toBytes + php string or)
121 |
122 | #### BigInteger binaryXor(ConvertibleToBi $x)
123 | Bitwise XOR
124 | - **GMP implementation:** gmp_xor
125 | - **Bcmath implementation:** custom (toBytes + php string xor)
126 |
127 | #### BigInteger setbit($index, $bitOn = true)
128 | Sets bit at given index
129 | - **GMP implementation:** gmp_setbit
130 | - **Bcmath implementation:** custom (toBits)
131 |
132 | #### bool testbit($index)
133 | Tests if a bit at given index is set
134 | - **GMP implementation:** gmp_testbit
135 | - **Bcmath implementation:** custom (toBits)
136 |
137 | #### int scan0($start)
138 | Scans for 0, and returns index of first found bit
139 | - **GMP implementation:** gmp_scan0
140 | - **Bcmath implementation:** custom (toBits)
141 |
142 | #### int scan1($start)
143 | Scans for 1, and returns index of first found bit
144 | - **GMP implementation:** gmp_scan1
145 | - **Bcmath implementation:** custom (toBits)
146 |
147 | #### int cmp(ConvertibleToBi $x)
148 | Compares numbers, returns <0, 0, >0
149 | - **GMP implementation:** gmp_cmp
150 | - **Bcmath implementation:** bccomp
151 |
152 | #### bool equals(ConvertibleToBi $x)
153 | Checks if numbers are equal
154 | - **GMP implementation:** gmp_cmp
155 | - **Bcmath implementation:** bccomp
156 |
157 | #### int sign()
158 | Sign of number, returns -1, 0, 1
159 | - **GMP implementation:** gmp_sign
160 | - **Bcmath implementation:** check first character
161 |
162 | #### int toNumber()
163 | Converts to number (use only with small 32/64bit numbers)
164 | - **GMP implementation:** gmp_intval
165 | - **Bcmath implementation:** intval
166 |
167 | #### string toDec()
168 | Converts to decimal string
169 | - **GMP implementation:** gmp_strval
170 | - **Bcmath implementation:** just the value
171 |
172 | #### string toHex()
173 | Converts to hex string
174 | - **GMP implementation:** gmp_strval
175 | - **Bcmath implementation:** toBytes + bin2hex
176 |
177 | #### string toBytes
178 | Converts to binary string
179 | - **GMP implementation:** gmp_strval + hex2bin
180 | - **Bcmath implementation:** custom (bcmod + bcdiv + bccomp)
181 |
182 | #### string toBits()
183 | Converts to bits string (0 and 1 characters)
184 | - **GMP implementation:** gmp_strval
185 | - **Bcmath implementation:** toBytes + decbin
186 |
187 | #### string toString(int $base = 10)
188 | Converts to string using given base (supported bases 2-62, 256)
189 | - **GMP implementation:** all above toX functions, and for non standard gmp_strval
190 | - **Bcmath implementation:** all above toX functions, and for non standard bcmod + bcdiv + bccomp
191 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/bigint-wrapper-php/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "simplito/bigint-wrapper-php",
3 | "description": "Common interface for php_gmp and php_bcmath modules",
4 | "license": "MIT",
5 | "authors": [
6 | {
7 | "name": "Simplito Team",
8 | "email": "s.smyczynski@simplito.com",
9 | "homepage": "https://simplito.com"
10 | }
11 | ],
12 | "autoload": {
13 | "psr-4": {
14 | "BI\\": "lib/"
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/bn-php/LICENSE.md:
--------------------------------------------------------------------------------
1 |
2 | ## MIT LICENSE
3 |
4 | Copyright (C) 2018 Simplito
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a
7 | copy of this software and associated documentation files (the
8 | "Software"), to deal in the Software without restriction, including
9 | without limitation the rights to use, copy, modify, merge, publish,
10 | distribute, sublicense, and/or sell copies of the Software, and to permit
11 | persons to whom the Software is furnished to do so, subject to the
12 | following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included
15 | in all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
20 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 | USE OR OTHER DEALINGS IN THE SOFTWARE.
24 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/bn-php/README.md:
--------------------------------------------------------------------------------
1 |
2 | # BigNum library for PHP
3 |
4 |
5 | ## Information
6 |
7 | This library provides a PHP Big Number API compatible with [bn.js](https://github.com/indutny/bn.js) and is used in Fast PHP ECC library [elliptic-php](https://github.com/simplito/elliptic-php).
8 |
9 | This software is licensed under the MIT License.
10 |
11 |
12 | ## Installation
13 |
14 | You can install this library via Composer:
15 | ```
16 | composer require simplito/bn-php
17 | ```
18 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/bn-php/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "simplito/bn-php",
3 | "description": "Big number implementation compatible with bn.js",
4 | "license": "MIT",
5 | "authors": [
6 | {
7 | "name": "Simplito Team",
8 | "email": "s.smyczynski@simplito.com",
9 | "homepage": "https://simplito.com"
10 | }
11 | ],
12 | "require": {
13 | "simplito/bigint-wrapper-php": "~1.0.0"
14 | },
15 | "require-dev": {
16 | "phpunit/phpunit": "*"
17 | },
18 | "autoload": {
19 | "psr-4": {
20 | "BN\\": "lib/"
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/bn-php/lib/Red.php:
--------------------------------------------------------------------------------
1 | m = Red::primeByName($m);
15 | else
16 | $this->m = $m;
17 |
18 | if( !$this->m->gtn(1) )
19 | throw new Exception("Modulus must be greater than 1");
20 | }
21 |
22 |
23 | public static function primeByName($name)
24 | {
25 | switch($name) {
26 | case "k256":
27 | return new BN("ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f", 16);
28 | case "p224":
29 | return new BN("ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001", 16);
30 | case "p192":
31 | return new BN("ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff", 16);
32 | case "p25519":
33 | return new BN("7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed", 16);
34 | default:
35 | throw new Exception("Unknown prime name " . $name);
36 | }
37 | }
38 |
39 | public function verify1(BN $num)
40 | {
41 | if (assert_options(ASSERT_ACTIVE)) assert(!$num->negative()); //,"red works only with positives");
42 | assert($num->red); //, "red works only with red numbers");
43 | }
44 |
45 | public function verify2(BN $a, BN $b)
46 | {
47 | if (assert_options(ASSERT_ACTIVE)) assert(!$a->negative() && !$b->negative()); //, "red works only with positives");
48 | assert($a->red && ($a->red == $b->red)); //, "red works only with red numbers");
49 | }
50 |
51 | public function imod(BN &$a) {
52 | return $a->umod($this->m)->_forceRed($this);
53 | }
54 |
55 | public function neg(BN $a)
56 | {
57 | if( $a->isZero() )
58 | return $a->_clone();
59 | return $this->m->sub($a)->_forceRed($this);
60 | }
61 |
62 | public function add(BN $a, BN $b)
63 | {
64 | $this->verify2($a, $b);
65 |
66 | $res = $a->add($b);
67 | if( $res->cmp($this->m) >= 0 )
68 | $res->isub($this->m);
69 | return $res->_forceRed($this);
70 | }
71 |
72 | public function iadd(BN &$a, BN $b)
73 | {
74 | $this->verify2($a, $b);
75 |
76 | $a->iadd($b);
77 | if( $a->cmp($this->m) >= 0 )
78 | $a->isub($this->m);
79 |
80 | return $a;
81 | }
82 |
83 | public function sub(BN $a, BN $b)
84 | {
85 | $this->verify2($a, $b);
86 |
87 | $res = $a->sub($b);
88 | if( $res->negative() )
89 | $res->iadd($this->m);
90 |
91 | return $res->_forceRed($this);
92 | }
93 |
94 | public function isub(BN &$a, $b)
95 | {
96 | $this->verify2($a, $b);
97 |
98 | $a->isub($b);
99 | if( $a->negative() )
100 | $a->iadd($this->m);
101 |
102 | return $a;
103 | }
104 |
105 | public function shl(BN $a, $num) {
106 | $this->verify1($a);
107 | return $this->imod($a->ushln($num));
108 | }
109 |
110 | public function imul(BN &$a, BN $b) {
111 | $this->verify2($a, $b);
112 | $res = $a->imul($b);
113 | return $this->imod($res);
114 | }
115 |
116 | public function mul(BN $a, BN $b) {
117 | $this->verify2($a, $b);
118 | $res = $a->mul($b);
119 | return $this->imod($res);
120 | }
121 |
122 | public function sqr(BN $a) {
123 | $res = $a->_clone();
124 | return $this->imul($res, $a);
125 | }
126 |
127 | public function isqr(BN &$a) {
128 | return $this->imul($a, $a);
129 | }
130 |
131 | public function sqrt(BN $a) {
132 | if ($a->isZero())
133 | return $a->_clone();
134 |
135 | $mod3 = $this->m->andln(3);
136 | assert($mod3 % 2 == 1);
137 |
138 | // Fast case
139 | if ($mod3 == 3) {
140 | $pow = $this->m->add(new BN(1))->iushrn(2);
141 | return $this->pow($a, $pow);
142 | }
143 |
144 | // Tonelli-Shanks algorithm (Totally unoptimized and slow)
145 | //
146 | // Find Q and S, that Q * 2 ^ S = (P - 1)
147 | $q = $this->m->subn(1);
148 | $s = 0;
149 | while (!$q->isZero() && $q->andln(1) == 0) {
150 | $s++;
151 | $q->iushrn(1);
152 | }
153 | if (assert_options(ASSERT_ACTIVE)) assert(!$q->isZero());
154 |
155 | $one = (new BN(1))->toRed($this);
156 | $nOne = $one->redNeg();
157 |
158 | // Find quadratic non-residue
159 | // NOTE: Max is such because of generalized Riemann hypothesis.
160 | $lpow = $this->m->subn(1)->iushrn(1);
161 | $z = $this->m->bitLength();
162 | $z = (new BN(2 * $z * $z))->toRed($this);
163 |
164 | while ($this->pow($z, $lpow)->cmp($nOne) != 0) {
165 | $z->redIAdd($nOne);
166 | }
167 |
168 | $c = $this->pow($z, $q);
169 | $r = $this->pow($a, $q->addn(1)->iushrn(1));
170 | $t = $this->pow($a, $q);
171 | $m = $s;
172 | while ($t->cmp($one) != 0) {
173 | $tmp = $t;
174 | for ($i = 0; $tmp->cmp($one) != 0; $i++) {
175 | $tmp = $tmp->redSqr();
176 | }
177 | if ($i >= $m) {
178 | throw new \Exception("Assertion failed");
179 | }
180 | if ($m - $i - 1 > 54) {
181 | $b = $this->pow($c, (new BN(1))->iushln($m - $i - 1));
182 | } else {
183 | $b = clone($c);
184 | $b->bi = $c->bi->powMod(1 << ($m - $i - 1), $this->m->bi);
185 | }
186 |
187 | $r = $r->redMul($b);
188 | $c = $b->redSqr();
189 | $t = $t->redMul($c);
190 | $m = $i;
191 | }
192 |
193 | return $r;
194 | }
195 |
196 | public function invm(BN &$a) {
197 | $res = $a->invm($this->m);
198 | return $this->imod($res);
199 | }
200 |
201 | public function pow(BN $a, BN $num) {
202 | $r = clone($a);
203 | $r->bi = $a->bi->powMod($num->bi, $this->m->bi);
204 | return $r;
205 | }
206 |
207 | public function convertTo(BN $num) {
208 | $r = $num->umod($this->m);
209 | return $r === $num ? $r->_clone() : $r;
210 | }
211 |
212 | public function convertFrom(BN $num) {
213 | $res = $num->_clone();
214 | $res->red = null;
215 | return $res;
216 | }
217 | }
218 |
219 | ?>
220 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/elliptic-php/LICENSE.md:
--------------------------------------------------------------------------------
1 |
2 | ## MIT LICENSE
3 |
4 | Copyright (C) 2016 Simplito
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a
7 | copy of this software and associated documentation files (the
8 | "Software"), to deal in the Software without restriction, including
9 | without limitation the rights to use, copy, modify, merge, publish,
10 | distribute, sublicense, and/or sell copies of the Software, and to permit
11 | persons to whom the Software is furnished to do so, subject to the
12 | following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included
15 | in all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
20 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 | USE OR OTHER DEALINGS IN THE SOFTWARE.
24 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/elliptic-php/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Fast Elliptic Curve Cryptography in PHP
3 |
4 |
5 | ## Information
6 |
7 | This library is a PHP port of [elliptic](https://github.com/indutny/elliptic), a great JavaScript ECC library.
8 |
9 | * Supported curve types: Short Weierstrass, Montgomery, Edwards, Twisted Edwards.
10 | * Curve 'presets': `secp256k1`, `p192`, `p224`, `p256`, `p384`, `p521`, `curve25519`, `ed25519`.
11 |
12 | This software is licensed under the MIT License.
13 |
14 | Projects which use Fast ECC PHP library: [PrivMX WebMail](https://privmx.com), ...
15 |
16 |
17 | ## Benchmarks
18 |
19 | ```
20 | +------------------------+----------------+--------+-----+------+
21 | | subject | mode | rstdev | its | revs |
22 | +------------------------+----------------+--------+-----+------+
23 | | elliptic#genKeyPair | 323.682ops/s | 2.72% | 5 | 50 |
24 | | mdanter#genKeyPair | 13.794ops/s | 3.18% | 5 | 50 |
25 | +------------------------+----------------+--------+-----+------+
26 | | elliptic#sign | 307.228ops/s | 3.82% | 5 | 50 |
27 | | mdanter#sign | 14.118ops/s | 2.12% | 5 | 50 |
28 | +------------------------+----------------+--------+-----+------+
29 | | elliptic#verify | 93.913ops/s | 5.93% | 5 | 50 |
30 | | mdanter#verify | 6.859ops/s | 2.95% | 5 | 50 |
31 | +------------------------+----------------+--------+-----+------+
32 | | elliptic#dh | 135.166ops/s | 1.67% | 5 | 50 |
33 | | mdanter#dh | 14.302ops/s | 0.89% | 5 | 50 |
34 | +------------------------+----------------+--------+-----+------+
35 | | elliptic#EdDSASign | 296.756ops/s | 1.09% | 5 | 50 |
36 | +------------------------+----------------+--------+-----+------+
37 | | elliptic#EdDSAVerify | 67.481ops/s | 2.76% | 5 | 50 |
38 | +------------------------+----------------+--------+-----+------+
39 | ```
40 |
41 |
42 | ## Installation
43 |
44 | You can install this library via Composer:
45 | ```
46 | composer require simplito/elliptic-php
47 | ```
48 |
49 |
50 | ## Implementation details
51 |
52 | ECDSA is using deterministic `k` value generation as per [RFC6979][0]. Most of
53 | the curve operations are performed on non-affine coordinates (either projective
54 | or extended), various windowing techniques are used for different cases.
55 |
56 | NOTE: `curve25519` could not be used for ECDSA, use `ed25519` instead.
57 |
58 | All operations are performed in reduction context using [bn-php][1].
59 |
60 |
61 | ## API
62 |
63 | ### ECDSA
64 |
65 | ```php
66 | genKeyPair();
75 |
76 | // Sign message (can be hex sequence or array)
77 | $msg = 'ab4c3451';
78 | $signature = $key->sign($msg);
79 |
80 | // Export DER encoded signature to hex string
81 | $derSign = $signature->toDER('hex');
82 |
83 | // Verify signature
84 | echo "Verified: " . (($key->verify($msg, $derSign) == TRUE) ? "true" : "false") . "\n";
85 |
86 | // CHECK WITH NO PRIVATE KEY
87 |
88 | // Public key as '04 + x + y'
89 | $pub = "049a1eedae838f2f8ad94597dc4368899ecc751342b464862da80c280d841875ab4607fb6ce14100e71dd7648dd6b417c7872a6ff1ff29195dabd99f15eff023e5";
90 |
91 | // Signature MUST be either:
92 | // 1) hex-string of DER-encoded signature; or
93 | // 2) DER-encoded signature as byte array; or
94 | // 3) object with two hex-string properties (r and s)
95 |
96 | // case 1
97 | $sig = '30450220233f8bab3f5df09e3d02f45914b0b519d2c04d13ac6964495623806a015df1cd022100c0c279c989b79885b3cc0f117643317bc59414bfb581f38e03557b8532f06603';
98 |
99 | // case 2
100 | $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];
101 |
102 | // case 3
103 | $sig = ['r' => '233f8bab3f5df09e3d02f45914b0b519d2c04d13ac6964495623806a015df1cd', 's' => 'c0c279c989b79885b3cc0f117643317bc59414bfb581f38e03557b8532f06603'];
104 |
105 |
106 | // Import public key
107 | $key = $ec->keyFromPublic($pub, 'hex');
108 |
109 | // Verify signature
110 | echo "Verified: " . (($key->verify($msg, $sig) == TRUE) ? "true" : "false") . "\n";
111 | ```
112 |
113 | ### EdDSA
114 |
115 | ```php
116 | keyFromSecret('61233ca4590acd'); // hex string or array of bytes
125 |
126 | // Sign message (can be hex sequence or array)
127 | $msg = 'ab4c3451';
128 | $signature = $key->sign($msg)->toHex();
129 |
130 | // Verify signature
131 | echo "Verified: " . (($key->verify($msg, $signature) == TRUE) ? "true" : "false") . "\n";
132 |
133 | // CHECK WITH NO PRIVATE KEY
134 |
135 | // Import public key
136 | $pub = '2763d01c334250d3e2dda459e5e3f949f667c6bbf0a35012c77ad40b00f0374d';
137 | $key = $ec->keyFromPublic($pub, 'hex');
138 |
139 | // Verify signature
140 | $signature = '93899915C2919181A3D244AAAC032CE78EF76D2FFC0355D4BE2C70F48202EBC5F2BB0541D236182F55B11AC6346B524150695E5DE1FEA570786E1CC1F7999404';
141 | echo "Verified: " . (($key->verify($msg, $signature) == TRUE) ? "true" : "false") . "\n";
142 | ```
143 |
144 | ### ECDH
145 |
146 | ```php
147 | genKeyPair();
154 | $key2 = $ec->genKeyPair();
155 |
156 | $shared1 = $key1->derive($key2->getPublic());
157 | $shared2 = $key2->derive($key1->getPublic());
158 |
159 | echo "Both shared secrets are BN instances\n";
160 | echo $shared1->toString(16) . "\n";
161 | echo $shared2->toString(16) . "\n";
162 | ```
163 |
164 | NOTE: `.derive()` returns a [BN][1] instance.
165 |
166 |
167 | [0]: http://tools.ietf.org/html/rfc6979
168 | [1]: https://github.com/simplito/bn-php
169 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/elliptic-php/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "simplito/elliptic-php",
3 | "description": "Fast elliptic curve cryptography",
4 | "type": "library",
5 | "homepage": "https://github.com/simplito/elliptic-php",
6 | "keywords": ["elliptic", "curve", "cryptography", "ECC",
7 | "ECDH", "ECDSA", "EdDSA",
8 | "secp256k1", "curve25519", "ed25519",
9 | "nistp192", "nistp224", "nistp256", "nistp384", "nistp521"],
10 | "license": "MIT",
11 | "authors": [
12 | {
13 | "name": "Simplito Team",
14 | "email": "s.smyczynski@simplito.com",
15 | "homepage": "https://simplito.com"
16 | }
17 | ],
18 | "require": {
19 | "ext-gmp": "*",
20 | "simplito/bn-php": "~1.1.0"
21 | },
22 | "require-dev": {
23 | "phpunit/phpunit": "*",
24 | "phpbench/phpbench": "@dev"
25 | },
26 | "autoload": {
27 | "psr-4": {
28 | "Elliptic\\": "lib/"
29 | }
30 | },
31 | "scripts": {
32 | "test": "phpunit --verbose"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/elliptic-php/lib/Curve/BaseCurve/Point.php:
--------------------------------------------------------------------------------
1 | curve = $curve;
16 | $this->type = $type;
17 | $this->precomputed = null;
18 | }
19 |
20 | abstract public function eq($other);
21 |
22 | public function validate() {
23 | return $this->curve->validate($this);
24 | }
25 |
26 | public function encodeCompressed($enc) {
27 | return $this->encode($enc, true);
28 | }
29 |
30 | public function encode($enc, $compact = false) {
31 | return Utils::encode($this->_encode($compact), $enc);
32 | }
33 |
34 | protected function _encode($compact)
35 | {
36 | $len = $this->curve->p->byteLength();
37 | $x = $this->getX()->toArray("be", $len);
38 |
39 | if( $compact )
40 | {
41 | array_unshift($x, ($this->getY()->isEven() ? 0x02 : 0x03));
42 | return $x;
43 | }
44 |
45 | return array_merge(array(0x04), $x, $this->getY()->toArray("be", $len));
46 | }
47 |
48 | public function precompute($power = null)
49 | {
50 | if( isset($this->precomputed) )
51 | return $this;
52 |
53 | $this->precomputed = array(
54 | "naf" => $this->_getNAFPoints(8),
55 | "doubles" => $this->_getDoubles(4, $power),
56 | "beta" => $this->_getBeta()
57 | );
58 |
59 | return $this;
60 | }
61 |
62 | protected function _hasDoubles($k)
63 | {
64 | if( !isset($this->precomputed) || !isset($this->precomputed["doubles"]) )
65 | return false;
66 |
67 | return count($this->precomputed["doubles"]["points"]) >= ceil(($k->bitLength() + 1) / $this->precomputed["doubles"]["step"]);
68 | }
69 |
70 | public function _getDoubles($step = null, $power = null)
71 | {
72 | if( isset($this->precomputed) && isset($this->precomputed["doubles"]) )
73 | return $this->precomputed["doubles"];
74 |
75 | $doubles = array( $this );
76 | $acc = $this;
77 | for($i = 0; $i < $power; $i += $step)
78 | {
79 | for($j = 0; $j < $step; $j++)
80 | $acc = $acc->dbl();
81 | array_push($doubles, $acc);
82 | }
83 |
84 | return array(
85 | "step" => $step,
86 | "points" => $doubles
87 | );
88 | }
89 |
90 | public function _getNAFPoints($wnd)
91 | {
92 | if( isset($this->precomputed) && isset($this->precomputed["naf"]) )
93 | return $this->precomputed["naf"];
94 |
95 | $res = array( $this );
96 | $max = (1 << $wnd) - 1;
97 | $dbl = $max === 1 ? null : $this->dbl();
98 | for($i = 1; $i < $max; $i++)
99 | array_push($res, $res[$i - 1]->add($dbl));
100 |
101 | return array(
102 | "wnd" => $wnd,
103 | "points" => $res
104 | );
105 | }
106 |
107 | public function _getBeta() {
108 | return null;
109 | }
110 |
111 | public function dblp($k)
112 | {
113 | $r = $this;
114 | for($i = 0; $i < $k; $i++)
115 | $r = $r->dbl();
116 | return $r;
117 | }
118 | }
119 |
120 | ?>
121 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/elliptic-php/lib/Curve/EdwardsCurve.php:
--------------------------------------------------------------------------------
1 | twisted = ($conf["a"] | 0) != 1;
24 | $this->mOneA = $this->twisted && ($conf["a"] | 0) == -1;
25 | $this->extended = $this->mOneA;
26 | parent::__construct("edward", $conf);
27 |
28 | $this->a = (new BN($conf["a"], 16))->umod($this->red->m);
29 | $this->a = $this->a->toRed($this->red);
30 | $this->c = (new BN($conf["c"], 16))->toRed($this->red);
31 | $this->c2 = $this->c->redSqr();
32 | $this->d = (new BN($conf["d"], 16))->toRed($this->red);
33 | $this->dd = $this->d->redAdd($this->d);
34 | if (assert_options(ASSERT_ACTIVE)) {
35 | assert(!$this->twisted || $this->c->fromRed()->cmpn(1) == 0);
36 | }
37 | $this->oneC = ($conf["c"] | 0) == 1;
38 | }
39 |
40 | public function _mulA($num) {
41 | if ($this->mOneA)
42 | return $num->redNeg();
43 | else
44 | return $this->a->redMul($num);
45 | }
46 |
47 | public function _mulC($num) {
48 | if ($this->oneC)
49 | return $num;
50 | else
51 | return $this->c->redMul($num);
52 | }
53 |
54 | // Just for compatibility with Short curve
55 | public function jpoint($x, $y, $z, $t = null) {
56 | return $this->point($x, $y, $z, $t);
57 | }
58 |
59 | public function pointFromX($x, $odd = false) {
60 | $x = new BN($x, 16);
61 | if (!$x->red)
62 | $x = $x->toRed($this->red);
63 |
64 | $x2 = $x->redSqr();
65 | $rhs = $this->c2->redSub($this->a->redMul($x2));
66 | $lhs = $this->one->redSub($this->c2->redMul($this->d)->redMul($x2));
67 |
68 | $y2 = $rhs->redMul($lhs->redInvm());
69 | $y = $y2->redSqrt();
70 | if ($y->redSqr()->redSub($y2)->cmp($this->zero) != 0)
71 | throw new \Exception('invalid point');
72 |
73 | $isOdd = $y->fromRed()->isOdd();
74 | if ($odd && !$isOdd || !$odd && $isOdd)
75 | $y = $y->redNeg();
76 |
77 | return $this->point($x, $y);
78 | }
79 |
80 | public function pointFromY($y, $odd = false) {
81 | $y = new BN($y, 16);
82 | if (!$y->red)
83 | $y = $y->toRed($this->red);
84 |
85 | // x^2 = (y^2 - 1) / (d y^2 + 1)
86 | $y2 = $y->redSqr();
87 | $lhs = $y2->redSub($this->one);
88 | $rhs = $y2->redMul($this->d)->redAdd($this->one);
89 | $x2 = $lhs->redMul($rhs->redInvm());
90 |
91 | if ($x2->cmp($this->zero) == 0) {
92 | if ($odd)
93 | throw new \Exception('invalid point');
94 | else
95 | return $this->point($this->zero, $y);
96 | }
97 |
98 | $x = $x2->redSqrt();
99 | if ($x->redSqr()->redSub($x2)->cmp($this->zero) != 0)
100 | throw new \Exception('invalid point');
101 |
102 | if ($x->isOdd() != $odd)
103 | $x = $x->redNeg();
104 |
105 | return $this->point($x, $y);
106 | }
107 |
108 | public function validate($point) {
109 | if ($point->isInfinity())
110 | return true;
111 |
112 | // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2)
113 | $point->normalize();
114 |
115 | $x2 = $point->x->redSqr();
116 | $y2 = $point->y->redSqr();
117 | $lhs = $x2->redMul($this->a)->redAdd($y2);
118 | $rhs = $this->c2->redMul($this->one->redAdd($this->d->redMul($x2)->redMul($y2)));
119 |
120 | return $lhs->cmp($rhs) == 0;
121 | }
122 |
123 | public function pointFromJSON($obj) {
124 | return Point::fromJSON($this, $obj);
125 | }
126 |
127 | public function point($x = null, $y = null, $z = null, $t = null) {
128 | return new Point($this, $x, $y, $z, $t);
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/elliptic-php/lib/Curve/MontCurve.php:
--------------------------------------------------------------------------------
1 | a = (new BN($conf["a"], 16))->toRed($this->red);
21 | $this->b = (new BN($conf["b"], 16))->toRed($this->red);
22 | $this->i4 = (new BN(4))->toRed($this->red)->redInvm();
23 | $this->a24 = $this->i4->redMul($this->a->redAdd($this->two));
24 | }
25 |
26 | public function validate($point)
27 | {
28 | $x = $point->normalize()->x;
29 | $x2 = $x->redSqr();
30 | $rhs = $x2->redMul($x)->redAdd($x2->redMul($this->a))->redAdd($x);
31 | $y = $rhs->redSqr();
32 |
33 | return $y->redSqr()->cmp($rhs) ===0;
34 | }
35 |
36 | public function decodePoint($bytes, $enc = false) {
37 | return $this->point(Utils::toArray($bytes, $enc), 1);
38 | }
39 |
40 | public function point($x, $z) {
41 | return new Point($this, $x, $z);
42 | }
43 |
44 | public function pointFromJSON($obj) {
45 | return Point::fromJSON($this, $obj);
46 | }
47 | }
48 |
49 | ?>
50 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/elliptic-php/lib/Curve/MontCurve/Point.php:
--------------------------------------------------------------------------------
1 | x = $this->curve->one;
18 | $this->z = $this->curve->zero;
19 | }
20 | else
21 | {
22 | $this->x = new BN($x, 16);
23 | $this->z = new BN($z, 16);
24 | if( !$this->x->red )
25 | $this->x = $this->x->toRed($this->curve->red);
26 | if( !$this->z->red )
27 | $this->z = $this->z->toRed($this->curve->red);
28 | }
29 | }
30 |
31 | public function precompute($power = null) {
32 | // No-op
33 | }
34 |
35 | protected function _encode($compact) {
36 | return $this->getX()->toArray("be", $this->curve->p->byteLength());
37 | }
38 |
39 | public static function fromJSON($curve, $obj) {
40 | return new Point($curve, $obj[0], isset($obj[1]) ? $obj[1] : $curve->one);
41 | }
42 |
43 | public function inspect()
44 | {
45 | if( $this->isInfinity() )
46 | return "";
47 | return "x->fromRed()->toString(16, 2) .
48 | " z: " . $this->z->fromRed()->toString(16, 2) + ">";
49 | }
50 |
51 | public function isInfinity() {
52 | // XXX This code assumes that zero is always zero in red
53 | return $this->z->isZero();
54 | }
55 |
56 | public function dbl()
57 | {
58 | // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3
59 | // 2M + 2S + 4A
60 |
61 | // A = X1 + Z1
62 | $a = $this->x->redAdd($this->z);
63 | // AA = A^2
64 | $aa = $a->redSqr();
65 | // B = X1 - Z1
66 | $b = $this->x->redSub($this->z);
67 | // BB = B^2
68 | $bb = $b->redSqr();
69 | // C = AA - BB
70 | $c = $aa->redSub($bb);
71 | // X3 = AA * BB
72 | $nx = $aa->redMul($bb);
73 | // Z3 = C * (BB + A24 * C)
74 | $nz = $c->redMul( $bb->redAdd($this->curve->a24->redMul($c)) );
75 | return $this->curve->point($nx, $nz);
76 | }
77 |
78 | public function add($p) {
79 | throw new \Exception('Not supported on Montgomery curve');
80 | }
81 |
82 | public function diffAdd($p, $diff)
83 | {
84 | // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3
85 | // 4M + 2S + 6A
86 |
87 | // A = X2 + Z2
88 | $a = $this->x->redAdd($this->z);
89 | // B = X2 - Z2
90 | $b = $this->x->redSub($this->z);
91 | // C = X3 + Z3
92 | $c = $p->x->redAdd($p->z);
93 | // D = X3 - Z3
94 | $d = $p->x->redSub($p->z);
95 | // DA = D * A
96 | $da = $d->redMul($a);
97 | // CB = C * B
98 | $cb = $c->redMul($b);
99 | // X5 = Z1 * (DA + CB)^2
100 | $nx = $diff->z->redMul($da->redAdd($cb)->redSqr());
101 | // Z5 = X1 * (DA - CB)^2
102 | $nz = $diff->x->redMul($da->redSub($cb)->redSqr());
103 |
104 | return $this->curve->point($nx, $nz);
105 | }
106 |
107 | public function mul($k)
108 | {
109 | $t = $k->_clone();
110 | $a = $this; // (N / 2) * Q + Q
111 | $b = $this->curve->point(null, null); // (N / 2) * Q
112 | $c = $this; // Q
113 |
114 | $bits = array();
115 | while( !$t->isZero() )
116 | {
117 | // TODO: Maybe it is faster to use toString(2)?
118 | array_push($bits, $t->andln(1));
119 | $t->iushrn(1);
120 | }
121 |
122 | for($i = count($bits) - 1; $i >= 0; $i--)
123 | {
124 | if( $bits[$i] === 0 )
125 | {
126 | // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q
127 | $a = $a->diffAdd($b, $c);
128 | // N * Q = 2 * ((N / 2) * Q + Q))
129 | $b = $b->dbl();
130 | }
131 | else
132 | {
133 | // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q)
134 | $b = $a->diffAdd($b, $c);
135 | // N * Q + Q = 2 * ((N / 2) * Q + Q)
136 | $a = $a->dbl();
137 | }
138 | }
139 |
140 | return $b;
141 | }
142 |
143 | public function eq($other) {
144 | return $this->getX()->cmp($other->getX()) === 0;
145 | }
146 |
147 | public function normalize()
148 | {
149 | $this->x = $this->x->redMul($this->z->redInvm());
150 | $this->z = $this->curve->one;
151 | return $this;
152 | }
153 |
154 | public function getX() {
155 | $this->normalize();
156 | return $this->x->fromRed();
157 | }
158 | }
159 |
160 | ?>
161 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/elliptic-php/lib/Curve/PresetCurve.php:
--------------------------------------------------------------------------------
1 | curve = new ShortCurve($options);
16 | elseif ( $options["type"] === "edwards" )
17 | $this->curve = new EdwardsCurve($options);
18 | else
19 | $this->curve = new MontCurve($options);
20 |
21 | $this->g = $this->curve->g;
22 | $this->n = $this->curve->n;
23 | $this->hash = isset($options["hash"]) ? $options["hash"] : null;
24 | }
25 | }
26 |
27 | ?>
28 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/elliptic-php/lib/EC.php:
--------------------------------------------------------------------------------
1 | $options);
27 |
28 | $this->curve = $options["curve"]->curve;
29 | $this->n = $this->curve->n;
30 | $this->nh = $this->n->ushrn(1);
31 |
32 | //Point on curve
33 | $this->g = $options["curve"]->g;
34 | $this->g->precompute($options["curve"]->n->bitLength() + 1);
35 |
36 | //Hash for function for DRBG
37 | if( isset($options["hash"]) )
38 | $this->hash = $options["hash"];
39 | else
40 | $this->hash = $options["curve"]->hash;
41 | }
42 |
43 | public function keyPair($options) {
44 | return new KeyPair($this, $options);
45 | }
46 |
47 | public function keyFromPrivate($priv, $enc = false) {
48 | return KeyPair::fromPrivate($this, $priv, $enc);
49 | }
50 |
51 | public function keyFromPublic($pub, $enc = false) {
52 | return KeyPair::fromPublic($this, $pub, $enc);
53 | }
54 |
55 | public function genKeyPair($options = null)
56 | {
57 | // Instantiate HmacDRBG
58 | $drbg = new HmacDRBG(array(
59 | "hash" => $this->hash,
60 | "pers" => isset($options["pers"]) ? $options["pers"] : "",
61 | "entropy" => isset($options["entropy"]) ? $options["entropy"] : Utils::randBytes($this->hash["hmacStrength"]),
62 | "nonce" => $this->n->toArray()
63 | ));
64 |
65 | $bytes = $this->n->byteLength();
66 | $ns2 = $this->n->sub(new BN(2));
67 | while(true)
68 | {
69 | $priv = new BN($drbg->generate($bytes));
70 | if( $priv->cmp($ns2) > 0 )
71 | continue;
72 |
73 | $priv->iaddn(1);
74 | return $this->keyFromPrivate($priv);
75 | }
76 | }
77 |
78 | private function _truncateToN($msg, $truncOnly = false)
79 | {
80 | $delta = intval(($msg->byteLength() * 8) - $this->n->bitLength());
81 | if( $delta > 0 ) {
82 | $msg = $msg->ushrn($delta);
83 | }
84 | if( $truncOnly || $msg->cmp($this->n) < 0 )
85 | return $msg;
86 |
87 | return $msg->sub($this->n);
88 | }
89 |
90 | public function sign($msg, $key, $enc = null, $options = null)
91 | {
92 | if( !is_string($enc) )
93 | {
94 | $options = $enc;
95 | $enc = null;
96 | }
97 |
98 | $key = $this->keyFromPrivate($key, $enc);
99 | $msg = $this->_truncateToN(new BN($msg, 16));
100 |
101 | // Zero-extend key to provide enough entropy
102 | $bytes = $this->n->byteLength();
103 | $bkey = $key->getPrivate()->toArray("be", $bytes);
104 |
105 | // Zero-extend nonce to have the same byte size as N
106 | $nonce = $msg->toArray("be", $bytes);
107 |
108 | $kFunc = null;
109 | if( isset($options["k"]) )
110 | $kFunc = $options["k"];
111 | else
112 | {
113 | // Instatiate HmacDRBG
114 | $drbg = new HmacDRBG(array(
115 | "hash" => $this->hash,
116 | "entropy" => $bkey,
117 | "nonce" => $nonce,
118 | "pers" => isset($options["pers"]) ? $options["pers"] : "",
119 | "persEnc" => isset($options["persEnc"]) ? $options["persEnc"] : false
120 | ));
121 |
122 | $kFunc = function($iter) use ($drbg, $bytes) {
123 | return new BN($drbg->generate($bytes));
124 | };
125 | }
126 |
127 | // Number of bytes to generate
128 | $ns1 = $this->n->sub(new BN(1));
129 |
130 | $canonical = isset($options["canonical"]) ? $options["canonical"] : false;
131 | for($iter = 0; true; $iter++)
132 | {
133 | $k = $kFunc($iter);
134 | $k = $this->_truncateToN($k, true);
135 |
136 | if( $k->cmpn(1) <= 0 || $k->cmp($ns1) >= 0 )
137 | continue;
138 |
139 | $kp = $this->g->mul($k);
140 | if( $kp->isInfinity() )
141 | continue;
142 |
143 | $kpX = $kp->getX();
144 | $r = $kpX->umod($this->n);
145 | if( $r->isZero() )
146 | continue;
147 |
148 | $s = $k->invm($this->n)->mul($r->mul($key->getPrivate())->iadd($msg));
149 | $s = $s->umod($this->n);
150 | if( $s->isZero() )
151 | continue;
152 |
153 | $recoveryParam = ($kp->getY()->isOdd() ? 1 : 0) | ($kpX->cmp($r) !== 0 ? 2 : 0);
154 |
155 | // Use complement of `s`, if it is > `n / 2`
156 | if( $canonical && $s->cmp($this->nh) > 0 )
157 | {
158 | $s = $this->n->sub($s);
159 | $recoveryParam ^= 1;
160 | }
161 |
162 | return new Signature(array(
163 | "r" => $r,
164 | "s" => $s,
165 | "recoveryParam" => $recoveryParam
166 | ));
167 | }
168 | }
169 |
170 | public function verify($msg, $signature, $key, $enc = false)
171 | {
172 | $msg = $this->_truncateToN(new BN($msg, 16));
173 | $key = $this->keyFromPublic($key, $enc);
174 | $signature = new Signature($signature, "hex");
175 |
176 | // Perform primitive values validation
177 | $r = $signature->r;
178 | $s = $signature->s;
179 |
180 | if( $r->cmpn(1) < 0 || $r->cmp($this->n) >= 0 )
181 | return false;
182 | if( $s->cmpn(1) < 0 || $s->cmp($this->n) >= 0 )
183 | return false;
184 |
185 | // Validate signature
186 | $sinv = $s->invm($this->n);
187 | $u1 = $sinv->mul($msg)->umod($this->n);
188 | $u2 = $sinv->mul($r)->umod($this->n);
189 |
190 | if( !$this->curve->_maxwellTrick )
191 | {
192 | $p = $this->g->mulAdd($u1, $key->getPublic(), $u2);
193 | if( $p->isInfinity() )
194 | return false;
195 |
196 | return $p->getX()->umod($this->n)->cmp($r) === 0;
197 | }
198 |
199 | // NOTE: Greg Maxwell's trick, inspired by:
200 | // https://git.io/vad3K
201 |
202 | $p = $this->g->jmulAdd($u1, $key->getPublic(), $u2);
203 | if( $p->isInfinity() )
204 | return false;
205 |
206 | // Compare `p.x` of Jacobian point with `r`,
207 | // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the
208 | // inverse of `p.z^2`
209 | return $p->eqXToP($r);
210 | }
211 |
212 | public function recoverPubKey($msg, $signature, $j, $enc = false)
213 | {
214 | assert((3 & $j) === $j); //, "The recovery param is more than two bits");
215 | $signature = new Signature($signature, $enc);
216 |
217 | $e = new BN($msg, 16);
218 | $r = $signature->r;
219 | $s = $signature->s;
220 |
221 | // A set LSB signifies that the y-coordinate is odd
222 | $isYOdd = ($j & 1) == 1;
223 | $isSecondKey = $j >> 1;
224 |
225 | if ($r->cmp($this->curve->p->umod($this->curve->n)) >= 0 && $isSecondKey)
226 | throw new \Exception("Unable to find second key candinate");
227 |
228 | // 1.1. Let x = r + jn.
229 | if( $isSecondKey )
230 | $r = $this->curve->pointFromX($r->add($this->curve->n), $isYOdd);
231 | else
232 | $r = $this->curve->pointFromX($r, $isYOdd);
233 |
234 | $eNeg = $this->n->sub($e);
235 |
236 | // 1.6.1 Compute Q = r^-1 (sR - eG)
237 | // Q = r^-1 (sR + -eG)
238 | $rInv = $signature->r->invm($this->n);
239 | return $this->g->mulAdd($eNeg, $r, $s)->mul($rInv);
240 | }
241 |
242 | public function getKeyRecoveryParam($e, $signature, $Q, $enc = false)
243 | {
244 | $signature = new Signature($signature, $enc);
245 | if( $signature->recoveryParam != null )
246 | return $signature->recoveryParam;
247 |
248 | for($i = 0; $i < 4; $i++)
249 | {
250 | $Qprime = null;
251 | try {
252 | $Qprime = $this->recoverPubKey($e, $signature, $i);
253 | }
254 | catch(\Exception $e) {
255 | continue;
256 | }
257 |
258 | if( $Qprime->eq($Q))
259 | return $i;
260 | }
261 | throw new \Exception("Unable to find valid recovery factor");
262 | }
263 | }
264 |
265 | ?>
266 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/elliptic-php/lib/EC/KeyPair.php:
--------------------------------------------------------------------------------
1 | ec = $ec;
16 |
17 | $this->priv = null;
18 | $this->pub = null;
19 |
20 | if( isset($options["priv"]) )
21 | $this->_importPrivate($options["priv"], $options["privEnc"]);
22 |
23 | if( isset($options["pub"]) )
24 | $this->_importPublic($options["pub"], $options["pubEnc"]);
25 | }
26 |
27 | public static function fromPublic($ec, $pub, $enc)
28 | {
29 | if( $pub instanceof KeyPair )
30 | return $pub;
31 |
32 | return new KeyPair($ec, array(
33 | "pub" => $pub,
34 | "pubEnc" => $enc
35 | ));
36 | }
37 |
38 | public static function fromPrivate($ec, $priv, $enc)
39 | {
40 | if( $priv instanceof KeyPair )
41 | return $priv;
42 |
43 | return new KeyPair($ec, array(
44 | "priv" => $priv,
45 | "privEnc" => $enc
46 | ));
47 | }
48 |
49 | public function validate()
50 | {
51 | $pub = $this->getPublic();
52 |
53 | if( $pub->isInfinity() )
54 | return array( "result" => false, "reason" => "Invalid public key" );
55 |
56 | if( !$pub->validate() )
57 | return array( "result" => false, "reason" => "Public key is not a point" );
58 |
59 | if( !$pub->mul($this->ec->curve->n)->isInfinity() )
60 | return array( "result" => false, "reason" => "Public key * N != O" );
61 |
62 | return array( "result" => true, "reason" => null );
63 | }
64 |
65 | public function getPublic($compact = false, $enc = "")
66 | {
67 | //compact is optional argument
68 | if( is_string($compact) )
69 | {
70 | $enc = $compact;
71 | $compact = false;
72 | }
73 |
74 | if( $this->pub === null )
75 | $this->pub = $this->ec->g->mul($this->priv);
76 |
77 | if( !$enc )
78 | return $this->pub;
79 |
80 | return $this->pub->encode($enc, $compact);
81 | }
82 |
83 | public function getPrivate($enc = false)
84 | {
85 | if( $enc === "hex" )
86 | return $this->priv->toString(16, 2);
87 |
88 | return $this->priv;
89 | }
90 |
91 | private function _importPrivate($key, $enc)
92 | {
93 | $this->priv = new BN($key, (isset($enc) && $enc) ? $enc : 16);
94 |
95 | // Ensure that the priv won't be bigger than n, otherwise we may fail
96 | // in fixed multiplication method
97 | $this->priv = $this->priv->umod($this->ec->curve->n);
98 | }
99 |
100 | private function _importPublic($key, $enc)
101 | {
102 | $x = $y = null;
103 | if ( is_object($key) ) {
104 | $x = $key->x;
105 | $y = $key->y;
106 | } elseif ( is_array($key) ) {
107 | $x = isset($key["x"]) ? $key["x"] : null;
108 | $y = isset($key["y"]) ? $key["y"] : null;
109 | }
110 |
111 | if( $x != null || $y != null )
112 | $this->pub = $this->ec->curve->point($x, $y);
113 | else
114 | $this->pub = $this->ec->curve->decodePoint($key, $enc);
115 | }
116 |
117 | //ECDH
118 | public function derive($pub) {
119 | return $pub->mul($this->priv)->getX();
120 | }
121 |
122 | //ECDSA
123 | public function sign($msg, $enc = false, $options = false) {
124 | return $this->ec->sign($msg, $this, $enc, $options);
125 | }
126 |
127 | public function verify($msg, $signature) {
128 | return $this->ec->verify($msg, $signature, $this);
129 | }
130 |
131 | public function inspect() {
132 | return "priv) ? $this->priv->toString(16, 2) : "") .
133 | " pub: " . (isset($this->pub) ? $this->pub->inspect() : "") . ">";
134 | }
135 |
136 | public function __debugInfo() {
137 | return ["priv" => $this->priv, "pub" => $this->pub];
138 | }
139 | }
140 |
141 | ?>
142 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/elliptic-php/lib/EC/Signature.php:
--------------------------------------------------------------------------------
1 | r = $options->r;
18 | $this->s = $options->s;
19 | $this->recoveryParam = $options->recoveryParam;
20 | return;
21 | }
22 |
23 | if (isset($options['r'])) {
24 | assert(isset($options["r"]) && isset($options["s"])); //, "Signature without r or s");
25 | $this->r = new BN($options["r"], 16);
26 | $this->s = new BN($options["s"], 16);
27 |
28 | if( isset($options["recoveryParam"]) )
29 | $this->recoveryParam = $options["recoveryParam"];
30 | else
31 | $this->recoveryParam = null;
32 | return;
33 | }
34 |
35 | if (!$this->_importDER($options, $enc))
36 | throw new \Exception('Unknown signature format');
37 |
38 | }
39 |
40 | private static function getLength($buf, &$pos)
41 | {
42 | $initial = $buf[$pos++];
43 | if( !($initial & 0x80) )
44 | return $initial;
45 |
46 | $octetLen = $initial & 0xf;
47 | $val = 0;
48 | for($i = 0; $i < $octetLen; $i++)
49 | {
50 | $val = $val << 8;
51 | $val = $val | $buf[$pos];
52 | $pos++;
53 | }
54 | return $val;
55 | }
56 |
57 | private static function rmPadding(&$buf)
58 | {
59 | $i = 0;
60 | $len = count($buf) - 1;
61 | while($i < $len && !$buf[$i] && !($buf[$i+1] & 0x80) )
62 | $i++;
63 |
64 | if( $i === 0 )
65 | return $buf;
66 |
67 | return array_slice($buf, $i);
68 | }
69 |
70 | private function _importDER($data, $enc)
71 | {
72 | $data = Utils::toArray($data, $enc);
73 | $dataLen = count($data);
74 | $place = 0;
75 |
76 | if( $data[$place++] !== 0x30)
77 | return false;
78 |
79 | $len = self::getLength($data, $place);
80 | if( ($len + $place) !== $dataLen )
81 | return false;
82 |
83 | if( $data[$place++] !== 0x02 )
84 | return false;
85 |
86 | $rlen = self::getLength($data, $place);
87 | $r = array_slice($data, $place, $rlen);
88 | $place += $rlen;
89 |
90 | if( $data[$place++] !== 0x02 )
91 | return false;
92 |
93 | $slen = self::getLength($data, $place);
94 | if( $dataLen !== $slen + $place )
95 | return false;
96 | $s = array_slice($data, $place, $slen);
97 |
98 | if( $r[0] === 0 && ($r[1] & 0x80 ) )
99 | $r = array_slice($r, 1);
100 | if( $s[0] === 0 && ($s[1] & 0x80 ) )
101 | $s = array_slice($s, 1);
102 |
103 | $this->r = new BN($r);
104 | $this->s = new BN($s);
105 | $this->recoveryParam = null;
106 |
107 | return true;
108 | }
109 |
110 | private static function constructLength(&$arr, $len)
111 | {
112 | if( $len < 0x80 )
113 | {
114 | array_push($arr, $len);
115 | return;
116 | }
117 |
118 | $octets = 1 + (log($len) / M_LN2 >> 3);
119 | array_push($arr, $octets | 0x80);
120 | while(--$octets)
121 | array_push($arr, ($len >> ($octets << 3)) & 0xff);
122 | array_push($arr, $len);
123 | }
124 |
125 | public function toDER($enc = false)
126 | {
127 | $r = $this->r->toArray();
128 | $s = $this->s->toArray();
129 |
130 | //Pad values
131 | if( $r[0] & 0x80 )
132 | array_unshift($r, 0);
133 | if( $s[0] & 0x80 )
134 | array_unshift($s, 0);
135 |
136 | $r = self::rmPadding($r);
137 | $s = self::rmPadding($s);
138 |
139 | while(!$s[0] && !($s[1] & 0x80))
140 | array_slice($s, 1);
141 |
142 | $arr = array(0x02);
143 | self::constructLength($arr, count($r));
144 | $arr = array_merge($arr, $r, array(0x02));
145 | self::constructLength($arr, count($s));
146 | $backHalf = array_merge($arr, $s);
147 | $res = array(0x30);
148 | self::constructLength($res, count($backHalf));
149 | $res = array_merge($res, $backHalf);
150 |
151 | return Utils::encode($res, $enc);
152 | }
153 | }
154 |
155 | ?>
156 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/elliptic-php/lib/EdDSA.php:
--------------------------------------------------------------------------------
1 | curve;
19 | $this->curve = $curve;
20 | $this->g = $curve->g;
21 | $this->g->precompute($curve->n->bitLength() + 1);
22 |
23 | $this->pointClass = get_class($curve->point());
24 | $this->encodingLength = intval(ceil($curve->n->bitLength() / 8));
25 | // TODO: !!!
26 | $this->hash = [ "algo" => "sha512" ];
27 | }
28 |
29 | /**
30 | * @param {Array|String} message - message bytes
31 | * @param {Array|String|KeyPair} secret - secret bytes or a keypair
32 | * @returns {Signature} - signature
33 | */
34 | public function sign($message, $secret) {
35 | $message = Utils::parseBytes($message);
36 | $key = $this->keyFromSecret($secret);
37 | $r = $this->hashInt($key->messagePrefix(), $message);
38 | $R = $this->g->mul($r);
39 | $Rencoded = $this->encodePoint($R);
40 | $s_ = $this->hashInt($Rencoded, $key->pubBytes(), $message)
41 | ->mul($key->priv());
42 | $S = $r->add($s_)->umod($this->curve->n);
43 | return $this->makeSignature([ "R" => $R, "S" => $S, "Rencoded" => $Rencoded ]);
44 | }
45 |
46 | /**
47 | * @param {Array} message - message bytes
48 | * @param {Array|String|Signature} sig - sig bytes
49 | * @param {Array|String|Point|KeyPair} pub - public key
50 | * @returns {Boolean} - true if public key matches sig of message
51 | */
52 | public function verify($message, $sig, $pub) {
53 | $message = Utils::parseBytes($message);
54 | $sig = $this->makeSignature($sig);
55 | $key = $this->keyFromPublic($pub);
56 | $h = $this->hashInt($sig->Rencoded(), $key->pubBytes(), $message);
57 | $SG = $this->g->mul($sig->S());
58 | $RplusAh = $sig->R()->add($key->pub()->mul($h));
59 | return $RplusAh->eq($SG);
60 | }
61 |
62 | public function hashInt() {
63 | $arguments = func_get_args();
64 | // TODO: refactor when hash-php is ready
65 | $hash = hash_init($this->hash["algo"]);
66 | for ($i = 0; $i < count($arguments); $i++)
67 | hash_update($hash, Utils::toBin($arguments[$i]));
68 | return Utils::intFromLE(hash_final($hash))->umod($this->curve->n);
69 | }
70 |
71 | public function keyFromPublic($pub) {
72 | return KeyPair::fromPublic($this, $pub);
73 | }
74 |
75 | public function keyFromSecret($secret) {
76 | return KeyPair::fromSecret($this, $secret);
77 | }
78 |
79 | public function makeSignature($sig) {
80 | if ($sig instanceof Signature)
81 | return $sig;
82 | return new Signature($this, $sig);
83 | }
84 |
85 | /**
86 | * * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2
87 | *
88 | * EdDSA defines methods for encoding and decoding points and integers. These are
89 | * helper convenience methods, that pass along to utility functions implied
90 | * parameters.
91 | *
92 | */
93 | public function encodePoint($point) {
94 | $enc = $point->getY()->toArray('le', $this->encodingLength);
95 | $enc[$this->encodingLength - 1] |= $point->getX()->isOdd() ? 0x80 : 0;
96 | return $enc;
97 | }
98 |
99 | public function decodePoint($bytes) {
100 | $bytes = Utils::parseBytes($bytes);
101 |
102 | $lastIx = count($bytes) - 1;
103 | $normed = $bytes;
104 | $normed[$lastIx] = $bytes[$lastIx] & ~0x80;
105 | $xIsOdd = ($bytes[$lastIx] & 0x80) !== 0;
106 |
107 | $y = Utils::intFromLE($normed);
108 | return $this->curve->pointFromY($y, $xIsOdd);
109 | }
110 |
111 | public function encodeInt($num) {
112 | return $num->toArray('le', $this->encodingLength);
113 | }
114 |
115 | public function decodeInt($bytes) {
116 | return Utils::intFromLE($bytes);
117 | }
118 |
119 | public function isPoint($val) {
120 | return is_a($val, $this->pointClass);
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/elliptic-php/lib/EdDSA/KeyPair.php:
--------------------------------------------------------------------------------
1 | } [params.secret] - secret seed bytes
14 | * @param {Point} [params.pub] - public key point (aka `A` in eddsa terms)
15 | * @param {Array} [params.pub] - public key point encoded as bytes
16 | *
17 | */
18 | function __construct($eddsa, $params) {
19 | $this->eddsa = $eddsa;
20 | $this->_secret = isset($params["secret"]) ? Utils::parseBytes($params["secret"]) : null;
21 | if (!isset($params["pub"])) {
22 | $this->_pub = null;
23 | $this->_pubBytes = null;
24 | return;
25 | }
26 | if ($eddsa->isPoint($params["pub"]))
27 | $this->_pub = $params["pub"];
28 | else
29 | $this->_pubBytes = Utils::parseBytes($params["pub"]);
30 | }
31 |
32 | public static function fromPublic($eddsa, $pub) {
33 | if ($pub instanceof KeyPair)
34 | return $pub;
35 | return new KeyPair($eddsa, [ "pub" => $pub ]);
36 | }
37 |
38 | public static function fromSecret($eddsa, $secret) {
39 | if ($secret instanceof KeyPair)
40 | return $secret;
41 | return new KeyPair($eddsa, [ "secret" => $secret ]);
42 | }
43 |
44 | private $_secret;
45 | public function secret() {
46 | return $this->_secret;
47 | }
48 |
49 | public function pubBytes() {
50 | if (!$this->_pubBytes)
51 | $this->_pubBytes = $this->eddsa->encodePoint($this->pub());
52 | return $this->_pubBytes;
53 | }
54 |
55 | private $_pub;
56 | public function pub() {
57 | if (!$this->_pub) {
58 | if ($this->_pubBytes)
59 | $this->_pub = $this->eddsa->decodePoint($this->_pubBytes);
60 | else
61 | $this->_pub = $this->eddsa->g->mul($this->priv());
62 | }
63 | return $this->_pub;
64 | }
65 |
66 | private $_privBytes;
67 | public function privBytes() {
68 | if (!$this->_privBytes) {
69 | $eddsa = $this->eddsa;
70 | $hash = $this->hash();
71 | $lastIx = $eddsa->encodingLength - 1;
72 |
73 | $a = array_slice($hash, 0, $eddsa->encodingLength);
74 | $a[0] &= 248;
75 | $a[$lastIx] &= 127;
76 | $a[$lastIx] |= 64;
77 | $this->_privBytes = $a;
78 | }
79 | return $this->_privBytes;
80 | }
81 |
82 | private $_priv;
83 | public function priv() {
84 | if (!$this->_priv) {
85 | $this->_priv = $this->eddsa->decodeInt($this->privBytes());
86 | }
87 | return $this->_priv;
88 | }
89 |
90 | private $_hash;
91 | public function hash() {
92 | if (!$this->_hash) {
93 | // TODO: !!!
94 | $hash = hash_init('sha512');
95 | hash_update($hash, Utils::toBin($this->secret()));
96 | $this->_hash = Utils::toArray( hash_final($hash), 'hex' );
97 | }
98 | return $this->_hash;
99 | }
100 |
101 | private $_messagePrefix;
102 | public function messagePrefix() {
103 | if (!$this->_messagePrefix) {
104 | $this->_messagePrefix = array_slice($this->hash(), $this->eddsa->encodingLength);
105 | }
106 | return $this->_messagePrefix;
107 | }
108 |
109 | public function sign($message) {
110 | assert($this->_secret); //, 'KeyPair can only verify');
111 | return $this->eddsa->sign($message, $this);
112 | }
113 |
114 | public function verify($message, $sig) {
115 | return $this->eddsa->verify($message, $sig, $this);
116 | }
117 |
118 | public function getSecret($enc = false) {
119 | assert($this->_secret); //, 'KeyPair is public only');
120 | return Utils::encode($this->secret(), $enc);
121 | }
122 |
123 | public function getPublic($enc = false) {
124 | return Utils::encode($this->pubBytes(), $enc);
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/elliptic-php/lib/EdDSA/Signature.php:
--------------------------------------------------------------------------------
1 | |Object} sig -
14 | * @param {Array|Point} [sig.R] - R point as Point or bytes
15 | * @param {Array|bn} [sig.S] - S scalar as bn or bytes
16 | * @param {Array} [sig.Rencoded] - R point encoded
17 | * @param {Array} [sig.Sencoded] - S scalar encoded
18 | */
19 | function __construct($eddsa, $sig) {
20 | $this->eddsa = $eddsa;
21 |
22 | if (is_string($sig))
23 | $sig = Utils::parseBytes($sig);
24 |
25 | if (is_array($sig) && !isset($sig["R"])) {
26 | $sig = [
27 | "R" => array_slice($sig, 0, $eddsa->encodingLength),
28 | "S" => array_slice($sig, $eddsa->encodingLength)
29 | ];
30 | }
31 |
32 | assert($sig["R"] && $sig["S"]); //, 'Signature without R or S');
33 |
34 | if ($eddsa->isPoint($sig["R"]))
35 | $this->_R = $sig["R"];
36 | if ($sig["S"] instanceof BN)
37 | $this->_S = $sig["S"];
38 |
39 | $this->_Rencoded = is_array($sig["R"]) ? $sig["R"] : (isset($sig["Rencoded"]) ?$sig["Rencoded"] : null);
40 | $this->_Sencoded = is_array($sig["S"]) ? $sig["S"] : (isset($sig["Sencoded"]) ?$sig["Sencoded"] : null);
41 | }
42 |
43 | private $_S;
44 | public function S() {
45 | if (!$this->_S) {
46 | $this->_S = $this->eddsa->decodeInt($this->Sencoded());
47 | }
48 | return $this->_S;
49 | }
50 |
51 | private $_R;
52 | public function R() {
53 | if (!$this->_R) {
54 | $this->_R = $this->eddsa->decodePoint($this->Rencoded());
55 | }
56 | return $this->_R;
57 | }
58 |
59 | private $_Rencoded;
60 | public function Rencoded() {
61 | if (!$this->_Rencoded) {
62 | $this->_Rencoded = $this->eddsa->encodePoint($this->R());
63 | }
64 | return $this->_Rencoded;
65 | }
66 |
67 | private $_Sencoded;
68 | public function Sencoded() {
69 | if (!$this->_Sencoded) {
70 | $this->_Sencoded = $this->eddsa->encodeInt($this->S());
71 | }
72 | return $this->_Sencoded;
73 | }
74 |
75 | public function toBytes() {
76 | return array_merge($this->Rencoded(), $this->Sencoded());
77 | }
78 |
79 | public function toHex() {
80 | return strtoupper(Utils::encode($this->toBytes(), 'hex'));
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/elliptic-php/lib/HmacDRBG.php:
--------------------------------------------------------------------------------
1 | hash = $options["hash"];
32 | $this->predResist = $options["predResist"];
33 |
34 | $this->outLen = $this->hash["outSize"];
35 | $this->minEntropy = $options["minEntropy"] ?: $this->hash["hmacStrength"];
36 |
37 | $this->reseed = null;
38 | $this->reseedInterval = null;
39 | $this->K = null;
40 | $this->V = null;
41 |
42 | $entropy = Utils::toBin($options["entropy"], $options["entropyEnc"]);
43 | $nonce = Utils::toBin($options["nonce"], $options["nonceEnc"]);
44 | $pers = Utils::toBin($options["pers"], $options["persEnc"]);
45 |
46 | if (assert_options(ASSERT_ACTIVE)) {
47 | assert(strlen($entropy) >= ($this->minEntropy / 8));
48 | }
49 | $this->_init($entropy, $nonce, $pers);
50 | }
51 |
52 | private function _init($entropy, $nonce, $pers)
53 | {
54 | $seed = $entropy . $nonce . $pers;
55 |
56 | $this->K = str_repeat(chr(0x00), $this->outLen / 8);
57 | $this->V = str_repeat(chr(0x01), $this->outLen / 8);
58 |
59 | $this->_update($seed);
60 | $this->reseed = 1;
61 | $this->reseedInterval = 0x1000000000000; // 2^48
62 | }
63 |
64 | private function _hmac()
65 | {
66 | return hash_init($this->hash["algo"], HASH_HMAC, $this->K);
67 | }
68 |
69 | private function _update($seed = false)
70 | {
71 | $kmac = $this->_hmac();
72 | hash_update($kmac, $this->V);
73 | hash_update($kmac, chr(0x00));
74 |
75 | if( $seed )
76 | hash_update($kmac, $seed);
77 | $this->K = hash_final($kmac, true);
78 |
79 | $kmac = $this->_hmac();
80 | hash_update($kmac, $this->V);
81 | $this->V = hash_final($kmac, true);
82 |
83 | if(!$seed)
84 | return;
85 |
86 | $kmac = $this->_hmac();
87 | hash_update($kmac, $this->V);
88 | hash_update($kmac, chr(0x01));
89 | hash_update($kmac, $seed);
90 | $this->K = hash_final($kmac, true);
91 |
92 | $kmac = $this->_hmac();
93 | hash_update($kmac, $this->V);
94 | $this->V = hash_final($kmac, true);
95 | }
96 |
97 | // TODO: reseed()
98 |
99 | public function generate($len, $enc = null, $add = null, $addEnc = null)
100 | {
101 | if ($this->reseed > $this->reseedInterval)
102 | throw new \Exception("Reseed is required");
103 |
104 | // Optional encoding
105 | if( !is_string($enc) )
106 | {
107 | $addEnc = $enc;
108 | $add = $enc;
109 | $enc = null;
110 | }
111 |
112 | // Optional additional data
113 | if( $add != null ) {
114 | $add = Utils::toBin($add, $addEnc);
115 | $this->_update($add);
116 | }
117 |
118 | $temp = "";
119 | while( strlen($temp) < $len )
120 | {
121 | $hmac = $this->_hmac();
122 | hash_update($hmac, $this->V);
123 | $this->V = hash_final($hmac, true);
124 | $temp .= $this->V;
125 | }
126 |
127 | $res = substr($temp, 0, $len);
128 | $this->_update($add);
129 | $this->reseed++;
130 |
131 | return Utils::encode(Utils::toArray($res), $enc);
132 | }
133 | }
134 |
135 | ?>
136 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/simplito/elliptic-php/lib/Utils.php:
--------------------------------------------------------------------------------
1 | cmpn(1) >= 0 )
68 | {
69 | if( !$k->isOdd() )
70 | array_push($naf, 0);
71 | else
72 | {
73 | $mod = $k->andln($ws - 1);
74 | $z = $mod;
75 | if( $mod > (($ws >> 1) - 1))
76 | $z = ($ws >> 1) - $mod;
77 | $k->isubn($z);
78 | array_push($naf, $z);
79 | }
80 |
81 | // Optimization, shift by word if possible
82 | $shift = (!$k->isZero() && $k->andln($ws - 1) === 0) ? ($w + 1) : 1;
83 | for($i = 1; $i < $shift; $i++)
84 | array_push($naf, 0);
85 | $k->iushrn($shift);
86 | }
87 |
88 | return $naf;
89 | }
90 |
91 | // Represent k1, k2 in a Joint Sparse Form
92 | public static function getJSF($k1, $k2)
93 | {
94 | $jsf = array( array(), array() );
95 | $k1 = $k1->_clone();
96 | $k2 = $k2->_clone();
97 | $d1 = 0;
98 | $d2 = 0;
99 |
100 | while( $k1->cmpn(-$d1) > 0 || $k2->cmpn(-$d2) > 0 )
101 | {
102 | // First phase
103 | $m14 = ($k1->andln(3) + $d1) & 3;
104 | $m24 = ($k2->andln(3) + $d2) & 3;
105 | if( $m14 === 3 )
106 | $m14 = -1;
107 | if( $m24 === 3 )
108 | $m24 = -1;
109 |
110 | $u1 = 0;
111 | if( ($m14 & 1) !== 0 )
112 | {
113 | $m8 = ($k1->andln(7) + $d1) & 7;
114 | $u1 = ( ($m8 === 3 || $m8 === 5) && $m24 === 2 ) ? -$m14 : $m14;
115 | }
116 | array_push($jsf[0], $u1);
117 |
118 | $u2 = 0;
119 | if( ($m24 & 1) !== 0 )
120 | {
121 | $m8 = ($k2->andln(7) + $d2) & 7;
122 | $u2 = ( ($m8 === 3 || $m8 === 5) && $m14 === 2 ) ? -$m24 : $m24;
123 | }
124 | array_push($jsf[1], $u2);
125 |
126 | // Second phase
127 | if( (2 * $d1) === ($u1 + 1) )
128 | $d1 = 1 - $d1;
129 | if( (2 * $d2) === ($u2 + 1) )
130 | $d2 = 1 - $d2;
131 | $k1->iushrn(1);
132 | $k2->iushrn(1);
133 | }
134 |
135 | return $jsf;
136 | }
137 |
138 | public static function intFromLE($bytes) {
139 | return new BN($bytes, 'hex', 'le');
140 | }
141 |
142 | public static function parseBytes($bytes) {
143 | if (is_string($bytes))
144 | return self::toArray($bytes, 'hex');
145 | return $bytes;
146 | }
147 |
148 | public static function randBytes($count)
149 | {
150 | $res = "";
151 | for($i = 0; $i < $count; $i++)
152 | $res .= chr(rand(0, 255));
153 | return $res;
154 | }
155 |
156 | public static function optionAssert(&$array, $key, $value = false, $required = false)
157 | {
158 | if( isset($array[$key]) )
159 | return;
160 | if( $required )
161 | throw new Exception("Missing option " . $key);
162 | $array[$key] = $value;
163 | }
164 | }
165 |
166 | ?>
167 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/stephenhill/base58/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "stephenhill/base58",
3 | "description": "Base58 Encoding and Decoding Library for PHP",
4 | "require-dev": {
5 | "phpunit/phpunit": "4.*",
6 | "athletic/athletic": "~0.1"
7 | },
8 | "license": "MIT",
9 | "authors": [
10 | {
11 | "name": "Stephen Hill",
12 | "email": "stephen@gatekiller.co.uk"
13 | }
14 | ],
15 | "config": {
16 | "bin-dir": "bin"
17 | },
18 | "autoload": {
19 | "psr-4": {
20 | "StephenHill\\": "src/",
21 | "StephenHill\\Benchmarks\\": "benchmarks/"
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/stephenhill/base58/contributing.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | I welcome anyone to contribute to this project. All bug reports, feature requests, and pull requests are greatly appriciated.
4 |
5 | To contribute some code, please do the following:
6 |
7 | 1. Fork this repository.
8 | 2. Create a new branch
9 | 3. Commit your changes to this branch.
10 | 4. Make sure your code follows the coding guidelines below.
11 | 5. When your happy with you changes, push this branch to Github.
12 | 6. Create a Pull Request into the master branch.
13 |
14 | ## Coding Guidelines
15 |
16 | Please ensure your pull request adheres to the following:
17 |
18 | * New code should be properly tested, and all tests must pass
19 | * PSR-1: Basic coding standard
20 | * PSR-2: Coding style guide
21 | * PSR-4: Autoloader
22 | * Semantic Versioning 2.0.0
23 |
24 | Thank you for your support!
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/stephenhill/base58/license:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Stephen Hill
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/stephenhill/base58/readme.md:
--------------------------------------------------------------------------------
1 | # Base58 Encoding and Decoding Library for PHP
2 |
3 | [](https://travis-ci.org/stephen-hill/base58php)
4 | [](https://packagist.org/packages/stephenhill/base58)
5 | [](https://github.com/stephen-hill/base58php/blob/master/license)
6 | [](https://flattr.com/submit/auto?user_id=stephen-hill&url=https%3A%2F%2Fgithub.com%2Fstephen-hill%2Fbase58php)
7 |
8 | ## Long Term Support
9 |
10 | Each major version of this library will be supported for 5 years after it's initial release. Support will be provided for security and bug fixes.
11 |
12 | Version 1 will therefore be supported until the 11th September 2019.
13 |
14 | ## Background
15 |
16 | I wanted a replacement for Base64 encoded strings and the [Base58 encoding used by Bitcoin](https://en.bitcoin.it/wiki/Base58Check_encoding) looked ideal. I looked around for an existing PHP library which would directly convert a string into Base58 but I couldn't find one, or at least one that worked correctly and was also well tested.
17 |
18 | So I decided to create a library with the following goals:
19 |
20 | - Encode/Decode PHP Strings
21 | - Simple and easy to use
22 | - Fully Tested
23 | - Available via Composer
24 |
25 | ## Requirements
26 |
27 | This library has the following requirements:
28 |
29 | - PHP => 5.3
30 | - BC Math Extension
31 |
32 | ## Installation
33 |
34 | I recommend you install this library via Composer.
35 |
36 | ```json
37 | {
38 | "require": {
39 | "stephenhill/base58": "~1.0"
40 | }
41 | }
42 | ```
43 |
44 | ## Basic Usage
45 |
46 | ```php
47 | require_once('vendor/autoload.php');
48 |
49 | $base58 = new StephenHill\Base58();
50 |
51 | $base58->encode('Hello World');
52 | $base58->decode('JxF12TrwUP45BMd');
53 | ```
54 |
55 | ## Advanced Usage
56 |
57 | By default this library chooses the encoding service provider to use, either GMPService or BCMathService (in that order).
58 | If you want to specify one of the included services or your own, you can inject it into the constructor.
59 |
60 | ```php
61 | require_once('vendor/autoload.php');
62 |
63 | $gmp = new StephenHill\GMPService();
64 | $base58 = new StephenHill\Base58(null, $gmp);
65 |
66 | $base58->encode('Hello World');
67 | $base58->decode('JxF12TrwUP45BMd');
68 | ```
69 |
70 | Also by default, this library uses Bitcoin's Base58 alphabet. If you want to use another variant, you can do this in the constructor.
71 |
72 | ```php
73 | require_once('vendor/autoload.php');
74 |
75 | // Flickr's Base58 Alphabet
76 | $base58 = new StephenHill\Base58('123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ');
77 |
78 | $base58->encode('Hello World');
79 | $base58->decode('iXf12sRWto45bmC');
80 | ```
81 |
82 | ## Testing
83 |
84 | This library is tested using PHPUnit.
85 |
86 | ```bash
87 | $ bin/phpunit
88 | ```
89 |
90 | ## Benchmarking
91 |
92 | You can benchmark this library using [Athletic](https://github.com/polyfractal/athletic).
93 | The benchmarking suite also benchmarks PHP's built-in Base64 and Base16 encoding for comparison.
94 |
95 | ```bash
96 | $ bin/athletic -p benchmarks
97 | ```
98 |
99 | Example output.
100 |
101 | ```
102 | StephenHill\Benchmarks\Base16Event
103 | Method Name Iterations Average Time Ops/second
104 | ------------ ------------ -------------- -------------
105 | encodeBase16: [10,000 ] [0.0000010839939] [922,514.40637]
106 | decodeBase16: [10,000 ] [0.0000011516809] [868,296.03561]
107 |
108 |
109 | StephenHill\Benchmarks\Base58BCMathEvent
110 | Method Name Iterations Average Time Ops/second
111 | ------------ ------------ -------------- -------------
112 | encodeBase58: [10,000 ] [0.0001500048161] [6,666.45263]
113 | decodeBase58: [10,000 ] [0.0001741812706] [5,741.14540]
114 |
115 |
116 | StephenHill\Benchmarks\Base58GMPEvent
117 | Method Name Iterations Average Time Ops/second
118 | ------------ ------------ -------------- -------------
119 | encodeBase58: [10,000 ] [0.0001168665648] [8,556.76730]
120 | decodeBase58: [10,000 ] [0.0001385705233] [7,216.54199]
121 |
122 |
123 | StephenHill\Benchmarks\Base64Event
124 | Method Name Iterations Average Time Ops/second
125 | ------------ ------------ -------------- -------------
126 | encodeBase64: [10,000 ] [0.0000009050369] [1,104,927.29189]
127 | decodeBase64: [10,000 ] [0.0000009787321] [1,021,730.04312]
128 | ```
129 |
130 | ## Contributing
131 |
132 | I welcome everyone to contribute to this library. Please see the Contributing document for details.
133 |
134 | ## License
135 |
136 | This library is license under the MIT License (MIT). Please see License File for more information.
137 |
138 | ## Credits
139 |
140 | This library was forked from [Jeremy Johnstone's](https://github.com/jsjohnst) Base58 methods on Gist https://gist.github.com/jsjohnst/126883.
141 |
142 | Some of the unit tests were based on the following:
143 |
144 | - https://code.google.com/p/bitcoinj/source/browse/core/src/test/java/com/google/bitcoin/core/Base58Test.java
145 | - https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/fixtures/base58.json
146 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/stephenhill/base58/src/BCMathService.php:
--------------------------------------------------------------------------------
1 | alphabet = $alphabet;
45 | $this->base = strlen($alphabet);
46 | }
47 | /**
48 | * Encode a string into base58.
49 | *
50 | * @param string $string The string you wish to encode.
51 | * @since Release v1.1.0
52 | * @return string The Base58 encoded string.
53 | */
54 | public function encode($string)
55 | {
56 | // Type validation
57 | if (is_string($string) === false) {
58 | throw new InvalidArgumentException('Argument $string must be a string.');
59 | }
60 |
61 | // If the string is empty, then the encoded string is obviously empty
62 | if (strlen($string) === 0) {
63 | return '';
64 | }
65 |
66 | // Strings in PHP are essentially 8-bit byte arrays
67 | // so lets convert the string into a PHP array
68 | $bytes = array_values(unpack('C*', $string));
69 |
70 | // Now we need to convert the byte array into an arbitrary-precision decimal
71 | // We basically do this by performing a base256 to base10 conversion
72 | $decimal = $bytes[0];
73 |
74 | for ($i = 1, $l = count($bytes); $i < $l; $i++) {
75 | $decimal = bcmul($decimal, 256);
76 | $decimal = bcadd($decimal, $bytes[$i]);
77 | }
78 |
79 | // This loop now performs base 10 to base 58 conversion
80 | // The remainder or modulo on each loop becomes a base 58 character
81 | $output = '';
82 | while ($decimal >= $this->base) {
83 | $div = bcdiv($decimal, $this->base, 0);
84 | $mod = (int) bcmod($decimal, $this->base);
85 | $output .= $this->alphabet[$mod];
86 | $decimal = $div;
87 | }
88 |
89 | // If there's still a remainder, append it
90 | if ($decimal > 0) {
91 | $output .= $this->alphabet[$decimal];
92 | }
93 |
94 | // Now we need to reverse the encoded data
95 | $output = strrev($output);
96 |
97 | // Now we need to add leading zeros
98 | foreach ($bytes as $byte) {
99 | if ($byte === 0) {
100 | $output = $this->alphabet[0] . $output;
101 | continue;
102 | }
103 | break;
104 | }
105 |
106 | return (string) $output;
107 | }
108 |
109 | /**
110 | * Decode base58 into a PHP string.
111 | *
112 | * @param string $base58 The base58 encoded string.
113 | * @since Release v1.1.0
114 | * @return string Returns the decoded string.
115 | */
116 | public function decode($base58)
117 | {
118 | // Type Validation
119 | if (is_string($base58) === false) {
120 | throw new InvalidArgumentException('Argument $base58 must be a string.');
121 | }
122 |
123 | // If the string is empty, then the decoded string is obviously empty
124 | if (strlen($base58) === 0) {
125 | return '';
126 | }
127 |
128 | $indexes = array_flip(str_split($this->alphabet));
129 | $chars = str_split($base58);
130 |
131 | // Check for invalid characters in the supplied base58 string
132 | foreach ($chars as $char) {
133 | if (isset($indexes[$char]) === false) {
134 | throw new InvalidArgumentException('Argument $base58 contains invalid characters. ($char: "'.$char.'" | $base58: "'.$base58.'") ');
135 | }
136 | }
137 |
138 | // Convert from base58 to base10
139 | $decimal = $indexes[$chars[0]];
140 |
141 | for ($i = 1, $l = count($chars); $i < $l; $i++) {
142 | $decimal = bcmul($decimal, $this->base);
143 | $decimal = bcadd($decimal, $indexes[$chars[$i]]);
144 | }
145 |
146 | // Convert from base10 to base256 (8-bit byte array)
147 | $output = '';
148 | while ($decimal > 0) {
149 | $byte = (int) bcmod($decimal, 256);
150 | $output = pack('C', $byte) . $output;
151 | $decimal = bcdiv($decimal, 256, 0);
152 | }
153 |
154 | // Now we need to add leading zeros
155 | foreach ($chars as $char) {
156 | if ($indexes[$char] === 0) {
157 | $output = "\x00" . $output;
158 | continue;
159 | }
160 | break;
161 | }
162 |
163 | return $output;
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/stephenhill/base58/src/Base58.php:
--------------------------------------------------------------------------------
1 |
10 | * @copyright 2014 Stephen Hill
11 | * @license http://www.opensource.org/licenses/MIT The MIT License
12 | * @link https://github.com/stephen-hill/base58php
13 | * @since Release v1.0.0
14 | */
15 | class Base58
16 | {
17 | /**
18 | * @var StephenHill\ServiceInterface;
19 | * @since v1.1.0
20 | */
21 | protected $service;
22 |
23 | /**
24 | * Constructor
25 | *
26 | * @param string $alphabet optional
27 | * @param ServiceInterface $service optional
28 | * @since v1.0.0
29 | * @since v1.1.0 Added the optional $service argument.
30 | */
31 | public function __construct(
32 | $alphabet = null,
33 | ServiceInterface $service = null
34 | ) {
35 | // Handle null alphabet
36 | if (is_null($alphabet) === true) {
37 | $alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
38 | }
39 |
40 | // Type validation
41 | if (is_string($alphabet) === false) {
42 | throw new InvalidArgumentException('Argument $alphabet must be a string.');
43 | }
44 |
45 | // The alphabet must contain 58 characters
46 | if (strlen($alphabet) !== 58) {
47 | throw new InvalidArgumentException('Argument $alphabet must contain 58 characters.');
48 | }
49 |
50 | // Provide a default service if one isn't injected
51 | if ($service === null) {
52 | // Check for GMP support first
53 | if (function_exists('\gmp_init') === true) {
54 | $service = new GMPService($alphabet);
55 | }
56 | else if (function_exists('\bcmul') === true) {
57 | $service = new BCMathService($alphabet);
58 | }
59 | else {
60 | throw new \Exception('Please install the BC Math or GMP extension.');
61 | }
62 | }
63 |
64 | $this->service = $service;
65 | }
66 |
67 | /**
68 | * Encode a string into base58.
69 | *
70 | * @param string $string The string you wish to encode.
71 | * @since v1.0.0
72 | * @return string The Base58 encoded string.
73 | */
74 | public function encode($string)
75 | {
76 | return $this->service->encode($string);
77 | }
78 |
79 | /**
80 | * Decode base58 into a PHP string.
81 | *
82 | * @param string $base58 The base58 encoded string.
83 | * @since v1.0.0
84 | * @return string Returns the decoded string.
85 | */
86 | public function decode($base58)
87 | {
88 | return $this->service->decode($base58);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/stephenhill/base58/src/GMPService.php:
--------------------------------------------------------------------------------
1 | alphabet = $alphabet;
45 | $this->base = strlen($alphabet);
46 | }
47 | /**
48 | * Encode a string into base58.
49 | *
50 | * @param string $string The string you wish to encode.
51 | * @since Release v1.1.0
52 | * @return string The Base58 encoded string.
53 | */
54 | public function encode($string)
55 | {
56 | // Type validation
57 | if (is_string($string) === false) {
58 | throw new InvalidArgumentException('Argument $string must be a string.');
59 | }
60 |
61 | // If the string is empty, then the encoded string is obviously empty
62 | if (strlen($string) === 0) {
63 | return '';
64 | }
65 |
66 | // Now we need to convert the byte array into an arbitrary-precision decimal
67 | // We basically do this by performing a base256 to base10 conversion
68 | $hex = unpack('H*', $string);
69 | $hex = reset($hex);
70 | $decimal = gmp_init($hex, 16);
71 |
72 | // This loop now performs base 10 to base 58 conversion
73 | // The remainder or modulo on each loop becomes a base 58 character
74 | $output = '';
75 | while (gmp_cmp($decimal, $this->base) >= 0) {
76 | list($decimal, $mod) = gmp_div_qr($decimal, $this->base);
77 | $output .= $this->alphabet[gmp_intval($mod)];
78 | }
79 |
80 | // If there's still a remainder, append it
81 | if (gmp_cmp($decimal, 0) > 0) {
82 | $output .= $this->alphabet[gmp_intval($decimal)];
83 | }
84 |
85 | // Now we need to reverse the encoded data
86 | $output = strrev($output);
87 |
88 | // Now we need to add leading zeros
89 | $bytes = str_split($string);
90 | foreach ($bytes as $byte) {
91 | if ($byte === "\x00") {
92 | $output = $this->alphabet[0] . $output;
93 | continue;
94 | }
95 | break;
96 | }
97 |
98 | return (string) $output;
99 | }
100 |
101 | /**
102 | * Decode base58 into a PHP string.
103 | *
104 | * @param string $base58 The base58 encoded string.
105 | * @since Release v1.1.0
106 | * @return string Returns the decoded string.
107 | */
108 | public function decode($base58)
109 | {
110 | // Type Validation
111 | if (is_string($base58) === false) {
112 | throw new InvalidArgumentException('Argument $base58 must be a string.');
113 | }
114 |
115 | // If the string is empty, then the decoded string is obviously empty
116 | if (strlen($base58) === 0) {
117 | return '';
118 | }
119 |
120 | $indexes = array_flip(str_split($this->alphabet));
121 | $chars = str_split($base58);
122 |
123 | // Check for invalid characters in the supplied base58 string
124 | foreach ($chars as $char) {
125 | if (isset($indexes[$char]) === false) {
126 | throw new InvalidArgumentException('Argument $base58 contains invalid characters.');
127 | }
128 | }
129 |
130 | // Convert from base58 to base10
131 | $decimal = gmp_init($indexes[$chars[0]], 10);
132 |
133 | for ($i = 1, $l = count($chars); $i < $l; $i++) {
134 | $decimal = gmp_mul($decimal, $this->base);
135 | $decimal = gmp_add($decimal, $indexes[$chars[$i]]);
136 | }
137 |
138 | // Convert from base10 to base256 (8-bit byte array)
139 | $output = '';
140 | while (gmp_cmp($decimal, 0) > 0) {
141 | list($decimal, $byte) = gmp_div_qr($decimal, 256);
142 | $output = pack('C', gmp_intval($byte)) . $output;
143 | }
144 |
145 | // Now we need to add leading zeros
146 | foreach ($chars as $char) {
147 | if ($indexes[$char] === 0) {
148 | $output = "\x00" . $output;
149 | continue;
150 | }
151 | break;
152 | }
153 |
154 | return $output;
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/stephenhill/base58/src/ServiceInterface.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | use Symfony\Polyfill\Mbstring as p;
13 |
14 | if (!function_exists('mb_strlen')) {
15 | define('MB_CASE_UPPER', 0);
16 | define('MB_CASE_LOWER', 1);
17 | define('MB_CASE_TITLE', 2);
18 |
19 | function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
20 | function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
21 | function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
22 | function mb_decode_numericentity($s, $convmap, $enc = null) { return p\Mbstring::mb_decode_numericentity($s, $convmap, $enc); }
23 | function mb_encode_numericentity($s, $convmap, $enc = null, $is_hex = false) { return p\Mbstring::mb_encode_numericentity($s, $convmap, $enc, $is_hex); }
24 | function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); }
25 | function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); }
26 | function mb_language($lang = null) { return p\Mbstring::mb_language($lang); }
27 | function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
28 | function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
29 | function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); }
30 | function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); }
31 | function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); }
32 | function mb_parse_str($s, &$result = array()) { parse_str($s, $result); }
33 | function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); }
34 | function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); }
35 | function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); }
36 | function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); }
37 | function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); }
38 | function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); }
39 | function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); }
40 | function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); }
41 | function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); }
42 | function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); }
43 | function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); }
44 | function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); }
45 | function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); }
46 | function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
47 | function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); }
48 | function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); }
49 | function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); }
50 | function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); }
51 | function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); }
52 | function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null) { return p\Mbstring::mb_convert_variables($toEncoding, $fromEncoding, $a, $b, $c, $d, $e, $f); }
53 | }
54 | if (!function_exists('mb_chr')) {
55 | function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); }
56 | function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); }
57 | function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
58 | }
59 |
60 | if (!function_exists('mb_str_split')) {
61 | function mb_str_split($string, $split_length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $split_length, $encoding); }
62 | }
63 |
--------------------------------------------------------------------------------
/nimiq-xpub/vendor/symfony/polyfill-mbstring/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "symfony/polyfill-mbstring",
3 | "type": "library",
4 | "description": "Symfony polyfill for the Mbstring extension",
5 | "keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"],
6 | "homepage": "https://symfony.com",
7 | "license": "MIT",
8 | "authors": [
9 | {
10 | "name": "Nicolas Grekas",
11 | "email": "p@tchwork.com"
12 | },
13 | {
14 | "name": "Symfony Community",
15 | "homepage": "https://symfony.com/contributors"
16 | }
17 | ],
18 | "require": {
19 | "php": ">=5.3.3"
20 | },
21 | "autoload": {
22 | "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" },
23 | "files": [ "bootstrap.php" ]
24 | },
25 | "suggest": {
26 | "ext-mbstring": "For best performance"
27 | },
28 | "minimum-stability": "dev",
29 | "extra": {
30 | "branch-alias": {
31 | "dev-master": "1.12-dev"
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/price_services/coingecko.php:
--------------------------------------------------------------------------------
1 | gateway = $gateway;
17 | }
18 |
19 | /**
20 | * @param {string[]} $crypto_currencies
21 | * @param {string} $shop_currency
22 | * @param {number} $order_amount
23 | * @return {[
24 | * 'prices'? => [[iso: string]: number]],
25 | * 'quotes'? => [[iso: string]: number]],
26 | * 'fees'? => [[iso: string]: number | ['gas_limit' => number, 'gas_price' => number]],
27 | * 'fees_per_byte'? => [[iso: string]: number],
28 | * ]} - Must include either prices or quotes, may include fees
29 | */
30 | public function get_prices( $crypto_currencies, $shop_currency, $order_amount ) {
31 | $fiat_currency = strtolower( $shop_currency );
32 | $ids = array_map( function( $currency_iso ) {
33 | return [
34 | 'nim' => 'nimiq-2',
35 | 'btc' => 'bitcoin',
36 | 'eth' => 'ethereum',
37 | ][ $currency_iso ];
38 | }, $crypto_currencies );
39 | $api_response = wp_remote_get( $this->api_endpoint . '/simple/price?ids=' . implode( ',', $ids ) . '&vs_currencies=' . $fiat_currency );
40 |
41 | if ( is_wp_error( $api_response ) ) {
42 | return $api_response;
43 | }
44 |
45 | $result = json_decode( $api_response[ 'body' ], true ); // Return as associative array (instead of object)
46 |
47 | if ( array_key_exists( 'error', $result ) ) {
48 | return new WP_Error( 'service', $result[ 'error' ] );
49 | }
50 |
51 | $prices = [];
52 | foreach ( $result as $id => $price_object ) {
53 | $currency_iso = [
54 | 'nimiq-2' => 'nim',
55 | 'bitcoin' => 'btc',
56 | 'ethereum' => 'eth',
57 | ][ $id ];
58 |
59 | $price = $price_object[ $fiat_currency ];
60 |
61 | if ( empty( $price ) ) {
62 | /* translators: %s: Uppercase three-letter currency code, e.g. PEN, SGD */
63 | return new WP_Error( 'service', sprintf( __( 'The currency %s is not supported by Coingecko.', 'wc-gateway-nimiq' ), strtoupper( $fiat_currency ) ) );
64 | };
65 |
66 | $prices[ $currency_iso ] = $price;
67 | }
68 |
69 | return [
70 | 'prices' => $prices,
71 | ];
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/price_services/fastspot.php:
--------------------------------------------------------------------------------
1 | gateway = $gateway;
17 | }
18 |
19 | /**
20 | * @param {string[]} $crypto_currencies
21 | * @param {string} $shop_currency
22 | * @param {number} $order_amount
23 | * @return {[
24 | * 'prices'? => [[iso: string]: number]],
25 | * 'quotes'? => [[iso: string]: number]],
26 | * 'fees'? => [[iso: string]: number | ['gas_limit' => number, 'gas_price' => number]],
27 | * 'fees_per_byte'? => [[iso: string]: number],
28 | * ]} - Must include either prices or quotes, may include fees
29 | */
30 | public function get_prices( $crypto_currencies, $shop_currency, $order_amount ) {
31 | $fiat_currency = strtoupper( $shop_currency );
32 | $uppercase_cryptos = array_map( 'strtoupper', $crypto_currencies );
33 |
34 | $options = [
35 | 'from' => $uppercase_cryptos,
36 | 'to' => [
37 | $fiat_currency => $order_amount,
38 | ],
39 | 'includedFees' => 'none',
40 | ];
41 |
42 | $api_response = wp_remote_post( $this->api_endpoint . '/estimates', [
43 | 'headers' => [
44 | 'Accept' => 'application/json',
45 | 'Content-Type' => 'application/json',
46 | ],
47 | 'body' => json_encode( $options ),
48 | ] );
49 |
50 | if ( is_wp_error( $api_response ) ) {
51 | return $api_response;
52 | }
53 |
54 | $result = json_decode( $api_response[ 'body' ], true ); // Return as associative array (instead of object)
55 |
56 | if ( array_key_exists( 'status', $result ) && $result[ 'status' ] >= 400 ) {
57 | return new WP_Error( 'service', $result[ 'detail' ] );
58 | }
59 |
60 | $quotes = [];
61 | $fees = [];
62 | $feesPerByte = [];
63 | foreach ( $result as $estimate ) {
64 | $price_object = $estimate[ 'from' ][ 0 ];
65 | $currency_iso = strtolower( $price_object[ 'symbol' ] );
66 |
67 | $quotes[ $currency_iso ] = $price_object[ 'amount' ];
68 |
69 | $fee = Crypto_Manager::coins_to_units( [
70 | $currency_iso => $price_object[ 'fundingNetworkFee' ][ 'total' ],
71 | ] )[ $currency_iso ];
72 | $feePerByte = Crypto_Manager::coins_to_units( [
73 | $currency_iso => $price_object[ 'fundingNetworkFee' ][ 'perUnit' ],
74 | ] )[ $currency_iso ];
75 |
76 | // Round ETH $feePerByte to its first three significant digits
77 | if ( $currency_iso === 'eth' ) {
78 | $feePerByte = strval( round( $feePerByte, -( strlen( $feePerByte ) - 3 ) ) );
79 | }
80 |
81 | $fees[ $currency_iso ] = $currency_iso === 'eth'
82 | ? [
83 | 'gas_limit' => 21000,
84 | 'gas_price' => $feePerByte,
85 | ] : $fee;
86 | $feesPerByte[ $currency_iso ] = $feePerByte;
87 | }
88 |
89 | return [
90 | 'quotes' => $quotes,
91 | 'fees' => $fees,
92 | 'fees_per_byte' => $feesPerByte,
93 | ];
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/price_services/interface.php:
--------------------------------------------------------------------------------
1 | [[iso: string]: number]],
18 | * 'quotes'? => [[iso: string]: number]],
19 | * 'fees'? => [[iso: string]: number | ['gas_limit' => number, 'gas_price' => number]],
20 | * 'fees_per_byte'? => [[iso: string]: number],
21 | * ]} - Must include either prices or quotes, may include fees
22 | */
23 | public function get_prices( $crypto_currencies, $shop_currency, $order_amount );
24 | }
25 |
--------------------------------------------------------------------------------
/price_services/nimiqx.php:
--------------------------------------------------------------------------------
1 | gateway = $gateway;
18 |
19 | $this->api_key = $gateway->get_option( 'nimiqx_api_key' );
20 | if ( empty( $this->api_key ) ) {
21 | throw new Exception( __( 'API key not set.', 'wc-gateway-nimiq') );
22 | }
23 | if ( !ctype_xdigit( $this->api_key ) ) {
24 | throw new Exception( __( 'Invalid API key.', 'wc-gateway-nimiq') );
25 | }
26 | }
27 |
28 | /**
29 | * @param {string[]} $crypto_currencies
30 | * @param {string} $shop_currency
31 | * @param {number} $order_amount
32 | * @return {[
33 | * 'prices'? => [[iso: string]: number]],
34 | * 'quotes'? => [[iso: string]: number]],
35 | * 'fees'? => [[iso: string]: number | ['gas_limit' => number, 'gas_price' => number]],
36 | * 'fees_per_byte'? => [[iso: string]: number],
37 | * ]} - Must include either prices or quotes, may include fees
38 | */
39 | public function get_prices( $crypto_currencies, $shop_currency, $order_amount ) {
40 | $currency = strtolower( $shop_currency );
41 | $api_response = wp_remote_get( $this->makeUrl( 'price/' . $currency ) );
42 |
43 | if ( is_wp_error( $api_response ) ) {
44 | return $api_response;
45 | }
46 |
47 | $result = json_decode( $api_response[ 'body' ], true );
48 |
49 | if ( $result->error ) {
50 | return new WP_Error( 'service', $result->error );
51 | }
52 |
53 | $price = $result[ $currency ];
54 |
55 | if ( empty( $price ) ) {
56 | /* translators: %s: Uppercase three-letter currency code, e.g. PEN, SGD */
57 | return new WP_Error( 'service', sprintf( __( 'The currency %s is not supported by NimiqX.', 'wc-gateway-nimiq' ), strtoupper( $currency ) ) );
58 | };
59 |
60 | return [
61 | 'prices' => [
62 | 'nim' => $price,
63 | ],
64 | ];
65 | }
66 |
67 | private function makeUrl( $path ) {
68 | return 'https://api.nimiqx.com/' . $path . '?api_key=' . $this->api_key;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/readme.txt:
--------------------------------------------------------------------------------
1 | === Cryptocurrency Checkout - Accept Bitcoin, Ethereum and Nimiq ===
2 |
3 | Contributors: nimiq
4 | Tags: woocommerce, cryptocurrency, crypto, checkout, gateway, nimiq, nim, bitcoin, btc, ethereum, eth
5 | Requires at least: 4.9
6 | Tested up to: 6.1
7 | Requires WooCommerce at least: 3.5
8 | Tested WooCommerce up to: 7.1
9 | Stable tag: 3.4.1
10 | Requires PHP: 7.1.0
11 | License: GPLv3
12 | License URI: https://www.gnu.org/licenses/gpl-3.0.html
13 |
14 | Receive crypto directly from your customers + easy integration + beautiful interface + no middleman + no fees.
15 |
16 | == Description ==
17 |
18 | Seamlessly integrate Bitcoin, Ethereum and Nimiq payments into your webshop. Receive the equivalent of your regular price in crypto directly in your wallet. Easy to integrate and free of charge. Beautifully designed and easy to use. Open source and decentralized.
19 |
20 | **Features Include:**
21 |
22 | * Bitcoin, Ethereum and Nimiq support
23 | * Automatic conversion from supported store currencies like USD or EUR to crypto at latest market prices
24 | * Full order status feedback in your WooCommerce panel
25 | * Decentralized and non-proprietary
26 | * Configurable conversion and validation service providers
27 | * Configurable confirmation times with sensible defaults
28 |
29 | _This Plugin is just getting started. Additional features such as instant and decentralized Crypto-to-Euro swaps are being currently developed._
30 |
31 | = How Does It Work? =
32 |
33 | 1. The customer selects “Cryptocurrency Checkout” and is sent to the Nimiq Checkout page.
34 | 2. Cryptocurrency Checkout by Nimiq offers to take payments in Bitcoin, Ethereum or Nimiq.
35 | 3. The customer selects a cryptocurrency and pays. An order is created in the WooCommerce panel and set to 'on-hold' by the plugin.
36 | 4. As soon as the transaction is confirmed on the blockchain, the plugin automatically updates the order status.
37 |
38 | = How To Integrate It? =
39 |
40 | 1. Install and activate the plugin
41 | 2. Find the **Cryptocurrency Checkout by Nimiq** in your list of plugins and click 'Settings'
42 | 3. Enter addresses and public keys of the currencies you want to accept
43 | 4. Tell your customers about your new payment option!
44 |
45 | Check out the documentation, with a more in-depth [tutorial](https://nimiq.github.io/tutorials/wordpress-payment-plugin-installation).
46 |
47 | = Where Does The Crypto Go? =
48 |
49 | You provide your wallet addresses in the WooCommerce admin panel and receive the crypto directly from your customer.
50 |
51 | If you are new to crypto, you can create a Bitcoin and Ethereum wallet with [Jaxx](https://jaxx.io) (a third-party application). For Nimiq, you don’t need to rely on third-parties and can create an address in just seconds and without the need to provide personal data, at [safe.nimiq.com](https://safe.nimiq.com).
52 |
53 | = What Is Nimiq? =
54 |
55 | Nimiq is a blockchain project, NIM is its cryptocurrency, designed for ease-of-use. Sending, receiving and storing NIM is as easy as using Facebook. Creating an account is even easier.
56 |
57 | Give it a try: [nimiq.com](https://nimiq.com)
58 |
59 | = Why Is This Plugin For Free? =
60 |
61 | We believe that cryptocurrencies are the future and will provide a better, more democratic and more open form of money. With this Checkout Plugin, we want to provide a tool for everyone interested in crypto. By providing BTC and ETH payments together with NIM, we wish to support cryptocurrencies in general while illustrating just how much more easy and convenient Nimiq is.
62 |
63 | == Screenshots ==
64 |
65 | 1. Easy to set up and maintain
66 | 2. Clean and straight forward payment settings
67 | 3. Seamlessly add cryptocurrency to your payment options
68 | 4. Payment Step 1: Chose your preferred currency
69 | 5. Payment Step 2: Get all relevant info at a glance
70 | 6. Payment Step 3: Pay using an app, QR code or manual inputs
71 | 7. Receive the payments straight to your wallet
72 |
73 | == Changelog ==
74 |
75 | = 3.4.1 - 2022.11.23 =
76 |
77 | * Add languages: Filipino, Portuguese, Russian, Ukrainian
78 |
79 | = 3.4.0 - 2022.01.10 =
80 |
81 | * Add support for Hub's acceptance of Nimiq payments from other wallets (for all three monitoring services)
82 | * Auto-complete orders that do not require shipping, after payment was confirmed
83 |
84 | = 3.3.2 - 2021.11.10 =
85 |
86 | * Rename plugin to "Cryptocurrency Checkout by Nimiq"
87 |
88 | = 3.3.1 - 2021.06.11 =
89 |
90 | * Fix bug where fee suggestions were sometimes converted wrongly from coins to units
91 |
92 | = 3.3.0 - 2021.01.25 =
93 |
94 | * Update Fastspot price service to new API
95 | * Add Dutch translations
96 |
97 | = 3.2.2 - 2020.08.11 =
98 |
99 | * Add Spanish translations
100 |
101 | = 3.2.1 - 2020.07.06 =
102 |
103 | * Add Chinese translations
104 | * Update French translations
105 |
106 | = 3.2.0 - 2020.06.22 =
107 |
108 | * Display vendor markup (margin) in Checkout price tooltip for transparency
109 | * Accept one decimal number for the margin setting
110 | * Nimiq Hub compatibility update
111 |
112 | = 3.1.4 - 2020.03.26 =
113 |
114 | * Change to custom CSRF token generation, as WP nonces sometimes have problems validating
115 | * Update HubApi to v1.2.1
116 | * Tested with WooCommerce 4.0
117 |
118 | = 3.1.3 - 2020.02.01 =
119 |
120 | * Improve French translations
121 |
122 | = 3.1.2 - 2020.01.17 =
123 |
124 | * Fix transaction validation not working when no Etherscan API key was set
125 |
126 | = 3.1.1 - 2019.12.16 =
127 |
128 | * Fix popup overlay positioning on scrollable pages
129 | * Fix endless loop for redirect payments from payment page
130 |
131 | = 3.1.0 - 2019.12.07 =
132 |
133 | * Add French translations
134 | * Add overlay to shop page when Nimiq Hub popup is open
135 |
136 | = 3.0.0 - 2019.11.22 =
137 |
138 | * Now accepting Bitcoin, Ethereum and Nimiq payments!
139 | * Huge usability improvements over previous versions.
140 |
141 | == Upgrade Notice ==
142 |
143 | = 3.4.0 =
144 |
145 | Enable Hub support for Nimiq payments from other wallets: update to enable your users to pay with any NIM wallet.
146 |
147 | = 3.3.1 =
148 |
149 | Fix bug in calculation of fee suggestions that could sometimes show a too high fee suggestion.
150 |
151 | = 3.3.0 =
152 |
153 | Update Fastspot price service to new API (old API will soon be shut off). Update NOW if you are using Fastspot as your price service! Also added Dutch translations.
154 |
155 | = 3.2.2 =
156 |
157 | Added Spanish translations.
158 |
159 | = 3.2.1 =
160 |
161 | Added Chinese translations, update french.
162 |
163 | = 3.2.0 =
164 |
165 | Display vendor markup (margin) in Checkout price tooltip for transparency.
166 |
167 | = 3.1.4 =
168 |
169 | Fix a problem that sometimes prevented Nimiq Checkout from opening correctly.
170 |
171 | = 3.1.3 =
172 |
173 | Improved French translations.
174 |
175 | = 3.1.2 =
176 |
177 | Fixed transaction validation when no Etherscan API key is set.
178 |
179 | = 3.1.1 =
180 |
181 | Fixed popup overlay positioning and endless redirect payment loop.
182 |
183 | = 3.1.0 =
184 |
185 | Added French translations and an overlay when the Nimiq Hub popup is open.
186 |
187 | = 3.0.0 =
188 |
189 | Cryptocurrency Checkout by Nimiq now also supports accepting payments in Bitcoin and Ethereum! Update your settings to enable the new currencies.
190 |
191 | == Acknowledgement ==
192 |
193 | This Nimiq payment gateway is based on skyverge's [WooCommerce Offline Gateway](https://github.com/bekarice/woocommerce-gateway-offline), which in turn forks the WooCommerce core "Cheque" payment gateway.
194 |
--------------------------------------------------------------------------------
/styles.css:
--------------------------------------------------------------------------------
1 | #nim_pay_button {
2 | margin: 0 auto 32px;
3 | background: #0582CA;
4 | background-image: radial-gradient(ellipse at bottom right, #265DD7, #0582CA);
5 | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
6 | color: white;
7 | font-size: 20px;
8 | line-height: 1;
9 | display: flex;
10 | flex-direction: row;
11 | align-items: center;
12 | border-radius: 500px;
13 | padding: 20px 36px;
14 | outline: none;
15 | position: relative;
16 | transition: transform 450ms cubic-bezier(0.25, 0, 0, 1), box-shadow 450ms cubic-bezier(0.25, 0, 0, 1);
17 | }
18 |
19 | #nim_pay_button:not([disabled]):hover,
20 | #nim_pay_button:not([disabled]):focus {
21 | box-shadow: 0 8px 20px rgba(0,0,0,0.2);
22 | transform: translateY(-2px);
23 | }
24 |
25 | #nim_pay_button span {
26 | text-transform: uppercase;
27 | letter-spacing: 0.1em;
28 | flex-shrink: 0;
29 | }
30 |
31 | #nim_pay_button img {
32 | margin-left: 16px;
33 | }
34 |
35 | #nim_pay_button:focus::before {
36 | content: '';
37 | position: absolute;
38 | left: -5px;
39 | top: -5px;
40 | right: -5px;
41 | bottom: -5px;
42 | border: 2px solid rgba(5, 130, 202, 0.5); /* Based on Nimiq Light Blue */
43 | border-radius: 500px;
44 | }
45 |
46 | #nim_gateway_info_block.hidden,
47 | #nim_payment_received_block.hidden {
48 | display: none;
49 | }
50 |
51 | #nim_gateway_info_block,
52 | #nim_payment_received_block {
53 | text-align: center;
54 | }
55 |
56 | #nim_payment_received_block .fa-check-circle {
57 | color: seagreen;
58 | font-size: 2em;
59 | margin-bottom: 8px;
60 | display: block;
61 | }
62 |
63 | #nim_payment_received_block small {
64 | display: block;
65 | }
66 |
67 | @media (max-width: 768px) {
68 | #nim_pay_button {
69 | margin: 16px auto 24px;
70 | font-size: 18px;
71 | padding: 18px 32px;
72 | }
73 |
74 | #nim_pay_button img {
75 | margin-left: 14px;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/validation_services/interface.php:
--------------------------------------------------------------------------------
1 |