最近,有项目中需要用到base64的加解密,所以用C语言实现了一遍,测试效果还不错,代码量和RAM消耗都比较低,可以提供给大家参考下。
#include
#include
#include "base64.h"
static uint8_t get_index_from_char(char c)
{
if ((c >= 'A') && (c <= 'Z')) return (c - 'A');
else if ((c >= 'a') && (c <= 'z')) return (c - 'a' + 26);
else if ((c >= '0') && (c <= '9')) return (c - '0' + 52);
else if (c == '+') return 62;
else if (c == '/') return 63;
else if (c == '=') return 64;
else if ((c == '\r') || (c == '\n')) return 254;
else return 255;
}
static char get_char_from_index(uint8_t i)
{
if ((i >= 0) && (i <= 25)) return (i + 'A');
else if ((i >= 26) && (i <= 51)) return (i - 26 + 'a');
else if ((i >= 52) && (i <= 61)) return (i - 52 + '0');
else if (i == 62) return '+';
else if (i == 63) return '/';
else return '=';
}
int base64_encode(const uint8_t *in, uint16_t in_len, char *out)
{
int i;
uint32_t tmp = 0;
uint16_t out_len = 0;
uint16_t left = in_len;
if ((!in) || (!out)) {
//invalid parameter
return BASE64_ERROR;
}
for (i = 0; i < in_len;) {
if (left >= 3) {
tmp = in[i];
tmp = (tmp << 8) + in[i+1];
tmp = (tmp << 8) + in[i+2];
out[out_len++] = get_char_from_index((tmp & 0x00FC0000) >> 18);
out[out_len++] = get_char_from_index((tmp & 0x0003F000) >> 12);
out[out_len++] = get_char_from_index((tmp & 0x00000FC0) >> 6);
out[out_len++] = get_char_from_index(tmp & 0x0000003F);
left -= 3;
i += 3;
} else {
break;
}
}
if (left == 2) {
tmp = in[i];
tmp = (tmp << 8) + in[i+1];
out[out_len++] = get_char_from_index((tmp & 0x0000FC00) >> 10);
out[out_len++] = get_char_from_index((tmp & 0x000003F0) >> 4);
out[out_len++] = get_char_from_index((tmp & 0x0000000F) << 2);
out[out_len++] = get_char_from_index(64);
} else if (left == 1) {
tmp = in[i];
out[out_len++] = get_char_from_index((tmp & 0x000000FC) >> 2);
out[out_len++] = get_char_from_index((tmp & 0x00000003) << 4);
out[out_len++] = get_char_from_index(64);
out[out_len++] = get_char_from_index(64);
}
out[out_len] = '\0';
return BASE64_SUCCESS;
}
int base64_decode(const char *in, uint8_t *out, uint16_t *out_len)
{
uint16_t i = 0, cnt = 0;
uint8_t c, in_data_cnt;
bool error_msg = false;
uint32_t tmp = 0;
if ((!in) || (!out) || (!out_len)) {
//invalid parameter
return BASE64_ERROR;
}
in_data_cnt = 0;
while (in[i] != '\0') {
c = get_index_from_char(in[i++]);
if (c == 255) {
//MSG_PRINTF(LOG_ERR, "INVALID MESSAGE CODE\n");
return BASE64_ERR_BASE64_BAD_MSG;
} else if (c == 254) {
continue; // Carriage return or newline feed, skip
} else if (c == 64) {
break; // Meet '=', break
}
tmp = (tmp << 6) | c;
if (++in_data_cnt == 4) {
out[cnt++] = (uint8_t)((tmp >> 16) & 0xFF);
out[cnt++] = (uint8_t)((tmp >> 8) & 0xFF);
out[cnt++] = (uint8_t)(tmp & 0xFF);
in_data_cnt = 0;
tmp = 0;
}
}
// Meet '=' or '\0'
if (in_data_cnt == 3) { // 3 chars before '=', encoded msg like xxx= OR
tmp = (tmp << 6); // 3 chars before '\0', encoded msg like xxx, considered '=' omitted
out[cnt++] = (uint8_t)((tmp >> 16) & 0xFF);
out[cnt++] = (uint8_t)((tmp >> 8) & 0xFF);
} else if (in_data_cnt == 2) { // 2 chars before '=', encoded msg like xx== OR
tmp = (tmp << 6); // 2 chars before '\0', encoded msg like xx, considered '=' omitted
tmp = (tmp << 6);
out[cnt++] = (uint8_t)((tmp >> 16) & 0xFF);
} else if (in_data_cnt != 0) {
error_msg = true; // Warn that the message format is wrong, but we tried our best to decode
}
*out_len = cnt;
return (error_msg ? BASE64_ERROR : BASE64_SUCCESS);
}
简单写了一个测试demo,有兴趣的可以一起看下。
#include
#include
#include "base64.h"
#include "convert.h"
int log_hexdump(const char *title, const unsigned char *data, int len)
{
char str[160], octet[10];
int ofs, i, k, d;
const unsigned char *buf = (const unsigned char *)data;
const char dimm[] = "+------------------------------------------------------------------------------+";
printf("%s (%d bytes):\r\n", title, len);
printf("%s\r\n", dimm);
printf("| Offset : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF |\r\n");
printf("%s\r\n", dimm);
for (ofs = 0; ofs < (int)len; ofs += 16) {
d = snprintf( str, sizeof(str), "| %08X: ", ofs );
for (i = 0; i < 16; i++) {
if ((i + ofs) < (int)len) {
snprintf( octet, sizeof(octet), "%02X ", buf[ofs + i] );
} else {
snprintf( octet, sizeof(octet), " " );
}
d += snprintf( &str[d], sizeof(str) - d, "%s", octet );
}
d += snprintf( &str[d], sizeof(str) - d, " " );
k = d;
for (i = 0; i < 16; i++) {
if ((i + ofs) < (int)len) {
str[k++] = (0x20 <= (buf[ofs + i]) && (buf[ofs + i]) <= 0x7E) ? buf[ofs + i] : '.';
} else {
str[k++] = ' ';
}
}
str[k] = '\0';
printf("%s |\r\n", str);
}
printf("%s\r\n", dimm);
return 0;
}
int main(int argc, const char *argv[])
{
const char *data = "C1D0F8FB4958670DBA40AB1F3752EF0D";
char base64_enc_calc[128] = {0};
char base64_enc_exp[128] = "QzFEMEY4RkI0OTU4NjcwREJBNDBBQjFGMzc1MkVGMEQ=";
const char *p_calc = data;
uint8_t base64_dec_calc[128];
uint16_t base64_dec_len = 0;
int ret;
if (argc > 1) {
p_calc = argv[1];
}
ret = base64_encode((const uint8_t *)p_calc, strlen(p_calc), base64_enc_calc);
if (!ret && !strcmp(base64_enc_calc, base64_enc_exp)) {
printf("base64_enc_calc: %s\n", base64_enc_calc);
printf("BASE64 encryption test OK\n");
} else {
printf("base64_enc_calc: %s\n", base64_enc_calc);
printf("base64_enc_exp : %s\n", base64_enc_exp);
printf("BASE64 encryption test FAIL\n");
}
ret = base64_decode(base64_enc_calc, base64_dec_calc, &base64_dec_len);
printf("ret: %d\n", ret);
if (!ret && !strcmp((char *)base64_dec_calc, p_calc)) {
printf("base64_dec_calc: %s\n", base64_dec_calc);
printf("BASE64 decryption test OK\n");
} else {
printf("base64_dec_calc: %s\n", base64_dec_calc);
printf("base64_org_data: %s\n", p_calc);
printf("BASE64 decryption test FAIL\n");
}
return 0;
}
测试结果,还挺正常的。
recan@ubuntu:~/win_share_workspace/coding-01workstation/workspace/crypto/base64$
recan@ubuntu:~/win_share_workspace/coding-01workstation/workspace/crypto/base64$ ./build.sh
gcc base64.c test.c ../../utils/convert.c -I../../utils -Wall -Werror -o test
recan@ubuntu:~/win_share_workspace/coding-01workstation/workspace/crypto/base64$
recan@ubuntu:~/win_share_workspace/coding-01workstation/workspace/crypto/base64$ ./test
base64_enc_calc: QzFEMEY4RkI0OTU4NjcwREJBNDBBQjFGMzc1MkVGMEQ=
BASE64 encryption test OK
ret: 0
base64_dec_calc: C1D0F8FB4958670DBA40AB1F3752EF0D
BASE64 decryption test OK
有兴趣的朋友可以下载源码,测试测试。
更多参考链接
[1] 【安全算法的github仓库】
[2] 【安全算法之概述】一文带你简要了解常见常用的安全算法
[3] 【安全算法之base64】base64加解密的C语言源码实现
[4] 【安全算法之MD5】MD5摘要运算的C语言源码实现
[5] 【安全算法之SHA1】SHA1摘要运算的C语言源码实现
[6] 【安全算法之SHA224】SHA224摘要运算的C语言源码实现
[7] 【安全算法之SHA256】SHA256摘要运算的C语言源码实现
[8] 【安全算法之SHA384】SHA384摘要运算的C语言源码实现
[9] 【安全算法之SHA512】SHA512摘要运算的C语言源码实现