C语言base64编码与解码

昨天工作中遇到需要将char *转换成base64的问题,把这块单独提取出来作为一个模块。
这里有几个参数需要解释一下:
char *out:一块buffer的首地址,这块buffer就是用来存放我们转码后的内容的。当然要注意提前malloc内存。
char *in:原字符串的首地址,指向需要转码的内容,即原字符串内容。
int inlen:原字符串长度。
int maxlen:可支持的转换后的字符串的最大长度,超出这个长度函数会返回-3,且out指向’\0’。
函数返回值:正常情况下返回转换后字符串的实际长度,错误返回错误码。
#define INVALID_ARG -1
#define WRONG_FORMAT -2
#define OUTPUT_OVERFLOW -3

base64.h

#ifndef __BASE64_H__
#define __BASE64_H__

/*************************************************
Function:       base64_to_ascii
Description:    decodes string from base64 to ascii
Input:          const char *in: the input string (NIL-terminated)
int inlen: length of input string
int maxlen: the output buffer size limit, 0 to ignore
Output:         unsigned char *out: decoded output string
Return:         length of output string on successful
less than 0 on error occur, then the output is invalid
Others:         
 *************************************************/
int base64_decode(unsigned char *out, unsigned char *in, int inlen, int maxlen);

/*************************************************
Function:       ascii_to_base64
Description:    encodes string from ascii to base64
Input:          const char *in: the input string (NIL-terminated)
int inlen: length of input string
int maxlen: the output buffer size limit, 0 to ignore
Output:         unsigned char *out: decoded output string
Return:         length of output string on successful
less than 0 on error occur, then the output is invalid
Others:         
 *************************************************/
int base64_encode(char *out, const unsigned char *in, int inlen, int maxlen);

#endif

base64.c

#include <ctype.h>
#include <string.h>
#include <syslog.h>

#define BAD     -1

#define INVALID_ARG -1
#define WRONG_FORMAT    -2
#define OUTPUT_OVERFLOW -3

static const char base64digits[] = // characters used for base64 code
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

static const char base64val[] = {// base64 alphabet
    BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
    BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
    BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 62, BAD, BAD, BAD, 63,
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, BAD, BAD, BAD, BAD, BAD, BAD,
    BAD, 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, BAD, BAD, BAD, BAD, BAD,
    BAD, 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, BAD, BAD, BAD, BAD, BAD
};

#define ENCODE64(c)     (((c) & 0xC0) ? BAD : base64digits[(int)c])
#define DECODE64(c)     (((c) & 0x80) ? BAD : base64val[(int)c])
//~#define DECODE64(c)     (isascii(c) ? base64val[c] : BAD)

/*************************************************
Function:       base64_to_ascii
Description:    decodes string from base64 to ascii
Input:          const char *in: the input string (NIL-terminated)
int inlen: length of input string
int maxlen: the output buffer size limit, 0 to ignore
Output:         unsigned char *out: decoded output string
Return:         length of output string on successful
less than 0 on error occur, then the output is invalid
Others:         
 *************************************************/
