89 lines
2.5 KiB
C++
89 lines
2.5 KiB
C++
#include "base58.h"
|
|
#include <algorithm>
|
|
#include <stdexcept>
|
|
|
|
const std::string Base58::ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
|
|
std::string Base58::encode(const std::vector<unsigned char>& data) {
|
|
if (data.empty()) {
|
|
return "";
|
|
}
|
|
|
|
// Skip leading zeros
|
|
size_t leading_zeros = 0;
|
|
while (leading_zeros < data.size() && data[leading_zeros] == 0) {
|
|
leading_zeros++;
|
|
}
|
|
|
|
// Convert to base58
|
|
std::vector<unsigned char> digits((data.size() - leading_zeros) * 138 / 100 + 1);
|
|
size_t digitslen = 1;
|
|
|
|
for (size_t i = leading_zeros; i < data.size(); i++) {
|
|
unsigned int carry = data[i];
|
|
for (size_t j = 0; j < digitslen; j++) {
|
|
carry += (unsigned int)(digits[j]) << 8;
|
|
digits[j] = carry % 58;
|
|
carry /= 58;
|
|
}
|
|
while (carry > 0) {
|
|
digits[digitslen++] = carry % 58;
|
|
carry /= 58;
|
|
}
|
|
}
|
|
|
|
// Convert to string
|
|
std::string result;
|
|
for (size_t i = 0; i < leading_zeros; i++) {
|
|
result += ALPHABET[0];
|
|
}
|
|
for (size_t i = 0; i < digitslen; i++) {
|
|
result += ALPHABET[digits[digitslen - 1 - i]];
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
std::vector<unsigned char> Base58::decode(const std::string& encoded) {
|
|
if (encoded.empty()) {
|
|
return std::vector<unsigned char>();
|
|
}
|
|
|
|
// Skip leading '1's (which represent leading zeros)
|
|
size_t leading_ones = 0;
|
|
while (leading_ones < encoded.length() && encoded[leading_ones] == '1') {
|
|
leading_ones++;
|
|
}
|
|
|
|
// Convert from base58
|
|
std::vector<unsigned char> bytes((encoded.length() - leading_ones) * 733 / 1000 + 1);
|
|
size_t byteslen = 1;
|
|
|
|
for (size_t i = leading_ones; i < encoded.length(); i++) {
|
|
unsigned int carry = ALPHABET.find(encoded[i]);
|
|
if (carry == std::string::npos) {
|
|
throw std::invalid_argument("Invalid character in Base58 string");
|
|
}
|
|
|
|
for (size_t j = 0; j < byteslen; j++) {
|
|
carry += (unsigned int)(bytes[j]) * 58;
|
|
bytes[j] = carry & 0xff;
|
|
carry >>= 8;
|
|
}
|
|
while (carry > 0) {
|
|
bytes[byteslen++] = carry & 0xff;
|
|
carry >>= 8;
|
|
}
|
|
}
|
|
|
|
// Add leading zeros
|
|
std::vector<unsigned char> result(leading_ones + byteslen);
|
|
for (size_t i = 0; i < leading_ones; i++) {
|
|
result[i] = 0;
|
|
}
|
|
for (size_t i = 0; i < byteslen; i++) {
|
|
result[leading_ones + i] = bytes[byteslen - 1 - i];
|
|
}
|
|
|
|
return result;
|
|
} |