base64加密换行符
㈠ 求进行base64解码的思路
关于这个编码的规则:
①.把3个字符变成4个字符..
②每76个字符加一个换行符..
③.最后的结束符也要处理..
对于①就是 4个字符32位..有个字符..24位...相差8个位..这8个位..会平均分给每个字节的高两位..则好2*4 = 8.吗...
下面是我用C++实现的...带有注释...通过移位操作实现的...对移位操作不熟悉的朋友可能有点吃力了...
void base642(char * string ,char * pch)
{
int i = 0;
BYTE b1 ,b2 ,b3;
CAtlStringA str(string);
int len = str.GetLength();
char b;
do
{
//
b1 = string[i++];
//b1 右移2位..高2位清0...
//b1.剩下2位要放在第2个字符中..
b = BASE64TABLE[b1>>2];
//得到第1个字符..
*pch ++ = b;
//判断是不是该换行了..76个字符要换行.放在这里..避免i=1的时候换行..
if(i % 76 == 0)
{
*pch ++ = '\r';
*pch ++ = '\n';
}
b2 = string[i++];
//(b1的最后2位要放在b2的第6位(7.8两位要填充0))b1.要左移4位... b2 右移4位...然后相加..在把最高2位清0..
//b2.剩下4位.要放在第3个字符中...
b = BASE64TABLE[((b1 << 4) + (b2 >> 4)) &(0x3f)];
//得到第2个字符..
*pch ++ = b;
//如果没有第3个字符了..那就停止循环了..
////这里不能是>= ...因为还要处理最后一个0x00结束符..len不包含最后结束符...
if(i > len)
break;//①
b3 = (BYTE) string[i++];
//b2的4位要放在第3个字符的第6位...b2.要左移2位...b3要右移6位..高2位放在此字符的最后两位..
//b3 就剩下了6个字符...
b = BASE64TABLE[((b2 << 2) + (b3 >>6)) &(0x3f)];
*pch ++ = b;
//如果超过了.就停止了吧..
if(i > len)
break;//②
///b3高2位清0 .就可以得到第4个字符...
b = BASE64TABLE[b3 &(0x3f)];
*pch ++ = b;
}while(i < len);
//取得余数..
int resie = len % 3;
///判断最后要加几个=号..
int y = (resie == 1) ? 2 : (resie == 2 ? 1 : 0) ;
for(int i = 0;i< y ;i++)
*pch++ = '=';
/*
这个算法...当中的break.总是感觉会丢失位...
但是仔细一想.最后一字符是0x00....丢失了..也不要紧..
假设有1个字符.. 加上一个结束符..实际上是两个字符..到①这个位置会break...丢失了4位...这4位全部是0..
假设有2个字符..加上一个结束符..实际上是三个字符.到②这个位置会break..丢失6位..同伴全部是0..
假设有3个字符...刚好处理完毕...最后一个结束符..不会处理了...
*/
}
void base642(char * string ,char * pch)
{
int i = 0;
BYTE b1 ,b2 ,b3;
CAtlStringA str(string);
int len = str.GetLength();
char b;
do
{
//
b1 = string[i++];
//b1 右移2位..高2位清0...
//b1.剩下2位要放在第2个字符中..
b = BASE64TABLE[b1>>2];
//得到第1个字符..
*pch ++ = b;
//判断是不是该换行了..76个字符要换行.放在这里..避免i=1的时候换行..
if(i % 76 == 0)
{
*pch ++ = '\r';
*pch ++ = '\n';
}
b2 = string[i++];
//(b1的最后2位要放在b2的第6位(7.8两位要填充0))b1.要左移4位... b2 右移4位...然后相加..在把最高2位清0..
//b2.剩下4位.要放在第3个字符中...
b = BASE64TABLE[((b1 << 4) + (b2 >> 4)) &(0x3f)];
//得到第2个字符..
*pch ++ = b;
//如果没有第3个字符了..那就停止循环了..
////这里不能是>= ...因为还要处理最后一个0x00结束符..len不包含最后结束符...
if(i > len)
break;//①
b3 = (BYTE) string[i++];
//b2的4位要放在第3个字符的第6位...b2.要左移2位...b3要右移6位..高2位放在此字符的最后两位..
//b3 就剩下了6个字符...
b = BASE64TABLE[((b2 << 2) + (b3 >>6)) &(0x3f)];
*pch ++ = b;
//如果超过了.就停止了吧..
if(i > len)
break;//②
///b3高2位清0 .就可以得到第4个字符...
b = BASE64TABLE[b3 &(0x3f)];
*pch ++ = b;
}while(i < len);
//取得余数..
int resie = len % 3;
///判断最后要加几个=号..
int y = (resie == 1) ? 2 : (resie == 2 ? 1 : 0) ;
for(int i = 0;i< y ;i++)
*pch++ = '=';
/*
这个算法...当中的break.总是感觉会丢失位...
但是仔细一想.最后一字符是0x00....丢失了..也不要紧..
假设有1个字符.. 加上一个结束符..实际上是两个字符..到①这个位置会break...丢失了4位...这4位全部是0..
假设有2个字符..加上一个结束符..实际上是三个字符.到②这个位置会break..丢失6位..同伴全部是0..
假设有3个字符...刚好处理完毕...最后一个结束符..不会处理了...
*/
}
这个是解码的函数.
view plain to clipboardprint?
void base644(char * string ,char * pch)
{
CAtlStringA tab("+/");
CAtlStringA str(string);
str.Remove('=');
str.Remove('\r');
str.Remove('\n');
int len = str.GetLength();
int i = 0;
BYTE b1 ,b2 ,b3 ,b4;
char ch;
do
{
//找字符1的位置.
b1 = tab.Find((str[i++]));
//找字符2的位置.
b2 = tab.Find((str[i++]));
//b1左移两位..还原.此时少了最后两位...b2的第6位和第5位..要右移4位(变成最后两位.)..此时和b1相加...即可
//b1还原...
ch = (b1 << 2) + (b2 >> 4);
//得到此字节..
*pch ++ = ch;
//超过了..break吧..这是要有这个=号...当=成立的时候.表明已经是最后一个字符了...后面不要处理..
if(i >= len)
break;
//取第3个字符..的位置
b3 = tab.Find((str[i++]));
//从这里开始判断..因为=号最多有两个...换行是额外加的..所以编码后有效的字符至少为2个..
//还原第2个字符...b2中有b1的两个位..所以b2左移4位..即可把b1的两个位和00两个最高位去除..b2中只有
//有效的4个位..b3中还有4个位....b3右移2位..即可把5位6位变成低4位..因为要相加的..
ch = (b2 <<4) + (b3 >> 2);
*pch ++ = ch;
//超过了..break吧.
if(i >= len)
break;
//找第4个字符..
b4 = tab.Find((str[i++]));
//还原第3个字符...b3中有两个位...要放在最高两位...所以左移6位..加上b4即可..(b4的高两位为0..)
ch = (b3 << 6) + b4;
*pch ++ = ch;
}
while(i < len);
////最后加个结束符...
*pch =0x00;
}
void base644(char * string ,char * pch)
{
CAtlStringA tab("+/");
CAtlStringA str(string);
str.Remove('=');
str.Remove('\r');
str.Remove('\n');
int len = str.GetLength();
int i = 0;
BYTE b1 ,b2 ,b3 ,b4;
char ch;
do
{
//找字符1的位置.
b1 = tab.Find((str[i++]));
//找字符2的位置.
b2 = tab.Find((str[i++]));
//b1左移两位..还原.此时少了最后两位...b2的第6位和第5位..要右移4位(变成最后两位.)..此时和b1相加...即可
//b1还原...
ch = (b1 << 2) + (b2 >> 4);
//得到此字节..
*pch ++ = ch;
//超过了..break吧..这是要有这个=号...当=成立的时候.表明已经是最后一个字符了...后面不要处理..
if(i >= len)
break;
//取第3个字符..的位置
b3 = tab.Find((str[i++]));
//从这里开始判断..因为=号最多有两个...换行是额外加的..所以编码后有效的字符至少为2个..
//还原第2个字符...b2中有b1的两个位..所以b2左移4位..即可把b1的两个位和00两个最高位去除..b2中只有
//有效的4个位..b3中还有4个位....b3右移2位..即可把5位6位变成低4位..因为要相加的..
ch = (b2 <<4) + (b3 >> 2);
*pch ++ = ch;
//超过了..break吧.
if(i >= len)
break;
//找第4个字符..
b4 = tab.Find((str[i++]));
//还原第3个字符...b3中有两个位...要放在最高两位...所以左移6位..加上b4即可..(b4的高两位为0..)
ch = (b3 << 6) + b4;
*pch ++ = ch;
}
while(i < len);
////最后加个结束符...
*pch =0x00;
}
//下面是测试程序.
view plain to clipboardprint?
int _tmain(int argc, _TCHAR* argv[])
{
char pch[0x1dc]={0};
CAtlStringA str("谢谢你啊" );
CStrBufA buf(str);
base642(CStrBufA::PXSTR(buf),pch);
cout <<pch<<endl;
cout <<"********************************************************************************"<<endl;
CAtlStringA str2 = "0LvQu8TjsKE=";
CStrBufA buf2(str2);
RtlZeroMemory(pch ,0x1dc);
base644(CStrBufA::PXSTR(buf2) ,pch);
cout <<pch<<endl;
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
char pch[0x1dc]={0};
CAtlStringA str("谢谢你啊" );
CStrBufA buf(str);
base642(CStrBufA::PXSTR(buf),pch);
cout <<pch<<endl;
cout <<"********************************************************************************"<<endl;
CAtlStringA str2 = "0LvQu8TjsKE=";
CStrBufA buf2(str2);
RtlZeroMemory(pch ,0x1dc);
base644(CStrBufA::PXSTR(buf2) ,pch);
cout <<pch<<endl;
return 0;
}
用到的数组.
const char BASE64TABLE[64]={
'A','B','C','D','E','F','G','H','I','J','K','L','M','N',
'O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b',
'c','d','e','f','g','h','i','j','k','l','m','n','o','p',
'q','r','s','t','u','v','w','x','y','z','0','1','2','3',
'4','5','6','7','8','9','+','/'
};
这个作用就是....26刚好64...base64会计算每个字符的6位...然后从这个表中选中一个字母.作为最后的编码...base64当中没有其它的字符了...
如果字符数不是3的倍数..就相应的加上=号..最多有两个等号了..纯粹是为了凑数...
上面是C的,下面是C++的:
#include <string>
using namespace std;
class ZBase64
{
public:
/*编码
DataByte
[in]输入的数据长度,以字节为单位
*/
string Encode(const unsigned char* Data,int DataByte);
/*解码
DataByte
[in]输入的数据长度,以字节为单位
OutByte
[out]输出的数据长度,以字节为单位,请不要通过返回值计算
输出数据的长度
*/
string Decode(const char* Data,int DataByte,int& OutByte);
};
#include "stdAfx.h"
#include "ZBase64.h"
string ZBase64::Encode(const unsigned char* Data,int DataByte)
{
//编码表
const char EncodeTable[]="+/";
//返回值
string strEncode;
unsigned char Tmp[4]={0};
int LineLength=0;
for(int i=0;i<(int)(DataByte / 3);i++)
{
Tmp[1] = *Data++;
Tmp[2] = *Data++;
Tmp[3] = *Data++;
strEncode+= EncodeTable[Tmp[1] >> 2];
strEncode+= EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];
strEncode+= EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];
strEncode+= EncodeTable[Tmp[3] & 0x3F];
if(LineLength+=4,LineLength==76) {strEncode+="\r\n";LineLength=0;}
}
//对剩余数据进行编码
int Mod=DataByte % 3;
if(Mod==1)
{
Tmp[1] = *Data++;
strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4)];
strEncode+= "==";
}
else if(Mod==2)
{
Tmp[1] = *Data++;
Tmp[2] = *Data++;
strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];
strEncode+= EncodeTable[((Tmp[2] & 0x0F) << 2)];
strEncode+= "=";
}
return strEncode;
}
string ZBase64::Decode(const char* Data,int DataByte,int& OutByte)
{
//解码表
const char DecodeTable[] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62, // '+'
0, 0, 0,
63, // '/'
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'
0, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z'
0, 0, 0, 0, 0, 0,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z'
};
//返回值
string strDecode;
int nValue;
int i= 0;
while (i < DataByte)
{
if (*Data != '\r' && *Data!='\n')
{
nValue = DecodeTable[*Data++] << 18;
nValue += DecodeTable[*Data++] << 12;
strDecode+=(nValue & 0x00FF0000) >> 16;
OutByte++;
if (*Data != '=')
{
nValue += DecodeTable[*Data++] << 6;
strDecode+=(nValue & 0x0000FF00) >> 8;
OutByte++;
if (*Data != '=')
{
nValue += DecodeTable[*Data++];
strDecode+=nValue & 0x000000FF;
OutByte++;
}
}
i += 4;
}
else// 回车换行,跳过
{
Data++;
i++;
}
}
return strDecode;
}
使用示例(结合CxImage库):
CString CScanDlg::EncodeImage()
{//对图片进行Base64编码
ZBase64 zBase;
//图片编码
CxImage image; // 定义一个CxImage对象
image.Load(this->m_strImgPath, CXIMAGE_FORMAT_JPG); //先装载jpg文件,需要指定文件类型
long size=0;//得到图像大小
BYTE* buffer=0;//存储图像数据的缓冲
image.Encode(buffer,size,CXIMAGE_FORMAT_JPG);//把image对象中的图像以type类型数据到buffer
string strTmpResult=zBase.Encode(buffer,size);
CString result;
result = strTmpResult.c_str();
return result;
}
void CScanDlg::DecodeImageData(CString strData)
{//对Base64编码过的数据解码并显示原图片
ZBase64 zBase;
int OutByte=0;
string strTmpResult=zBase.Decode(strData,strData.GetLength(),OutByte);
int i,len = strTmpResult.length();
BYTE *buffer = new BYTE[len];
for (i=0;i<len;++i)
{
buffer[i] = strTmpResult[i];
}
CxImage image(buffer,len,CXIMAGE_FORMAT_JPG);//把内存缓冲buffer中的数据构造成Image对象
delete [] buffer;
CDC* hdc = m_picture.GetDC();
m_bitmap = image.MakeBitmap(hdc->m_hDC);
HBITMAP h0ldBmp = m_picture.SetBitmap(m_bitmap);
if(h0ldBmp) DeleteObject(h0ldBmp);
if(hdc->m_hDC) m_picture.ReleaseDC(hdc);
if(m_bitmap) DeleteObject(m_bitmap);
}
㈡ 求助 关于Base64解码的问题
BASE64编码,有几点注意,第一,编码的时候是否添加换行符,第二,空字符即“=”你是否处理了,第三,解码时的逻辑是否和编码相符合。
㈢ 如何使用Base64进行加密和解密
其实Base64的加密和解密的算法不是很复杂,首先是定义自己64位的密钥,64个字符是固定,但是顺序是可以随自己的设计而变化。例如:
char[] BaseTable=new char[64]{
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9','+','/'};
接下来,在加密的时候就是对于需要加密的每个字符,通过一定的算法,转换成上面64字符的一种;而在解密的时候则是把64字符中任意一个字符反算出加密前的字符。对于每个字符的操作有很多方法,这里就不一一介绍了。需要注意的是“=”字符,在Base64加密算法中,是很重要的,它是起到补零作用。
以下是完整代码:
//----------------------------- Base64 class --------------------------------------
//---------------------------------------------------------------------------------
//---File:clsBase64
//---Description:The class file to encode string or decode string in base algorith
//---Author:Knight
//---Date:Oct.8, 2005
//---------------------------------------------------------------------------------
//----------------------------{ Base64 class }-------------------------------------
using System;
namespace Base64
{
/// <summary>
/// Summary description for clsBase64.
/// </summary>
public class clsBase64
{
private char[] source;
private char[] lookupTable;
private int length, length2, length3;
private int blockCount;
private int paddingCount;
public clsBase64()
{
//
// TODO: Add constructor logic here
//
source = null;
length = length2 = length3 =0;
blockCount = 0;
paddingCount = 0;
}
/// <summary>
/// Create base64 char array using default base64 char array
/// </summary>
/// <param name="CreatePara"></param>
/// <returns>return the new base64 char array</returns>
private char[] CreateBase64Char( ref char[] CreatePara )
{
char[] BaseTable=new char[64]{
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9','+','/'};
const int CREATE_TYPE = 8;
byte bParaValue = 0;
byte bTemp;
for( int i = 0; i < CreatePara.Length; i++ )
{
bTemp = ( byte )( CreatePara[i] );
switch( bTemp % CREATE_TYPE )
{
case 1:
// 00000001
bTemp =( byte )( bTemp ^ 0x01 );
break;
case 2:
// 00000010
bTemp =( byte )( bTemp ^ 0x02 );
break;
case 3:
// 00000100
bTemp =( byte )( bTemp ^ 0x04 );
break;
case 4:
// 00001000
bTemp =( byte )( bTemp ^ 0x08 );
break;
case 5:
// 00010000
bTemp =( byte )( bTemp ^ 0x10 );
break;
case 6:
// 00100000
bTemp =( byte )( bTemp ^ 0x20 );
break;
case 7:
// 01000000
bTemp =( byte )( bTemp ^ 0x40 );
break;
default:
// 10000000
bTemp =( byte )( bTemp ^ 0x80 );
break;
}
bParaValue =( byte )( bParaValue ^ bTemp );
}
char chrTemp;
int nIndex;
switch( bParaValue % CREATE_TYPE )
{
case 1:
// Exechange 0 <--> 1, 2 <--> 3, 4 <--> 5, 6 <--> 7
for( int i = 0; i < BaseTable.Length / CREATE_TYPE; i++ )
{
nIndex = i * CREATE_TYPE;
chrTemp = BaseTable[nIndex];
BaseTable[nIndex] = BaseTable[nIndex + 1];
BaseTable[nIndex + 1] = chrTemp;
chrTemp = BaseTable[nIndex + 2];
BaseTable[nIndex + 2] = BaseTable[nIndex + 3];
}
//remove paddings
length3=length2-paddingCount;
byte[] result=new byte[length3];
for(int x=0;x<length3;x++)
{
result[x]=buffer2[x];
}
return result;
}
private byte char2sixbit(char c)
{
if( c=='=' )
return 0;
else
{
for (int x=0;x<64;x++)
{
if (lookupTable[x]==c)
return (byte)x;
}
//should not reach here
return 0;
}
}
}
}
㈣ 怎么用base64加密字符串
base64的作用不是加密,而是用来避免“字节”中不能转换成可显示字符的数值。 比如0-32的控制字符,空格,制表符都不能被打印在纸上,base64只使用大写小写数字标点。 可以打印在纸上,数据可以在传统平面媒介上携带。 md5是散列函数,提取数据的特征,输出是不可逆的散列值,用于代表某信息A而又不暴露信息A的内容。不直接用于加密文件。
㈤ 为什么DES加密结果后多个换行符
android.util.Base64.encodeToString(result, 0);
这个byte转换为string时的问题
是这个问题
㈥ 为什么Base64编码有回车换行符
The encoded output stream must be represented in lines of no more than 76 characters each.
Base64一行不能超过76字符,超过则添加回车换行符。
结合前面博客说的“有回车符,导致JSON格式不符合要求”,那就明白了,对附件进行Base64编码,因为超过76字节,所以要添加回车换行符,后台解析带有回车换行符的JSON字符串就出现“ net.sf.json.JSONException : Unterminated string ”。
问题根源就是回车换行符,那删除就行了,谷歌后又发现一问题,原来“回车换行符( )”是在Windows才有,而linux只有换行( ),Mac只有回车( )。
㈦ Java Base64加码解码 Base64.encodeBase64 ( ) 和 new BASE64Enccoder( ).encode( )区别
Base64.encodeBase64 ( ) 可以处理换行符,
new BASE64Enccoder( ).encode( )需要单独处理换行符。
在linux/windows下,推荐使用第一种,不用自己单独处理换行。
㈧ 怎么去掉换行 - Java
把输出结果的\r\n替换成“”不就行了