Base64原理与实现
Base64编码说明
Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。 如果剩下的字符不足3个字节,则用0填充,输出字符使用'=',因此编码后输出的文本末尾可能会出现1或2个'='。
为了保证所输出的编码位可读字符,Base64制定了一个编码表,以便进行统一转换。编码表的大小为2^6=64,这也是Base64名称的由来。
Base64编码表
码值 | 字符 | 码值 | 字符 | 码值 | 字符 | 码值 | 字符 | |||
---|---|---|---|---|---|---|---|---|---|---|
0 | A | 16 | Q | 32 | g | 48 | w | |||
1 | B | 17 | R | 33 | h | 49 | x | |||
2 | C | 18 | S | 34 | i | 50 | y | |||
3 | D | 19 | T | 35 | j | 51 | z | |||
4 | E | 20 | U | 36 | k | 52 | 0 | |||
5 | F | 21 | V | 37 | l | 53 | 1 | |||
6 | G | 22 | W | 38 | m | 54 | 2 | |||
7 | H | 23 | X | 39 | n | 55 | 3 | |||
8 | I | 24 | Y | 40 | o | 56 | 4 | |||
9 | J | 25 | Z | 41 | p | 57 | 5 | |||
10 | K | 26 | a | 42 | q | 58 | 6 | |||
11 | L | 27 | b | 43 | r | 59 | 7 | |||
12 | M | 28 | c | 44 | s | 60 | 8 | |||
13 | N | 29 | d | 45 | t | 61 | 9 | |||
14 | O | 30 | e | 46 | u | 62 | + | |||
15 | P | 31 | f | 47 | v | 63 | / |
C++实现:
base64.h
#ifndef _BASE64_HH
#define _BASE64_HH #ifdef __cplusplus
extern "C" {
#endif //__cplusplus unsigned char* base64Decode(char* pszInput, unsigned int& iReturnSize, bool trimTrailingZeros = true); char* base64Encode(char const* origSigned, unsigned iOrigLength); #ifdef __cplusplus
}
#endif //__cplusplus #endif //_BASE64_HH
base64.cpp
#include "base64.h"
#include <string.h> static char base64DecodeTable[];
//初始化编码对照表
static const char base64Char[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; char* strDupSize(char const* str)
{
if (str == NULL) return NULL;
size_t len = strlen(str) + ;
char* copy = new char[len]; return copy;
} //初始化解码对照表
static void initBase64DecodeTable()
{
for (int i = ; i < ; ++i)
base64DecodeTable[i] = (char)0x80; // default value: invalid for (int i = 'A'; i <= 'Z'; ++i)
base64DecodeTable[i] = + (i - 'A');
for (int i = 'a'; i <= 'z'; ++i)
base64DecodeTable[i] = + (i - 'a');
for (int i = ''; i <= ''; ++i)
base64DecodeTable[i] = + (i - '');
base64DecodeTable[(unsigned char)'+'] = ;
base64DecodeTable[(unsigned char)'/'] = ;
base64DecodeTable[(unsigned char)'='] = ; //0x40
} // 解码
unsigned char* base64Decode(char* pszInput, unsigned int& iReturnSize, bool trimTrailingZeros)
{
static bool haveInitedBase64DecodeTable = false;
if (!haveInitedBase64DecodeTable)
{
initBase64DecodeTable();
haveInitedBase64DecodeTable = true;
} unsigned char* pszOutput = new unsigned char[strlen(pszInput)];
int k = ;
/*******************************************************************************************
*技巧:先减去3 ---in case "pszInput" is not a multiple of 4 bytes (although it should be) *
* 个人觉得这里不用做处理,因为编码时候已经做过处理,密文肯定为4的整数倍 *
*******************************************************************************************/
int const jMax = strlen(pszInput) - ; //将密文四个字节为一组,每组解码为三个字节
for (int j = ; j < jMax; j += )
{
char inTmp[], outTmp[];
for (int i = ; i < ; ++i)
{
inTmp[i] = pszInput[i+j];
outTmp[i] = base64DecodeTable[(unsigned char)inTmp[i]];
if ((outTmp[i]&0x40) != ) //如果遇到'=',将其视为结束字符
outTmp[i] = 0x00;
} pszOutput[k++] = (outTmp[]<<) | (outTmp[]>>);
pszOutput[k++] = (outTmp[]<<) | (outTmp[]>>);
pszOutput[k++] = (outTmp[]<<) | outTmp[];
} if (trimTrailingZeros)
{
while (k > && pszOutput[k-] == '\')
--k;
}
iReturnSize = k;
unsigned char* result = new unsigned char[iReturnSize];
memset(result, , iReturnSize);
memmove(result, pszOutput, iReturnSize);
delete[] pszOutput;
return result;
} // 编码
char* base64Encode(char const* origSigned, unsigned iOrigLength)
{
unsigned char const* orig = (unsigned char const*)origSigned;
if (orig == NULL)
return NULL; unsigned const iNumResultBytes = *(iOrigLength/ + (iOrigLength% ? : ));
char* result = new char[iNumResultBytes + ]; //源码三个字节为一组,编码后将三个字节变为四个字节
unsigned i;
for (i = ; i < iOrigLength/; ++i)
{
// 取源码的第一个字节的前六位,前面加两个零生成第一个字节
result[*i+] = base64Char[(orig[*i]>>) & 0x3F];
// 取源码的第一个字节的后两位和第二个字节的前四位,前面补两个零生成第二个字节
result[*i+] = base64Char[((orig[*i]<<) | (orig[*i+]>>)) & 0x3F];
// 取源码的第二个字节的后四位和第三个字节的前两位,前面补两个零生成第三个字节
result[*i+] = base64Char[((orig[*i+]<<) | (orig[*i+]>>)) & 0x3F];
// 取源码的第三个字节的后六位,前面补两个零生成第四个字节
result[*i+] = base64Char[orig[*i+]&0x3F];
}
//不足三个字节的最后补'='字符,补足三个字节
if (iOrigLength%)
{
result[*i+] = base64Char[(orig[*i]>>) & 0x3F];
if (iOrigLength% == )
{
result[*i+] = base64Char[((orig[*i]<<) | (orig[*i+]>>))&0x3F];
result[*i+] = base64Char[(orig[*i+]<<)&0x3C];
}
else
{
result[*i+] = base64Char[((orig[*i])<<)&0x3F];
result[*i+] = '=';
}
result[*i+] = '=';
} result[iNumResultBytes] = '\0';
return result;
}
测试代码main.cpp
#include "base64.h"
#include <iostream> using namespace std; int main()
{
cout << "请输入要转换的字符串(支持中文):" << endl;
char szStrOrigin[];
scanf("%s", szStrOrigin);
unsigned int iReturnSize;
cout << "编码之前字符串:" << szStrOrigin << endl;
char *pEncodeStr = base64Encode(szStrOrigin, strlen(szStrOrigin));
cout << "编码之后字符串:" << pEncodeStr << endl;
unsigned char *pDecodeStr = base64Decode(pEncodeStr, iReturnSize);
cout << "解码之后字符串:" << pDecodeStr << endl;
system("pause");
}
运行结果:
Base64原理与实现的更多相关文章
- Base64原理
一.Base64编码由来 为什么会有Base64编码呢?因为有些网络传送渠道并不支持所有的字节,例如传统的邮件只支持可见字符的传送,像ASCII码的控制字符就 不能通过邮件传送.这样用途就受到了很大的 ...
- Base64原理解析
一. Base64编码由来 为什么会有Base64编码呢?因为有些网络传送渠道并不支持所有的字节,例如传统的邮件只支持可见字符的传送,像ASCII码的控制字符就 不能通过邮件传送.这样用途就受到了很大 ...
- Base64原理解析与使用
一.Base64编码由来 为什么会有Base64编码呢?因为有些网络传送渠道并不支持所有的字节,例如传统的邮件只支持可见字符的传送,像ASCII码的控制字符就 不能通过邮件传送.这样用途就受到了很大的 ...
- 一份简明的 Base64 原理解析
书接上回,在 记一个 Base64 有关的 Bug 一文里,我们说到了 Base64 的编解码器有不同实现,交叉使用它们可能引发的问题等等. 这一回,我们来对 Base64 这一常用编解码技术的原理一 ...
- base64原理,使用场景
Base64编码,是我们程序开发中经常使用到的编码方法.它是一种基于用64个可打印字符来表示二进制数据的表示方法.它通常用作存储.传输一些二进制数据编码方法!也是MIME(多用途互联网邮件扩展,主要用 ...
- Base64原理简介
Base64是一种编码方式,通常用于将二进制数据转换成可见字符的形式,该过程可逆. 过程大致如下: 1. 对64个可见字符,进行一个索引编码.索引是二进制的值,对应找到一个可见字符. Base64 编 ...
- base64 原理
Base64编码之所以称为Base64,是因为其使用64个字符来对任意数据进行编码,同理有Base32.Base16编码.标准Base64编码使用的64个字符为: 这64个字符是各种字符编码(比如AS ...
- Base64原理 bits 3->4 8bits/byte-->6bits/byte
实践: window.btoa('a')a YQ==abcdef YWJjZGVmabc YWJjab YWI= https://en.wikipedia.org/wiki/Base64 The Ba ...
- php base64 原理
#include <stdio.h> #include <stdlib.h> #include <string.h> static const char base6 ...
随机推荐
- 【BZOJ】1854: [Scoi2010]游戏【二分图】
1854: [Scoi2010]游戏 Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 6759 Solved: 2812[Submit][Status] ...
- 【BZOJ-2329&2209】括号修复&括号序列 Splay
2329: [HNOI2011]括号修复 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 1007 Solved: 476[Submit][Statu ...
- mysql exists 如何使用
还没时间看,exists用的少 ==>当你只需要判断后面的查询结果是否存 在时使用exists() http://edu.codepub.com/2011/0208/29218.php 今天正 ...
- WCF消息传递
通过了解了WCF的一些基本概念并创建和编写WCF应用中的相应方法,实现了WCF服务和客户端之间的调用,就能够理解WCF应用是如何进行通信的.了解了一些基本的WCF概念后,还需要深入了解WCF消息的概念 ...
- vs2012\vs2013\vs2015碰到生成时报该错误:项目中不存在目标“GatherAllFilesToPublish”
手头一个vs2010升级到vs2012后,web项目发布到本地目录时项目报错:“该项目中不存在目标“GatherAllFilesToPublish”” 通过谷歌大神的帮助,找到了解决方法.共享之. 原 ...
- In-Place upgrade to Team Foundation Server (TFS) 2015 from TFS 2013Team Foundation Server TFS TFS 2015 TFS upgrade TFS with Sharepoint
This upgrade document gives detailed step by step procedure for the In-Place upgrade from TFS 2013 t ...
- 集群服务器下使用SpringBoot @Scheduled注解定时任务
原文:https://blog.csdn.net/huyang1990/article/details/78551578 SpringBoot提供了 Schedule模块完美支持定时任务的执行 在实际 ...
- C#编程(三十八)----------运算符
原文链接: http://blog.csdn.net/shanyongxu/article/details/46877353 运算符 类别 运算符 算术运算符 + - * / 逻辑运算符 & ...
- 记linux下rm误删bin文件的解决方式
平常有个坏习惯,删文件为了快点,喜欢用rm xx*,删除一些关键词文件.今天为了删/bin下几个含有mix关键词的文件,使用命令rm mix*.手贱,mix和*之间多了个空格...灾难发生了!bin下 ...
- 解决html5 audio iphone,ipd,safari不能自动播放问题
html audio 在iPhone,ipd,safari浏览器不能播放是有原因滴 (在safri on ios里面明确指出等待用户的交互动作后才能播放media,也就是说如果你没有得到用户的acti ...