ocubom / base-convert
Safe number conversion between arbitrary bases.
Requires
- php: >=8.1
Requires (Dev)
- friendsofphp/php-cs-fixer: *
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^2.2
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- phpunit/phpunit: ^10.5|^11.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Safe number conversion between arbitrary bases
Explore the docs » · Report Bug · Request Feature
About ocubom/base-convert
ocubom/base-convert performs safe number conversion between arbitrary bases. The conversion uses a custom implementation to avoid the float precision problem of the native PHP base_convert function.
This implementation is extracted from the Symfony UID component.
The class BinaryUtil implements the necessary fromBase and toBase methods.
These methods were extracted to ensure compatibility and reduce the minimum PHP version required.
Getting Started
Prerequisites
- PHP >= 8.1 (tested up to 8.6)
- Composer >= 2.0
Installation
Install the package via composer:
composer require ocubom/base-convert
Usage
Simply import the namespaced base_convert and use it like the native function. Although this implementation is drop-in compatible with the native function, it provides several improvements:
-
Extends support to base-62, whereas the native version only supports bases between 2 and 36.
The conversion uses the same Base62 algorithm as the GMP extension, making them 100% compatible.
-
"Named bases" are supported.
Name Base decbase 10 decimalbase 10 dozbase 12 duodecimalbase 12 hexbase 16 hexadecimalbase 16 octbase 8 octalbase 8 sexagesimalbase 60 vigesimalbase 20 -
The special base
binorbinarycan be used to convert to and from binary strings. This can be used to directly convert binary outputs of some functions.use function Ocubom\Math\base_convert; $hex = base_convert(random_bytes(32), 'bin', 'hex');
[!Warning]
Do not confuse a binary encoding (
binorbinary) with the Base-2 encoding (a text string with the characters0and1).In PHP there are several pairs of functions:
In this library, the strings
binandbinaryare considered equivalent to the first set of functions. -
New bases can be used by implementing the
BaseInterface.Includes bases for Douglas Crockford base-32 and variants of base-58 encodings. These implementations are examples of how to customize your own encoding.
-
base_convertsupports additional left padding. This is useful for maintaining fixed-length numbers that start with zero. -
Includes a drop-in replacement for the
random_bytesfunction with a second argument to specify the output base. -
Provides an object-oriented
Numberclass to use the conversions.
Note
Positional Math vs. Stream Encoding
This library performs pure positional mathematical conversion. It treats the input bytes as a single, large integer and computes the output using successive divisions and remainders.
This is fundamentally different from stream-based encodings (like standard RFC 4648 Base64), which process data in fixed bit-chunks (e.g., 6-bit blocks) and often use padding (=).
Douglas Crockford base-32 encoding
A secure version of the base-32 encoding proposed by Douglas Crockford.
Note
The encoding scheme is required to
-
Be human-readable and machine-readable.
-
Be compact. Humans have difficulty in manipulating long strings of arbitrary symbols.
-
Be error resistant. Entering the symbols must not require keyboarding gymnastics.
-
Be pronounceable. Humans should be able to accurately transmit the symbols to other humans using a telephone.
-- Douglas Crockford. base-32
This encoding is accessible:
-
By passing a
Crockfordobject as any of the base arguments of thebase_convertfunction.use Ocubom\Math\Base\Crockford; use function Ocubom\Math\base_convert; // Encoding $crockford = base_convert(random_bytes(32), 'bin', new Crockford()); // Decoding $hex = base_convert($crockford, new Crockford(), 'hex');
-
Using the
encodeanddecodemethods of theCrockfordclass.use Ocubom\Math\Crockford; // Encoding $crockford = Crockford::encode(random_bytes(32), 'bin'); // Decoding $hex = Crockford::decode($crockford, 'hex');
-
Using the
crockford_encodeandcrockford_decodefunctions.use function Ocubom\Math\crockford_decode; use function Ocubom\Math\crockford_encode; // Encoding $crockford = crockford_encode(random_bytes(32), 'bin'); // Decoding $hex = crockford_decode($crockford, 'hex');
An additional parameter can be added to include a checksum for error detection.
base-58 encodings
Warning
Do not confuse Base58* with numeric base-58 (provided by the Numeric class).
Base-58 is a family of encoding schemes designed to provide a compact, human-readable representation of large integers.
In order to make the output more readable, base-58 deliberately omits characters that can be easily confused by humans (such as 0, O, I, and l) and avoids non-alphanumeric symbols like + or /.
Although popularized by Bitcoin, several platforms have adapted the underlying mathematics using different character arrangements (alphabets) to suit their specific needs.
Note
Why base-58 instead of standard base-64 encoding?
-
Don't want 0OIl characters that look the same in some fonts and could be used to create visually identical looking data.
-
A string with non-alphanumeric characters is not as easily accepted as input.
-
E-mail usually won't line-break if there's no punctuation to break at.
-
Double-clicking selects the whole string as one word if it's all alphanumeric.
-- Satoshi Nakamoto. Bitcoin source code
This package provides out-of-the-box support for the three most popular base-58 variants. They share the same math engine but use different alphabets:
Base58Btc: Satoshi Nakamoto's original base-58 encoding.Base58Flickr: Flickr URL shortener encoding (optimized for URLs by ordering digits and lowercase letters first).Base58Xrp: XRP Ledger base-58 encoding (alphabet arranged so addresses start withr).
These encodings are accessible by passing their respective objects as the base argument of the base_convert function:
use Ocubom\Math\Base\Base58Btc; use Ocubom\Math\Base\Base58Flickr; use Ocubom\Math\Base\Base58Xrp; use function Ocubom\Math\base_convert; $bytes = random_bytes(32); // Encoding with different alphabets $btc = base_convert($bytes, 'bin', new Base58Btc()); $flickr = base_convert($bytes, 'bin', new Base58Flickr()); $xrp = base_convert($bytes, 'bin', new Base58Xrp()); // Decoding $hex = base_convert($btc, new Base58Btc(), 'hex');
Roadmap
See the open issues for a list of proposed features (and known issues).
Support
Reach out to the maintainer at GitHub Issues.
Authorship
Oscar Cubo Medina — https://ocubom.github.io
For a full list of all authors and contributors, see the contributors page.
License
Distributed under the MIT License.
See LICENSE for more information.