c#图片base64去转义字符_密码学基础:Base64编码

c#图⽚base64去转义字符_密码学基础:Base64编码
写这篇⽂章的⽬的主要是整理下密码学中Base64的知识点,并把它们分享出来,本⽂⽬的:写这篇⽂章的⽬的主要是整理下密码学中
本⽂⽬的:
并且帮助初探密码学的坛友们⼀步⼀步的⽤C语⾔将Base64的编码实现出来。
希望⼤家在浏览完本⽚⽂章后可以⾃⼰去实现⼀下,相信⼀定会对你的编程技术阅读⽅法:
阅读⽅法:希望⼤家在浏览完本⽚⽂章后可以⾃⼰去实现⼀下,相信⼀定会对你的编程技术有所提⾼。(附件中提供参考代码,请点击阅读原⽂下载)
熟练掌握C语⾔
具备基础:
具备基础:熟练掌握
学习环境:任意
任意C语⾔开发环境,Base64加解密⼯具
学习环境:
Base64简介
虽然这篇⽂章发布在密码算法区,但希望⼤家不要误解,Base64并不是⼀种加密的⽅法,⽽是⼀种编码的⽅式。虽然⽤Base64加密(暂且说是加密)的字符串看起来有⼀种被加密的感觉,但是这只是感觉。
因为如果⽤标准的Base64进⾏加密会发现很多Base64的特征,⽐如在Base64字符串中会出现'+'和''两种字符,在字符串的末尾经常会有⼀个到两个连续的'='。
只要发现了这些特征,就可以肯定这个字符串被Base64加密过,只要通过相应的解密⼩程序就可以轻松得到加密前的样⼦(⾮标准的除外)。
那么有为什么说Base64是⼀中编码⽅式呢?这是因为Base64可以把所有的⼆进制数据都转换成ASCII码可打印字符串的形式。以便在只⽀持⽂本的环境中也能够顺利地传输⼆进制数据。
当然有时在CTF的题⽬中掺杂上⾮标准的Base64编码表也会有加密的效果,但是如果到这个表那就编程明⽂了,所以在CTF题⽬中只会起到辅助的作⽤。
Base64的编码原理游艇门
Base64编码的核⼼原理是将⼆进制数据进⾏分组,每24Bit(3字节)为⼀个⼤组,再把⼀个⼤组的数据分成4个6Bit的⼩分组。
宏嘉焊锡
由于6Bit数据只能表⽰64个不同的字符(2^6=64),所以这也是Base64的名字由来。
这64个字符分别对应ASCII码表中的'A'-'Z','a'-'z','0''9','+'和'/'。他们的对应关系是由Base64字符集决定的。
因为⼩分组中的6Bit数据表⽰起来并不⽅便,所以要把每个⼩分组进⾏⾼位补零操作,这样每个⼩分组就构成了⼀个8Bit(字节)的数据。
在补零操作完成后接下来的⼯作就简单多了,那就是将⼩分组的内容作为Base64字符集的下标,然后⼀⼀替换成对应的ASCII字符。加密⼯作完成。
Base64解密的⼯作原理也⾮常的简单,只要操作⽅式和加密步骤相反即可。⾸先将Base64编码根据其对应的字符集转换成下标,这就是补完零后的8Bit(⼀字节)数据。
既然有补零操作那⾃然会有去零操作了,我们要将这些8Bit数据的最⾼位上的两个0抹去形成6Bit数据,这也就是前⾯我们提到过的⼩分组。
最后就是将每4个6Bit数据进⾏合并形成24Bit的⼤分组,然后将这些⼤分组按照每组8Bit进⾏拆分就会得到3个8Bit的数据,这写8Bit数据就是加密前的数据了。解密⼯作完成。
重点:别看前⾯说的Base64⼯作流程这么简单,实际上⾥⾯还是有很多坑的,那在我们了解了编码原理后现在就来填坑了:
我们在Base64编码前是⽆法保证准备编码的字符串长度是3的倍数,所以为了让编码能够顺利进⾏就必须在获取编码字符串的同时判断字符串的长度是否是3的倍数。
如果是3的倍数编码就可以正常进⾏,如果不是那么就要进⾏额外的操作——补零,就是要在不⾜3的倍数的字符串末尾⽤0x00进⾏填充。这样就是解决了字符串长度不⾜的问题了,但是同时也引进了另⼀个新的问题,那就是末尾补充上的0在进⾏Base64字符集替换的时候会与字符集中的'A'字符发⽣冲突。
因为字符集中的下标0对应的字符是'A',⽽末尾填充上的0x00在分组补零后同样是下标0x00,这样就⽆法分辨出到底是末尾填充的0x00还是⼆进制数据中的0x00。
为了解决这个问题我们就必须引⼊Base64字符集外的新字符来区分末尾补充上的0x00,这就是'='字符不在Base64字符集中,但是也出现在Base64编码的原因了,'='字符在⼀个Base64编码的末尾中最多会出现两个,如果不符合这以规则那么这个Base64就可能被⼈做了⼿脚。
Base64字符集:
Base64的编码图解
我们以输⼊字符串"6666"为例: 
1、判断字符串长度,不⾜3的倍数⽤0x00填充
2、将补零后的字符串进⾏8Bit分组
3、把每个⼤分组进⾏6Bit分组
4、将6Bit组转换成Base64字符集的下标
(注:由于是进⾏图⽚解说,所以省区了6Bit组⾼位补零操作)
5、把字符集的下标替换成Base64字符
6、修正末尾的符号,得到Base64编码结果
解密操作和加密操作相反!
Base64核⼼代码讲解(C语⾔)
>>>>
Base64加密部分:
1、将长度补全后的字符串转换成6Bit分组
int TransitionSixBitGroup(unsigned char *BitPlainText, unsigned char* SixBitGroup, unsigned int SixBitGroupSize)
{
int ret = 0;
/
/1、每4个6Bit组⼀个循环
for (int i = 0, j = 0; i < SixBitGroupSize; i += 4, j += 3)
{
SixBitGroup[i] = ((BitPlainText[j] & 0xFC) >> 2);
SixBitGroup[i + 1] = ((BitPlainText[j] & 0x03) << 4) + ((BitPlainText[j + 1] & 0xF0) >> 4);
SixBitGroup[i + 2] = ((BitPlainText[j + 1] & 0x0F) << 2) + ((BitPlainText[j + 2] & 0xC0) >> 6);
SixBitGroup[i + 3] = (BitPlainText[j + 2] & 0x3F);
}
return ret;
}
这⼀段代码的功能是将已经补⾜长度的16进制数据转变成6Bit分组,每⼀个分组⽤8Bit(⼀个字节)表⽰,所以也就⾃动完成了6Bit组的⾼位补零操作。
这⾥⽤到了⼀个for循环,其⽬的是为了达到前⾯所说的分组,这⾥分了两个部分,⼀部分是将16进制数据分成⼀个38Bit的⼤分组,另⼀部分是将⼤分组中的数据分割成46Bit的⼩分组。
分割的过程⽤到了很多位操作,⼤⼤降低了分组的复杂性,只不过需要注意运算法的优先级。
语句剖析:
SixBitGroup[i] = ((BitPlainText[j] & 0xFC) >> 2); //在38Bit数据中的第⼀个数据取6Bit内容右移两位得到第⼀个6Bit数据。
SixBitGroup[i + 1] = ((BitPlainText[j] & 0x03) << 4) + ((BitPlainText[j + 1] & 0xF0) >> 4);//在38Bit数据中的第⼀个数据取2Bit内容后左移4位,加上38Bit数据中的第⼆个数据取4Bit数据构成第⼆个6Bit数据。
SixBitGroup[i + 2] = ((BitPlainText[j + 1] & 0x0F) << 2) + ((BitPlainText[j + 2] & 0xC0) >> 6);//在38Bit数据中的第⼆个数据取4Bit内容后左移2位,加上38Bit数据中的第三个数据取2Bit数据右移6位构成第三个6Bit数据。
SixBitGroup[i + 3] = (BitPlainText[j + 2] & 0x3F);//在38Bit数据中的第三个数据取6Bit数据得到最后⼀个6Bit数据。
2、根据6Bit组获取字符串
unsigned char Base64Table[64] =
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'G', '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', '+', '/'
};
int GetBase64String(unsigned char *CipherGroup, unsigned char *SixBitGroup, unsigned int SixBitGroupSize)
{
int ret = 0;
for (int i = 0; i < SixBitGroupSize; i++)
{
CipherGroup[i] = Base64Table[SixBitGroup[i]];
}
return ret;
}
通过第⼀步的处理,我们得到了Base64的⾼位补零后的6Bit分组也就是Base64字符集的下标。
通过下标获取Base64字符集中的内容也就⾮常简单了,利⽤for循环进⾏查表赋值操作就可以初步得到Base64的编码值了。
3、将初步得到Base64的编码值末尾补充的字符转换成'='
for (int i = SixBitGroupSize - 1; i > SixBitGroupSize - 3; i--)
{
if (CipherGroup[i] == 'A')
{
热熔胶封箱机
CipherGroup[i] = '=';
}
}
因为Base64编码最多只可能出现两个'='字符,所以判断条件为i > SixBitGroupSize-3,并且在循环中判断末尾是否是补充字符。经过这⼀过程,也就获取了Base64加密后的结果。
加密完成!
>>>>
解密部分:
1、将Base64密⽂转换成Base64下标
int GetBase64Index(unsigned char *CipherText, unsigned char *Base64Index, unsigned int Base64IndexSize)
{
int ret = 0;
for (int i = 0; i < Base64IndexSize; i++)
{
//计算下标
微晶钢if (CipherText[i] >= 'A' && CipherText[i] <= 'Z') //'A'-'Z'
{
Base64Index[i] = CipherText[i] - 'A';
}
else if (CipherText[i] >= 'a' && CipherText[i] <= 'z') //'a'-'z'
{
Base64Index[i] = CipherText[i] - 'a' + 26;
}
else if (CipherText[i] >= '0' && CipherText[i] <= '9') //'0'-'9'
{
Base64Index[i] = CipherText[i] - '0' + 52;
}
else if (CipherText[i] == '+')
{
Base64Index[i] = 62;
}
else if (CipherText[i] == '/')
{
Base64Index[i] = 63;
}
else //处理字符串末尾是'='的情况
{
Base64Index[i] = 0;
}
}
return ret;
}
由于Base64字符串是⽤ASCII码表⽰的,所以要想获取其对应的索引号就需要减去每⼀段ASCII第⼀个字符后加上相应的偏移,最后应该注意的是不要忘记还有⼀个不在Base64字符集的字符。
2、将Base64下标(6Bit组)转换为明⽂字符串的8Bit组形式

本文发布于:2024-09-23 16:22:51,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/4/219091.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:数据   编码   字符串   末尾
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议