【加解密與C】Base系列(三)Base85

Base85 編碼簡介

Base85(也稱為 Ascii85)是一種二進制到文本的編碼方案,用于將二進制數據轉換為可打印的ASCII字符。它的效率高于Base64,但生成的字符串可能包含特殊字符(如引號或反斜杠),需在特定場景(如JSON)中謹慎使用。

編碼原理

Base85將每4個字節(32位)的二進制數據轉換為5個Base85字符。計算公式如下:

  1. 將4字節數據視為一個32位無符號整數(大端序)。
  2. 重復除以85,取余數作為Base85字符的索引值。
  3. 將索引映射到字符集(如!u)。

示例:
假設4字節數據為0x4A3B2C1D,轉換步驟如下:

  • 數值為1,246,434,333
  • 依次除以85:
    • 1246434333 ÷ 85 = 14663933,余數28 → 字符<(索引28)。
    • 14663933 ÷ 85 = 172517,余數48 → 字符o(索引48)。
    • 繼續計算剩余字符。

常用字符集

不同實現可能使用不同字符集,常見兩種:

  1. RFC 1924版本
    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstu  
    

  2. Adobe Ascii85
    • 字符范圍:!(33)到u(117)。
    • 特殊標記:z表示4字節全零,~~~~~為數據流結束符。

注意事項

  • 數據對齊:輸入數據長度若非4字節倍數,需補零處理。
  • 特殊字符:避免在XML/JSON中直接使用,需額外轉義。
  • 效率權衡:Base85比Base64節省約1/4空間,但復雜度更高。

應用場景

  • Adobe PDF:用于內嵌二進制數據(如字體)。
  • 網絡傳輸:需要緊湊編碼的場景。
  • Git存儲:Git的二進制補丁可能使用Base85。
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>#define BLOCK_SIZE 4
#define ENCODED_BLOCK_SIZE 5// Base85編碼函數
char *base85_encode(const uint8_t *data, size_t len) {if (data == NULL || len == 0) return NULL;// 計算輸出緩沖區大小(每4字節→5字符)size_t max_out_len = ((len + BLOCK_SIZE - 1) / BLOCK_SIZE) * ENCODED_BLOCK_SIZE + 1;char *output = malloc(max_out_len);if (!output) return NULL;size_t out_index = 0;uint32_t block = 0;for (size_t i = 0; i < len; i += BLOCK_SIZE) {size_t remaining = len - i;size_t block_len = (remaining < BLOCK_SIZE) ? remaining : BLOCK_SIZE;// 構建32位大端序塊block = 0;for (size_t j = 0; j < block_len; j++) {block |= (uint32_t)data[i + j] << (24 - 8 * j);}// 全零塊縮寫為'z'if (block_len == BLOCK_SIZE && block == 0) {output[out_index++] = 'z';continue;}// 計算5個Base85字符(從高位到低位)char encoded[ENCODED_BLOCK_SIZE];for (int j = ENCODED_BLOCK_SIZE - 1; j >= 0; j--) {encoded[j] = (block % 85) + '!';block /= 85;}// 根據實際字節數復制有效字符size_t chars_to_copy = block_len + 1;  // 字節數+1for (size_t j = 0; j < chars_to_copy; j++) {output[out_index++] = encoded[j];}}output[out_index] = '\0';return output;
}// Base85解碼函數
uint8_t *base85_decode(const char *input, size_t *out_len) {if (input == NULL || out_len == NULL) return NULL;size_t in_len = strlen(input);if (in_len == 0) return NULL;// 計算最大輸出長度(每5字符→4字節)size_t max_out_len = (in_len * BLOCK_SIZE) / ENCODED_BLOCK_SIZE;uint8_t *output = malloc(max_out_len);if (!output) return NULL;size_t in_index = 0;size_t out_index = 0;uint32_t block = 0;while (in_index < in_len) {// 處理全零塊縮寫if (input[in_index] == 'z') {for (int j = 0; j < BLOCK_SIZE; j++) {output[out_index++] = 0;}in_index++;continue;}// 讀取5個字符(不足時用'u'填充)size_t chars_in_block = 0;block = 0;for (int j = 0; j < ENCODED_BLOCK_SIZE; j++) {if (in_index >= in_len) break;char c = input[in_index++];if (c < '!' || c > 'u') continue;  // 跳過無效字符block = block * 85 + (c - '!');chars_in_block++;}// 填充不足的字符while (chars_in_block < ENCODED_BLOCK_SIZE) {block = block * 85 + ('u' - '!');chars_in_block++;}// 提取4個字節(大端序)size_t bytes_to_write = chars_in_block - 1;  // 字符數-1=原始字節數for (int j = 0; j < bytes_to_write; j++) {output[out_index++] = (block >> (24 - 8 * j)) & 0xFF;}}*out_len = out_index;return output;
}// 測試函數
int main() {// 編碼測試uint8_t data[] = {0x86, 0x4F, 0xD2, 0x6F, 0xB5, 0x59, 0x00, 0x00};char *encoded = base85_encode(data, sizeof(data));printf("Encoded: %s\n", encoded);  // 輸出: L/Ch[+>Gz// 解碼測試size_t decoded_len;uint8_t *decoded = base85_decode(encoded, &decoded_len);printf("Decoded: ");for (size_t i = 0; i < decoded_len; i++) {printf("%02X ", decoded[i]);  // 輸出: 86 4F D2 6F B5 59 00 00}printf("\n");// 清理內存free(encoded);free(decoded);return 0;
}

