系列文章目录
前言
一、常用加密算法?
1. md5是什么
MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。1996年后该算法被证实存在弱点,可以被加以破解,对于需要高度安全性的数据,专家一般建议改用其他算法,如SHA-2。2004年,证实MD5算法无法防止碰撞(collision),因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。
MD5算法的原理可简要的叙述为:MD5码以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
MD5特点
加密不可逆,即无法通过密文得到原文。
不变性,即相同的原文,通过MD5算法得到的密文总是相同的。
散列性,即对原文作轻微的改动,都可导致最终的密文完全改变。
2. Base64是什么
Base64是一种基于64个可打印字符来表示二进制数据的方法。Base64是一种编码方式,不是加密算法,它是没有可读性的,但不代表这个编码就是加密的。加密需要保证没有秘钥的人无法解密信息,更无法从密文中破解任务明文信息,但Base64可以很轻松的反编码。
另外它没有用到秘钥 不具有加密算法的安全性。
标准的Base64不适合直接放在url里传输,因为Base64字符里面含有字符(+ / =)URL编码器会变成%XX的形式,这样经过URL传递后解码可能会出错,所以要在URL中传输Base64的值 就必须把+ / = 替换掉,可以使用urlEncodecomponent来解决。
标准Base64编码使用的64个字符为:如图
Base64编码本质上是一种将二进制数据转成文本数据的方案。对于非二进制数据,是先将其转换成二进制形式,然后每连续6比特(2的6次方=64)计算其十进制值,根据该值在上面的索引表中找到对应的字符,最终得到一个文本字符串。
假设我们要对 Hello! 进行Base64编码,按照ASCII表,其转换过程如下图所示:
可知 Hello! 的Base64编码结果为 SGVsbG8h,每3个原始字符经Base64编码成4个字符。那么,当原始字符串长度不能被3整除时,怎么办呢?
以 Hello!! 为例,其转换过程为:
Hello!! Base64编码的结果为 SGVsbG8hIQAA。可见,不能被3整除时会采用来来补0的方式来完成编码。
需要注意的是:标准Base64编码通常用 = 字符来替换最后的 A,即编码结果为 SGVsbG8hIQ==。因为 = 字符并不在Base64编码索引表中,其意义在于结束符号,在Base64解码时遇到 = 时即可知道一个Base64编码字符串结束。
二、基本实现
1. md5
基于openssl实现的
#include <string>
#include <openssl/md5.h>
std::string MD5String(const std::string& str)
{
unsigned char md5[17]={0};
char output[33] = {0};
MD5_CTX c;
MD5_Init(&c);
MD5_Update(&c, str.c_str(), str.size());
MD5_Final(md5, &c);
auto index = 0;
for(int i = 0; i < 16; i++){
sprintf(&output[index], "%02x",md5[i]);
index += 2;
}
return output;
}
2. base64、decode
class Base64Codec {
public:
std::string _base64_table;
static const char base64_pad = '=';
public:
Base64Codec(){
_base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /* Base64 Dictionary */
}
std::string Encode(const unsigned char * str, int bytes) {
std::string _encode_result;
const unsigned char * current;
current = str;
while (bytes > 2) {
_encode_result += _base64_table[current[0] >> 2];
_encode_result += _base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
_encode_result += _base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
_encode_result += _base64_table[current[2] & 0x3f];
current += 3;
bytes -= 3;
}
if (bytes > 0)
{
_encode_result += _base64_table[current[0] >> 2];
if (bytes % 3 == 1) {
_encode_result += _base64_table[(current[0] & 0x03) << 4];
_encode_result += "==";
}
else if (bytes % 3 == 2) {
_encode_result += _base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
_encode_result += _base64_table[(current[1] & 0x0f) << 2];
_encode_result += "=";
}
}
return _encode_result;
}
std::string Decode(const char *str, int bytes){
const char DecodeTable[] =
{
-2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -2, -2, -1, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -2, -2, -2,
-2, 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, -2, -2, -2, -2, -2,
-2, 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, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2
};
int kkk = 0;
int bin = 0, i = 0;
std::string _decode_result;
const char *current = str;
char ch;
while ((ch = *current++) != '\0' && length-- > 0)
{
if (ch == base64_pad) {
if (*current != '=' && (i % 4) == 1) {
return NULL;
}
continue;
}
kkk = ch;
ch = DecodeTable[kkk];
if (ch < 0) { /* a space or some other separator character, we simply skip over */
continue;
}
switch (i % 4)
{
case 0:
bin = ch << 2;
break;
case 1:
bin |= ch >> 4;
_decode_result += bin;
bin = (ch & 0x0f) << 4;
break;
case 2:
bin |= ch >> 2;
_decode_result += bin;
bin = (ch & 0x03) << 6;
break;
case 3:
bin |= ch;
_decode_result += bin;
break;
}
i++;
}
return _decode_result;
}
};
总结
欢迎大家使用指正。