├── .gitignore ├── .travis.yml ├── benchmarks ├── Base16Event.php ├── Base58BCMathEvent.php ├── Base58GMPEvent.php └── Base64Event.php ├── composer.json ├── contributing.md ├── docs ├── index.md └── navbar.md ├── license ├── phpunit.xml ├── readme.md ├── src ├── BCMathService.php ├── Base58.php ├── GMPService.php └── ServiceInterface.php └── tests ├── Base58Test.php └── bootstrap.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | /bin/ 3 | composer.lock 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | before_script: 4 | - composer install 5 | 6 | php: 7 | - 5.3 8 | - 5.4 9 | - 5.5 10 | - 5.6 11 | - 7 12 | - 7.1 13 | - 7.2 14 | - 7.3 15 | - hhvm 16 | 17 | script: bin/phpunit 18 | -------------------------------------------------------------------------------- /benchmarks/Base16Event.php: -------------------------------------------------------------------------------- 1 | base58 = new Base58(null, new BCMathService()); 16 | } 17 | 18 | /** 19 | * @iterations 10000 20 | */ 21 | public function encodeBase58() 22 | { 23 | $this->base58->encode('Hello World'); 24 | } 25 | 26 | /** 27 | * @iterations 10000 28 | */ 29 | public function decodeBase58() 30 | { 31 | $this->base58->decode('JxF12TrwUP45BMd'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /benchmarks/Base58GMPEvent.php: -------------------------------------------------------------------------------- 1 | base58 = new Base58(null, new GMPService()); 16 | } 17 | 18 | /** 19 | * @iterations 10000 20 | */ 21 | public function encodeBase58() 22 | { 23 | $this->base58->encode('Hello World'); 24 | } 25 | 26 | /** 27 | * @iterations 10000 28 | */ 29 | public function decodeBase58() 30 | { 31 | $this->base58->decode('JxF12TrwUP45BMd'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /benchmarks/Base64Event.php: -------------------------------------------------------------------------------- 1 | 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 | -------------------------------------------------------------------------------- /docs/navbar.md: -------------------------------------------------------------------------------- 1 | # Menu 2 | 3 | * [Home][home] 4 | 5 | [home]: /index.md 6 | -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | ./tests/ 20 | 21 | 22 | 23 | 24 | 25 | src 26 | 27 | vendor 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Base58 Encoding and Decoding Library for PHP 2 | 3 | [![Build Status](https://travis-ci.org/stephen-hill/base58php.png)](https://travis-ci.org/stephen-hill/base58php) 4 | [![Packagist Release](http://img.shields.io/packagist/v/stephenhill/base58.svg)](https://packagist.org/packages/stephenhill/base58) 5 | [![MIT License](http://img.shields.io/packagist/l/stephenhill/base58.svg)](https://github.com/stephen-hill/base58php/blob/master/license) 6 | [![Flattr this](https://api.flattr.com/button/flattr-badge-large.png)](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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/ServiceInterface.php: -------------------------------------------------------------------------------- 1 | assertSame($encoded, $instance->encode($string)); 18 | } 19 | 20 | /** 21 | * @dataProvider encodingsProvider 22 | */ 23 | public function testDecode($string, $encoded, $instance) 24 | { 25 | $string = (string) $string; 26 | $encoded = (string) $encoded; 27 | 28 | $this->assertSame($string, $instance->decode($encoded)); 29 | } 30 | 31 | public function encodingsProvider() 32 | { 33 | $instances = array( 34 | new Base58(null, new BCMathService()), 35 | new Base58(null, new GMPService()) 36 | ); 37 | 38 | $tests = array( 39 | array('', ''), 40 | array('1', 'r'), 41 | array('a', '2g'), 42 | array('bbb', 'a3gV'), 43 | array('ccc', 'aPEr'), 44 | array('hello!', 'tzCkV5Di'), 45 | array('Hello World', 'JxF12TrwUP45BMd'), 46 | array('this is a test', 'jo91waLQA1NNeBmZKUF'), 47 | array('the quick brown fox', 'NK2qR8Vz63NeeAJp9XRifbwahu'), 48 | array('THE QUICK BROWN FOX', 'GRvKwF9B69ssT67JgRWxPQTZ2X'), 49 | array('simply a long string', '2cFupjhnEsSn59qHXstmK2ffpLv2'), 50 | array("\x00\x61", '12g'), 51 | array("\x00", '1'), 52 | array("\x00\x00", '11'), 53 | array('0248ac9d3652ccd8350412b83cb08509e7e4bd41', '3PtvAWwSMPe2DohNuCFYy76JhMV3rhxiSxQMbPBTtiPvYvneWu95XaY') 54 | ); 55 | 56 | $return = array(); 57 | 58 | foreach ($instances as $instance) { 59 | foreach ($tests as $test) { 60 | $test[] = $instance; 61 | $return[] = $test; 62 | } 63 | } 64 | 65 | return $return; 66 | } 67 | 68 | /** 69 | * @expectedException InvalidArgumentException 70 | * @expectedExceptionMessage Argument $alphabet must be a string. 71 | */ 72 | public function testConstructorTypeException() 73 | { 74 | new Base58(intval(123)); 75 | } 76 | 77 | /** 78 | * @expectedException InvalidArgumentException 79 | * @expectedExceptionMessage Argument $alphabet must contain 58 characters. 80 | */ 81 | public function testConstructorLengthException() 82 | { 83 | new Base58(''); 84 | } 85 | 86 | /** 87 | * @expectedException InvalidArgumentException 88 | * @expectedExceptionMessage Argument $string must be a string. 89 | */ 90 | public function testEncodeTypeException() 91 | { 92 | $base58 = new Base58(); 93 | $base58->encode(intval(123)); 94 | } 95 | 96 | /** 97 | * @expectedException InvalidArgumentException 98 | * @expectedExceptionMessage Argument $base58 must be a string. 99 | */ 100 | public function testDecodeTypeException() 101 | { 102 | $base58 = new Base58(); 103 | $base58->decode(intval(123)); 104 | } 105 | 106 | /** 107 | * @expectedException InvalidArgumentException 108 | * @expectedExceptionMessage Argument $base58 contains invalid characters. 109 | */ 110 | public function testInvalidBase58() 111 | { 112 | $base58 = new Base58(); 113 | $base58->decode("This isn't valid base58"); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 |