int mbedtls_base64_encode(
    unsigned char *dst,
    size_t dlen,
    size_t *olen,
    const unsigned char *src,
    size_t slen
)
1.0、参考
1.1、此函数的作用

base64编码

1.2、参数说明

unsigned char *dst是编码后的数据存放的地方。C语言中没有其他语言中的byte类型,C语言中表达byte类型就是用unsigned charunsigned char的意思就是告诉编译器, 不要把我的最高位当成符号位,这样这8bit就都表示真实的数据了。 我们知道,base64编码后的内容是ASCII字符集中的字符组成的字符串, 定义为char *dst更为精确。但是这里定义成了unsigned char *dst, 这就没有明确说这个里面存放的是ASCII字符集中的字符组成的字符串。 但是我们自己是知道的,这里面存放的就是ASCII字符集中的字符组成的字符串。 而由ASCII字符集中的字符组成的字符串使用unsigned char *dstchar *dst是一样的,可以进行相互转换。但是,如果不是ASCII字符集中的字符组成的字符串使用unsigned char *dstchar *dst是不一样的,需要注意这一点。

size_t的定义:

typedef long unsigned int __darwin_size_t;
typedef __darwin_size_t size_t;

size_t dlenunsigned char *dst的大小,单位是字节

size_t *olen是一个指针,用来存放unsigned char *dst中最终写入了多少字节数据。 为啥要传入指针呢?这是因为这个数字会变化,在函数内部对其指向的内容做了修改。

const unsigned char *src表示要编码的字节数据,需要注意的是,要做base64编码的内容可以是任意字节,比如一张图片, 当然,我们通常使用的常见情形是对字符串进行base64编码。这也就是为啥把输入定义为了unsigned char*而不是char*的原因。因为定义为char*就限定死了,只能编码字符串。

size_t slenconst unsigned char *src的大小,单位是字节

注意:

size_t dlen到底应该传入多少呢?这有2个办法得知:

方法一:如果你熟悉base64编码,自己就可以计算出来,如下:

size_t n = inputLength / 3 + (inputLength % 3);
size_t outputLength = n<< 2 + 1;

方法二:如果你不熟悉base64编码,就调用本函数,只要dst = NULL; dlen = 0,所需要的长度就保存在size_t *olen中了,如下:

mbedtls_base64_encode(NULL, 0, writenBytes, input, inputLength);
1.3、返回值说明

0表示编码成功。

MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL表示因为传入的dlen不够大, 编码后的数据根本无法全部放在dst中。

1.4、使用示例

step1、创建一个项目目录base64并进入该目录

mkdir base64 && cd base64

step2、使用curl命令下载base64.hbase64.c两个文件:

curl -LO https://raw.githubusercontent.com/ARMmbed/mbedtls/master/include/mbedtls/base64.h
curl -LO https://raw.githubusercontent.com/ARMmbed/mbedtls/master/library/base64.c

step3、创建config.h文件,其内容如下

#define MBEDTLS_BASE64_C

MBEDTLS_BASE64_C这个宏控制着是否开启BASE64相关的定义。

step4、将base64.c中的mbedtls/字符串去掉

sed -i    's@mbedtls/@@g' base64.c 2> /dev/null ||
sed -i "" 's@mbedtls/@@g' base64.c

step5、编写一个C语言源程序base64Test.c,其内容如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "base64.h"

void showHelp() {
    printf("usage: base64 encode xxxx\n");
    exit(1);
}

char* base64Encode(unsigned char* input, size_t inputLength, size_t* writenBytes, int* resultCode) {
    //看看需要分配多少个字节
    size_t n = inputLength / 3 + (inputLength % 3);
    size_t outputLength = n << 2 + 1;

    //加密后的数据,这里定义为char*更明确,因为编码后的内容就是ASCII字符集中的字符组成的字符串
    char* output = (char*) calloc(outputLength, sizeof(char));
    
    //编码
    (*resultCode) = mbedtls_base64_encode((unsigned char*)output, outputLength, writenBytes, input, inputLength);
    
    0 == (*resultCode) ? return output : return NULL;
}

int main(int argc, char* argv[]) {
    if (argc == 3) {
        if (strcmp("encode", argv[1]) == 0) {
            size_t writenBytes = 0;
            int resultCode = -1;
            char* output = base64Encode((unsigned char*)argv[2], strlen(argv[2]), &writenBytes, &errorCode);
            if (NULL == output) {
                printf("error occurred. code is %d\n", resultCode);
                return resultCode;
            } else {
                printf("base64(%s) = %s\n", argv[2], output);
            }
        } else {
            showHelp();
        }
    } else {
        showHelp();
    }
    return 0;
}

step6、使用cc命令进行编译:

cc -o base64Test base64Test.c base64.c

step7、执行base64Test,结果如下

./base64Test encode abc
base64(abc) = YWJj

step8、在在线工具中输入相同的字符,看看输出是否一样。

source code on GitHub