最近,有项目中需要用到base64的加解密,所以用C语言实现了一遍,测试效果还不错,代码量和RAM消耗都比较低,可以提供给大家参考下。
#include <stdbool.h>#include <stdint.h>#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;elsereturn 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 '/';elsereturn '=';}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 parameterreturn 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 parameterreturn 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= ORtmp = (tmp << 6); // 3 chars before '\0', encoded msg like xxx, considered '=' omittedout[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== ORtmp = (tmp << 6); // 2 chars before '\0', encoded msg like xx, considered '=' omittedtmp = (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 <stdio.h>#include <string.h>#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语言源码实现