当前位置: 首页 > article >正文

c++ Base58编码解码

Base58

  • 字符集 Base58 使用 58 个字符进行编码,字符集为:123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz。注意:0(零)、O(大写字母O)、I(大写字母I)和 l(小写字母L)等字符被排除,以避免视觉上的混淆。

  • 编码长度:Base58 编码和 Base64 类似,但由于字符集更小,编码后的长度比 Base64 稍短。

  • 应用场景

  • 主要用于加密货币(如比特币)中,作为钱包地址等信息的编码方式。

  • 由于字符集避免了视觉上容易混淆的字符,因此在用户界面中显示时更为友好。

  • 示例

"Hello" -> "JxF12TrwUP45p7r"
#include <iostream>
#include <vector>
#include <assert.h>
using namespace std;/** All alphanumeric characters except for "0", "I", "O", and "l" */
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
static const int8_t mapBase58[256] = {-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 1, 2, 3, 4, 5, 6,  7, 8,-1,-1,-1,-1,-1,-1,-1, 9,10,11,12,13,14,15, 16,-1,17,18,19,20,21,-1,22,23,24,25,26,27,28,29, 30,31,32,-1,-1,-1,-1,-1,-1,33,34,35,36,37,38,39, 40,41,42,43,-1,44,45,46,47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
};
constexpr inline bool IsSpace(char c) noexcept {return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v';
}bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch, int max_ret_len)
{// Skip leading spaces.while (*psz && IsSpace(*psz))psz++;// Skip and count leading '1's.int zeroes = 0;int length = 0;while (*psz == '1') {zeroes++;if (zeroes > max_ret_len) return false;psz++;}// Allocate enough space in big-endian base256 representation.int size = strlen(psz) * 733 / 1000 + 1; // log(58) / log(256), rounded up.std::vector<unsigned char> b256(size);// Process the characters.static_assert(sizeof(mapBase58) / sizeof(mapBase58[0]) == 256, "mapBase58.size() should be 256"); // guarantee not out of rangewhile (*psz && !IsSpace(*psz)) {// Decode base58 characterint carry = mapBase58[(uint8_t)*psz];if (carry == -1)  // Invalid b58 characterreturn false;int i = 0;for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {carry += 58 * (*it);*it = carry % 256;carry /= 256;}assert(carry == 0);length = i;if (length + zeroes > max_ret_len) return false;psz++;}// Skip trailing spaces.while (IsSpace(*psz))psz++;if (*psz != 0)return false;// Skip leading zeroes in b256.std::vector<unsigned char>::iterator it = b256.begin() + (size - length);// Copy result into output vector.vch.reserve(zeroes + (b256.end() - it));vch.assign(zeroes, 0x00);while (it != b256.end())vch.push_back(*(it++));return true;
}std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
{// Skip & count leading zeroes.int zeroes = 0;int length = 0;while (pbegin != pend && *pbegin == 0) {pbegin++;zeroes++;}// Allocate enough space in big-endian base58 representation.int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up.std::vector<unsigned char> b58(size);// Process the bytes.while (pbegin != pend) {int carry = *pbegin;int i = 0;// Apply "b58 = b58 * 256 + ch".for (auto it = b58.rbegin();(carry != 0 || i < length) && (it != b58.rend());it++, i++) {carry += 256 * (*it);*it = carry % 58;carry /= 58;}assert(carry == 0);length = i;pbegin++;}// Skip leading zeroes in base58 result.std::vector<unsigned char>::iterator it = b58.begin() + (size - length);while (it != b58.end() && *it == 0)it++;// Translate the result into a string.std::string str;str.reserve(zeroes + (b58.end() - it));str.assign(zeroes, '1');while (it != b58.end())str += pszBase58[*(it++)];return str;
}int main(int argc, char argv[])
{unsigned char data[] = "测试base58数据";int len = sizeof(data);cout << data << endl;std::string re = EncodeBase58(data, data + len);cout << re << endl;std::vector<unsigned char> vsh;DecodeBase58(re.data(), vsh, 4096);cout << vsh.data() << endl;return 0;
}
http://www.lryc.cn/news/2402835.html

相关文章:

  • 证券交易柜台系统解析与LinkCounter解决方案开发实践
  • XXTEA,XTEA与TEA
  • 机器人玩转之---嵌入式开发板基础知识到实战选型指南(包含ORIN、RDK X5、Raspberry pi、RK系列等)
  • 腾讯云国际版和国内版账户通用吗?一样吗?为什么?
  • OrCAD X Capture CIS设计小诀窍系列第二季--03.如何在Capture中输出带有目录和元器件信息的PDF
  • 汽车的安全性能测试:试验台铁地板的重要性
  • Lua和JS的垃圾回收机制
  • 实践指南:从零开始搭建RAG驱动的智能问答系统
  • 边缘计算服务器
  • 矩阵的偏导数
  • 第R9周:阿尔茨海默病诊断(优化特征选择版)
  • 电动螺丝刀-多实体拆图建模案例
  • 当丰收季遇上超导磁测量:粮食产业的科技新征程
  • 电子电气架构 --- 什么是功能架构?
  • Android四大组件通讯指南:Kotlin版组件茶话会
  • C++.OpenGL (11/64)材质(Materials)
  • AudioRelay 0.27.5 手机充当电脑音响
  • 会计 - 合并1- 业务、控制、合并日
  • 前端项目eslint配置选项详细解析
  • NVIDIA Dynamo:数据中心规模的分布式推理服务框架深度解析
  • 第十三节:第四部分:集合框架:HashMap、LinkedHashMap、TreeMap
  • Spring AI之RAG入门
  • 应用案例 | 设备分布广, 现场维护难? 宏集Cogent DataHub助力分布式锅炉远程运维, 让现场变“透明”
  • C#中的密封类与静态类:特性、区别与应用实例
  • LINUX 66 FTP 2 ;FTP被动模式;FTP客户服务系统
  • 网心云 OEC/OECT 笔记(2) 运行RKNN程序
  • vue-21 (使用 Vuex 模块和异步操作构建复杂应用)
  • #开发环境篇:postMan可以正常调通,但是浏览器里面一直报403
  • 将word文件转为kindle可识别的azw3文件的方法
  • 动态规划之01背包