//int base64_decode(unsigned char *out, const unsigned char *in, int inlen, int maxlen) {
int base64_decode(unsigned char *out, unsigned char *in, int inlen, int maxlen) {
    //~int inlen = strlen (in);
    int outlen = 0;
    int over = 0; // decode over flag
    register char digit0, digit1, digit2, digit3;
    unsigned char *out_org = out;
    memset(out, 0x00, maxlen);

    // check if arguments valid
    if (!out || !in) {
        return INVALID_ARG;
    }

    // decode each four base64 characters
    for (; inlen >= 4; inlen -= 4, in += 4) {
        // update output length and check overflow
        if (++outlen >= maxlen && maxlen) {
            *out_org = '\0';
            return OUTPUT_OVERFLOW;
        }

        if ((digit0 = DECODE64(in[0])) == BAD) {
            *out_org = '\0';
            return WRONG_FORMAT;
        }
        if ((digit1 = DECODE64(in[1])) == BAD) {
            *out_org = '\0';
            return WRONG_FORMAT;
        }
        *out++ = ((digit0 << 2) & 0xFC) | ((digit1 >> 4) & 0x03);

        if (in[2] != '=') {
            // update output length and check overflow
            if (++outlen >= maxlen && maxlen) {
                *out_org = '\0';
                return OUTPUT_OVERFLOW;
            }

            if ((digit2 = DECODE64(in[2])) == BAD) {
                *out_org = '\0';
                return WRONG_FORMAT;
            }
            *out++ = ((digit1 << 4) & 0xF0) | ((digit2 >> 2) & 0x0F);

            if (in[3] != '=') {
                // update output length and check overflow
                if (++outlen >= maxlen && maxlen) {
                    *out_org = '\0';
                    return OUTPUT_OVERFLOW;
                }

                if ((digit3 = DECODE64(in[3])) == BAD) {
                    *out_org = '\0';
                    return WRONG_FORMAT;
                }
                *out++ = ((digit2 << 6) & 0xC0) | (digit3 & 0x3F);
            } else {
                over = 1;
                break;
            }
        } else {
            over = 1;
            break;
        }
    }

    // there cannt have tail-fragment except after '='
    if (!over && inlen > 0) {
        *out_org = '\0';
        return WRONG_FORMAT;
    }

    // terminate the output string
    *out = '\0';

    return outlen;
}

/*************************************************
Function:       ascii_to_base64
Description:    encodes string from ascii to base64
Input:          const char *in: the input string (NIL-terminated)
int inlen: length of input string
int maxlen: the output buffer size limit, 0 to ignore
Output:         unsigned char *out: decoded output string
Return:         length of output string on successful
less than 0 on error occur, then the output is invalid
Others:         
 *************************************************/
int base64_encode(char *out, const unsigned char *in, int inlen, int maxlen) {
    int outlen = 0;
    char *out_org = out;
    memset(out, 0x00, maxlen);

    // check if arguments valid
    if (!out || !in) {
        return INVALID_ARG;
    }

    // encode each three ascii characters
    for (; inlen >= 3; inlen -= 3, in += 3) {
        // update output length and check overflow
        outlen += 4;
        if (outlen >= maxlen && maxlen) {
            // use >= because there must have a '\0'
            *out_org = '\0';
            return OUTPUT_OVERFLOW;
        }
        if ((*out++ = ENCODE64((in[0] >> 2) & 0x3F)) == BAD) {
            *out_org = '\0';
            return WRONG_FORMAT;
        }
        if ((*out++ = ENCODE64(((in[0] << 4) & 0x30) | ((in[1] >> 4) & 0x0F))) == BAD) {
            *out_org = '\0';
            return WRONG_FORMAT;
        }
        if ((*out++ = ENCODE64(((in[1] << 2) & 0x3C) | ((in[2] >> 6) & 0x03))) == BAD) {
            *out_org = '\0';
            return WRONG_FORMAT;
        }
        if ((*out++ = ENCODE64(in[2] & 0x3F)) == BAD) {
            *out_org = '\0';
            return WRONG_FORMAT;
        }
    }

    // encode tail-fragment if exist
    if (inlen > 0) {
        char fragment;

        // update output length and check overflow
        outlen += 4;
        if (outlen >= maxlen && maxlen) {
            *out_org = '\0';
            return OUTPUT_OVERFLOW;
        }

        if ((*out++ = ENCODE64((in[0] >> 2) & 0x3F)) == BAD) {
            *out_org = '\0';
            return WRONG_FORMAT;
        }
        fragment = (in[0] << 4) & 0x30;
        if (inlen > 1) {
            fragment |= (in[1] >> 4) & 0x0F;
        }
        if ((*out++ = ENCODE64(fragment)) == BAD) {
            *out_org = '\0';
            return WRONG_FORMAT;
        }
        if (inlen < 2) {
            *out++ = '=';
        } else {
            if ((*out++ = ENCODE64((in[1] << 2) & 0x3C)) == BAD) {
                *out_org = '\0';
                return WRONG_FORMAT;
            }
        }
        *out++ = '=';
    }

    // terminate the output string
    *out = '\0';
    return outlen;
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高晓伟_Steven

相逢即是有缘,动力源于金钱。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值