base85的實現規則相對比較多,如果不替換原始字母表,建議使用openssl接口。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/87989.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/87989.shtml
英文地址,請注明出處:http://en.pswp.cn/web/87989.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Docker企業級應用:從入門到生產環境最佳實踐

一、Docker核心概念與架構 1.1 Docker技術棧 #mermaid-svg-CUEiyGo05ZYG524v {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-CUEiyGo05ZYG524v .error-icon{fill:#552222;}#mermaid-svg-CUEiyGo05ZYG524v .error-te…

8、保存應用數據

目錄用戶首選項的使用用戶首選項主要API用戶首選項開發流程用戶首選項開發實踐關系型數據庫的使用關系型數據庫工作流程關系型數據庫開發實踐用戶首選項的使用 用戶首選項主要API 用戶首選項開發流程 成功的獲取了一個名為myStore的Preferences實例 保存了一個鍵值對&#x…

(C++)list列表相關基礎用法(C++教程)(STL庫基礎教程)

源代碼&#xff1a;#include <iostream> #include <list>using namespace std;int main(){list<int> numbers{10,20,30};numbers.push_front(5);numbers.push_back(40);auto it numbers.begin();advance(it,2);numbers.insert(it,15);cout<<"該列…

Spring CGLIB私有方法訪問成員變量為null問題

