base64编解码源码适用于c和c++

该代码提供了简洁的Base64编码和解码函数,适用于标准Base64和URL安全的Base64。源码包括了头文件my_base64.h和实现文件my_base64.c,删除了不必要的编译宏,用户需自行移植编译。附带了测试样例以展示如何使用这两个函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

网上找了一些源码,实用时都有点问题(也可能是我没用对),于是自己参考了一份源码改写了。

直接提供最简洁的源码,删减了一堆编译宏,需要使用者自己实现移植编译。

.c文件里面有使用例子参考。

源码

my_base64.h

/**
 * @file my_base64.h
 * @author zhongwei.peng
 * @brief Base64就是一种基于64个可打印字符来表示二进制数据的方法。可查看RFC2045~RFC2049.
 *        参考了 intel base64 库,参考链接: https://github.com/intel/base64
 * @version 0.1
 * @date 2023-01-04
 * 
 * @copyright Copyright (c) 2023
 * 
 */

#ifndef __MY_BASE64_H__
#define __MY_BASE64_H__

/*
标准Base64 = 0
URL中使用  = 1
标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,
而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符。
*/
#define BASE64_USE_URL    (1)

// 获取 encode 需要的缓存空间, x 为十六进制数据长度,单位 byte
#define BASE64_ENCODE_BUF_SIZE(x) (((x)+5) / 3 * 4)

/**
    * @brief base64 编码
    * 
    * @param in[in] 需要编码的缓存(十六进制)
	* @param len[in] 需要编码的字节数
    * @param out[out] 编码后输出缓存指针(字符串)
	* @param len_out[out] 编码后输出缓存指针(字符串)的长度
*/
void base64_encode(const unsigned char *in, unsigned int len_in, char *out, unsigned int *len_out);

/**
    * @brief base64 解码
    * 
    * @param base64_str[in] 需要解码的缓存(字符串)
	* @param len[in] 需要解码的字节数
    * @param out[out] 解码后输出缓存指针
	* @param len_out[out] 解码后输出缓存长度
*/
void base64_decode(const char *base64_str, unsigned int len, unsigned char *out, unsigned int *len_out);

#endif

my_base64.c

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "my_base64.h"

/*
// test sample
void test_base64(void)
{
	unsigned char src_code[] = {'b', 'a', 's', 'e', '6', '4', 'v', '1'};
	char *encode_out;
	unsigned int encode_len;
	unsigned char *decode_out;
	unsigned int decode_len;

	encode_len = BASE64_ENCODE_BUF_SIZE(sizeof(src_code));
	encode_out = (char *)malloc(encode_len);
	if (encode_out)
	{
	    // encode
		base64_encode(src_code, sizeof(src_code), encode_out, &encode_len);
		
		// decode
		decode_out = (unsigned char *)malloc(encode_len);
		if (decode_out)
		{
			base64_decode(encode_out, encode_len, decode_out, &decode_len);
			free(decode_out);
		}

		free(encode_out);
	}
}
*/

static const char _base64_alphabet[]    = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char _base64url_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";

static const int base64_reverse_alphabet[256] = {
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
    -1,  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, -1, -1, -1, -1, -1,
    -1, 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, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};

static const int base64url_reverse_alphabet[256] = {
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1,
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
    -1,  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, -1, -1, -1, -1, 63,
    -1, 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, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};

/**
    * @brief base64 编码
    * 
    * @param in[in] 需要编码的缓存(十六进制)
	* @param len[in] 需要编码的字节数
    * @param out[out] 编码后输出缓存指针(字符串)
	* @param len_out[out] 编码后输出缓存指针(字符串)的长度
*/
void base64_encode(const unsigned char *in, unsigned int len, char *out, unsigned int *len_out)
{
	char filler = '=';
    size_t i = 0;
	size_t n = len;
	uint_least32_t val;
	unsigned int o = 0; // offset
    const char *alphabet;

	if (BASE64_USE_URL)
		alphabet = _base64url_alphabet;
	else
		alphabet = _base64_alphabet;

    if (n >= 3) {
        for (i = 0; n - i >= 3; i += 3) {
			// read 3 bytes x 8 bits = 24 bits
			val = (in[i+0] << 16) | (in[i+1] << 8) | in[i+2];

            // write 4 chars x 6 bits = 24 bits
            out[o++] = alphabet[(val >> 18) & 0x3f];
            out[o++] = alphabet[(val >> 12) & 0x3f];
            out[o++] = alphabet[(val >> 6) & 0x3f];
            out[o++] = alphabet[val & 0x3f];
        }
    }

	if (n - i == 2) {
		val = (in[i] << 8);
        val |= in[i + 1];
		out[o++] = alphabet[(val >> 10) & 0x3f];
		out[o++] = alphabet[(val >> 4) & 0x3f];
		out[o++] = alphabet[(val << 2) & 0x3f];
		out[o++] = filler;
	} else if (n - i == 1) {
		out[o++] = alphabet[(in[i] >> 2) & 0x3f];
		out[o++] = alphabet[(in[i] << 4) & 0x3f];
		out[o++] = filler;
		out[o++] = filler;
	}

	out[o] = '\0';
	*len_out = o;

    return;
}

/**
    * @brief base64 解码
    * 
    * @param base64_str[in] 需要解码的缓存(字符串)
	* @param len[in] 需要解码的字节数
    * @param out[out] 解码后输出缓存指针
	* @param len_out[out] 解码后输出缓存长度
*/
void base64_decode(const char *base64_str, unsigned int len, unsigned char *out, unsigned int *len_out)
{
	unsigned char *p = out;
    const unsigned char *in = (const unsigned char *)base64_str;
    const unsigned char *end = in + len;
    const int *reverse_alphabet;
	unsigned int val;

    if (BASE64_USE_URL) 
        reverse_alphabet = base64url_reverse_alphabet;
    else
        reverse_alphabet = base64_reverse_alphabet;

    while (in < end) {
        if (reverse_alphabet[in[0]] < 0 || reverse_alphabet[in[1]] < 0)
            break;

        val = (reverse_alphabet[in[0]] & 0xFF) << 18;
        val |= (reverse_alphabet[in[1]] & 0xFF) << 12;

        if (in[2] == '=' || in[2] == '\0') {
			*p++ = val >> 16;
            break;
        } else if (in[3] == '=' || in[3] == '\0') {
			val |= (reverse_alphabet[in[2]] & 0xFF) << 6;
			*p++ = val >> 16;
			*p++ = val >> 8;
            break;
        } else {
            val |= (reverse_alphabet[in[2]] & 0xFF) << 6;
            val |= (reverse_alphabet[in[3]] & 0xFF);
			*p++ = val >> 16;
			*p++ = val >> 8;
			*p++ = val;
			in += 4;
        }
    } // !while

	*p = '\0';
	*len_out = p - out;

    return;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值