A Detailed Guide to Base58 Encoding and Decoding in PHP
In this blog, we’ll dive into the world of Base58 encoding and decoding — a popular method used in various applications such as cryptocurrency addresses, IPFS, and URL shorteners. Specifically, we’ll focus on how to encode and decode hexadecimal strings into Base58 encoded strings, particularly the case where the output is restricted to 3 characters.
We’ll cover the underlying technical concepts, step-by-step instructions, and provide practical examples in PHP. Whether you’re building a cryptocurrency application or just curious about Base58 encoding, this guide will be useful.
What is Base58 Encoding?
Base58 encoding is a binary-to-text encoding scheme that encodes binary data into a string of ASCII characters, similar to Base64. However, Base58 avoids characters that can be easily confused with others (like the number 0
, the letter O
, the number 1
, and the letter I
), which helps in reducing errors when reading or typing the encoded strings.
The Base58 alphabet consists of the following characters:
123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
The primary use of Base58 encoding is found in cryptocurrency systems like Bitcoin, where it is used to encode public keys and wallet addresses.
Base58 Encoding Process
Base58 works by encoding 8-bit bytes into a set of 58 possible characters. It’s similar to Base64, but with a smaller set of characters, and is designed to avoid ambiguous characters.
Here’s the general procedure for encoding data into Base58:
- Convert the input data into a large integer.
- Divide the integer by 58, obtaining the quotient and remainder.
- The remainder corresponds to a character from the Base58 alphabet.
- Repeat the process with the quotient until the quotient becomes 0.
- The encoded string is the collection of characters corresponding to the remainders.
Decoding Base58
To decode a Base58 string, we reverse the encoding process:
- Convert the Base58 string back to an integer by using the reverse operation: each character is mapped to its position in the Base58 alphabet.
- After obtaining the integer, convert it back into a byte sequence.
- Convert the byte sequence back into the original data format (in our case, hexadecimal).
PHP Implementation of Base58 Encoding and Decoding
In this section, we will provide PHP functions to encode and decode hexadecimal strings into 3-character Base58 strings and vice versa.
Base58 Encoding Function
First, let’s create a function that converts a raw byte string into a Base58-encoded string.
// Base58 alphabet
$alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
// Function to convert a number into Base58
function base58_encode($input) {
global $alphabet;
// Convert input string to an integer
$num = gmp_init(bin2hex($input), 16); // Treat input as hex and convert to GMP integer
$base58 = '';
while (gmp_cmp($num, 0) > 0) {
list($num, $mod) = gmp_div_qr($num, 58);
$base58 = $alphabet[gmp_intval($mod)] . $base58;
}
return $base58;
}
- This function uses GMP (GNU Multiple Precision) arithmetic to handle very large numbers since Base58 encoding can result in numbers that exceed the normal integer range.
- It converts the input string into hexadecimal and then treats it as a large integer.
- The function repeatedly divides the number by 58, appending the corresponding Base58 character for the remainder until the quotient becomes zero.
Base58 Decoding Function
Now, let’s create the decoding function to reverse the Base58 encoding.
// Function to decode a Base58 string
function base58_decode($input) {
global $alphabet;
// Convert Base58 string to an integer
$num = gmp_init(0); // Initialize a large integer
$base58_len = strlen($input);
// Iterate through each character in the input string
for ($i = 0; $i < $base58_len; $i++) {
$char = $input[$i];
$index = strpos($alphabet, $char); // Find the character's index in the Base58 alphabet
$num = gmp_add(gmp_mul($num, 58), $index); // Multiply the number by 58 and add the index
}
// Convert the integer back to a hexadecimal string
$hex = gmp_strval($num, 16); // Convert to hexadecimal
// Ensure it has an even number of characters (required for packing)
if (strlen($hex) % 2 != 0) {
$hex = '0' . $hex;
}
return $hex;
}
- The decoding function takes a Base58 string and converts it into a large integer.
- After decoding, the integer is converted back into a hexadecimal string, which is the original format.
Converting to a 3-Character Base58 Encoded String
We are specifically interested in encoding a hexadecimal string into 3-character Base58 strings. For that, we simply apply the base58_encode()
function and trim the result to 3 characters.
// Function to convert a string (like '1000202020202342') to Base58 and get 3 characters
function convert_to_base58($str) {
// Convert input string to bytes
$input = pack('H*', $str); // Pack the hex string into raw bytes
// Get the Base58 encoding
$encoded = base58_encode($input);
// Trim the encoded string to 3 characters
return substr($encoded, 0, 3);
}
Full Example with Encoding and Decoding
$input = '1000202020202342'; // Input hex string
$base58_str = convert_to_base58($input); // Convert to 3-char Base58
echo "Encoded '$input' to 3 chars: $base58_str\n";
// Now decode the Base58 string back to hex
$decoded_hex = base58_decode($base58_str);
echo "Decoded Base58 '$base58_str' to hex: $decoded_hex\n";
Example Walkthrough
- Input Hex String:
'1000202020202342'
- Base58 Encoded String: After running the above code, the Base58 encoded string of this hex string will be
4r1
. - Decoded Hex String: When decoding
4r1
, we get back the original hexadecimal string1000202020202342
.
Handling Invalid Inputs
It’s important to ensure that the input is valid before encoding or decoding. In the PHP example, we used the ctype_xdigit()
function to check whether a string is a valid hexadecimal string.
if (ctype_xdigit($input)) {
// Valid hex string, proceed with encoding
} else {
echo "Invalid hexadecimal string.\n";
}
Applications of Base58
Base58 encoding is widely used in several applications:
- Cryptocurrency: For encoding wallet addresses and public keys.
- URL shorteners: For generating unique, human-readable short URLs.
- Data storage: In systems like IPFS, where large data needs to be referenced in a compact, unique format.
Conclusion
In this guide, we learned how to encode and decode hexadecimal strings using Base58 in PHP. We provided a step-by-step explanation, code snippets, and practical examples of how to work with Base58 encoding, including how to achieve 3-character Base58 encoded strings.
Understanding and implementing Base58 encoding is essential for various use cases, from cryptocurrencies to data storage systems, and knowing how to work with it in PHP will make it easier for you to integrate Base58 encoding into your projects.
Happy coding!
Leave a Reply