場景 代碼 RestController public class TestJob {Autowiredprivate XxService xxService;XxlJob("testCGLIB")private void doTest(){System.out.println("方法調用");System.out.println("成員變量注入:"(xxService!null));this.doInnerTest()…

Paimon本地表查詢引擎LocalTableQuery詳解

LocalTableQueryLocalTableQuery 是 Paimon 中實現本地化、帶緩存的表查詢的核心引擎。它的主要應用場景是 Flink 中的 Lookup Join。當 Flink 作業需要根據一個流中的 Key 去關聯一個 Paimon 維表時&#xff0c;LocalTableQuery 可以在 Flink 的 TaskManager 節點上&#xff0…

使用協程簡化異步資源獲取操作

異步編程的兩種場景 在異步編程中&#xff0c;回調函數通常服務于兩種不同場景&#xff1a; 一次性資源獲取&#xff1a;等待異步操作完成并返回結果。持續事件通知。監聽并響應多個狀態變更。 Kotlin為這兩種場景提供了解決方案&#xff1a;使用掛起函數簡化一次性資源獲取…

ABP VNext + Cosmos DB Change Feed:搭建實時數據變更流服務

ABP VNext Cosmos DB Change Feed&#xff1a;搭建實時數據變更流服務 &#x1f680; &#x1f4da; 目錄ABP VNext Cosmos DB Change Feed&#xff1a;搭建實時數據變更流服務 &#x1f680;TL;DR ?&#x1f680;1. 環境與依賴 &#x1f3d7;?2. 服務注冊與依賴注入 &…

STM32-定時器

定時器&#xff1a;有4個獨立通道&#xff1a;輸入捕獲&#xff1b;輸出比較PWM生成&#xff1b;單脈沖模式輸出&#xff1b;可通外部信號控制定時器&#xff08;TIMx-ETR&#xff09;&#xff1b;支持針對定時的增量&#xff08;正交&#xff09;編碼器、霍爾傳感器電路通用定…

Windows Server 2019--職業技能大賽B模塊Windows服務器配置樣題

一、賽題說明 &#xff08;一&#xff09;競賽介紹 請詳細閱讀網絡拓撲圖&#xff0c;為所有計算機修改默認防火墻以便允許ICMP和相應的流量&#xff0c;不允許直接關閉主機的防火墻。除了CD-ROM/HDD驅動器&#xff0c;請不要修改虛擬機本身的硬件設置。 &#xff08;二&…

vue3+Echarts實現立體柱狀圖

Echarts柱狀圖中文網&#xff1a;https://echarts.apache.org/examples/zh/index.html#chart-type-bar 效果展示&#xff1a; 主要實現過程是三部分的組合&#xff0c;最上面是一個橢圓&#xff0c;中間是正常的柱子&#xff0c;下方再加上一個橢圓&#xff0c;就出來立體的效…

【UE5】虛幻引擎小百科

一、類名前面的大寫字母的含義是什么UE5常見前綴分類表前綴含義實例用于AActorACharacter&#xff0c;AWeaponBase可放入世界中的對象&#xff08;有位置、可碰撞等&#xff09;UUObject派生類UUserWidget&#xff0c;UWeaponComponent引擎對象、邏輯模塊&#xff0c;不具備Tra…

【Linux系統】vim編輯器 | 編譯器gcc/g++ | make/Makefile

1. vim編輯器一、歷史發展與Vim vs Vi的區別起源與演進Vi&#xff08;1976年&#xff09; &#xff1a;由Bill Joy開發&#xff0c;嵌入BSD Unix系統&#xff0c;是首個面向屏幕的文本編輯器&#xff0c;但功能有限&#xff08;如無多級撤銷&#xff09;。Vim&#xff08;1991年…

國產飛騰主板,賦能網絡安全防御硬手段

? 當前&#xff0c;網絡安全形勢嚴峻&#xff0c;網絡攻擊手段不斷翻新&#xff0c;從數據泄露到電腦中毒&#xff0c;企業、機構乃至國家的數字資產都面臨著巨大風險。在此背景下&#xff0c;國產硬件技術的突破對筑牢網絡安全防線意義重大。 高能計算機基于市場需求&#…

Spring AI 概述與架構設計

目錄一、前言二、簡介三、核心能力概覽四、理解模塊架構圖五、模型適配能力六、最小應用示例七、與傳統 LLM 調用相比八、總結九、參考一、前言 在 AI 正以前所未有的速度“下沉”到各類系統與業務的當下&#xff0c;Spring 官方推出的 Spring AI 項目&#xff0c;為 Java 開發…

UI前端與數字孿生融合新領域:智慧環保的污染源監測與治理

hello寶子們...我們是艾斯視覺擅長ui設計、前端開發、數字孿生、大數據、三維建模、三維動畫10年經驗!希望我的分享能幫助到您!如需幫助可以評論關注私信我們一起探討!致敬感謝感恩!一、引言&#xff1a;數字孿生重構智慧環保的技術范式在環境污染治理壓力持續增大的背景下&…

【go/wails】wails入門系列(一)環境安裝與demo

文章目錄說在前面go安裝nodejs安裝wails創建項目運行說在前面 操作系統&#xff1a;win11go版本&#xff1a;1.24.4nodejs版本&#xff1a;v22.16.0wails版本&#xff1a;v2.10.1 go安裝 官網 這里 下載安裝即可 nodejs 官網 這里 下載安裝即可 安裝wails 設置go國內代理g…

linux qt 使用log4cpp庫

一、日志庫下載 下載地址&#xff1a;https://log4cpp.sourceforge.net/二、日志庫解壓&#xff0c;編譯 1.將文件夾解壓出來2.進入文件夾內部&#xff0c;打開終端3.終端中依次輸入以下命令 mkdir build ./configure --prefix$(pwd)/build make make install 一般來說不會報錯…

探索阿里云Data Integration:數據同步的魔法工具

引言在當今數字化時代&#xff0c;數據已成為企業的核心資產&#xff0c;如同企業發展的 “燃料”&#xff0c;驅動著業務的增長與創新。從用戶行為數據到業務運營數據&#xff0c;從市場趨勢數據到供應鏈數據&#xff0c;每一個數據點都蘊含著巨大的價值&#xff0c;能夠為企業…

【Java面試】Redis的poll函數epoll函數區別?

Redis 在選擇 poll 和 epoll 時主要基于性能需求、連接規模、操作系統支持等因素。以下是具體場景的對比與選擇建議&#xff1a;1. 何時使用 poll 函數&#xff1f;適用場景&#xff1a; 跨平臺兼容性需求&#xff1a;poll 在幾乎所有操作系統&#xff08;如 Windows、BSD、Lin…

RPC--RPCHandler的實現

在RPC框架中&#xff0c;Handler用于接收RpcRequest&#xff0c;經過處理后返回RpcResponseSlf4jpublic class RpcRequestHandler {private final ServiceProvider serviceProvider;//獲取一個單例模式的服務提供類public RpcRequestHandler() {serviceProvider SingletonFact…