C语言base64实现

1. base64 原理

  • Base64 算法的原理,是将输入流中的字节按每 3 个分为一组,然后 每次取 6 个比特,将其转换成表格中对应的数据,一直重复到没有剩余的字符为止,转换表格如下:
    base64编码表
  • 上面就是Base64的索引表,字符选用了"A-Z、a-z、0-9、+、/" 64个可打印字符,这是标准的Base64协议规定。在日常使用中还会看到“=”或“==”号出现在Base64的编码结果中,“=”在此是作为填充字符出现。
  • 示例说明
    以下图的表格为示例,具体分析当字符 占 全 \color{gold}{占全} 时的过程。
    show table1
    当位数 不 足 \color{gold}{不足} 的时候。
    show table2

2.base64实现

核心原理
1. 获取第一个字符8个 bit 的前6位,作为 base64编码的第一位;
2. 获取第一个字符8个 bit 的后2位和第二个字符8个 bit 的前4位,作为 base64 编码的第二位;
3. 获取第二个字符8个 bit 的后4位和第三个字符8个 bit 的前2位,作为 base64编码的第三位;
4. 获取第三个字符8个 bit 的后6位,作为 base64编码的第四位;
如此3个字符可编码 base64 为4个字符,当位数不够时补 0 来满足一个字符,且要实现编码后的位数为4的倍数,不足的用 “=” 代替。

方法一

利用 ASCII 码与 base64 码进行转换的方法

  • base64是由 A ∼ Z , a ∼ z , 1 ∼ 9 , + , / \color{red} {A{\sim}Z , a{\sim}z ,1{\sim}9, + , / } AZ,az,19,+,/构成,其编码位 0 ∼ 64 \color{red}{0{\sim}64} 064,通过对比 A S C I I \color{red} { ASCII } ASCII 码表可找到对应数字关系

1.编码

  • 设传入字符为c,c语言中 char 字符以ASCII码存储,将其变为真正的ASCII码对应的字符即可。
    a :当 ASCII 码小于 25(0~25) 时,return ( ‘A’ + c );26是对应的前26个 base (A~Z)码
    b :当 ASCII 码在26到51(26~51)之间时,return ( ‘a’ + ( c - 26 ));此时是接下来的26个 base(a~z)码
    c :当 ASCII 码在52到61(52~61)之间时,return ( ‘0’ + ( c - 52 ));此时是接下来的10个 base(0~9)码
    d :当 ASCII 码为62(62)时,return ‘+’
    e :当 ASCII 码为63(63)时,return ‘/’
    f :当 ASCII 码大于63 (64~…)时, 此时c = c - c/64*64;循环以上步骤;

2.解码

  • 编码传入字符m,base64 的字符,将其还原为真正的 ASCII 码即可。
    a :当输入字符在A~Z间return ( m - ‘A’ )
    b :当输入字符在a~z之间return ( 26 + m - ‘a’ )
    c : 当输入的字符在0~9之间return ( 52 + m - ‘0’ )
    d :当输入的字符为 “+”return 62
    e :当输入字符为 “/”return 63
if(*m>='A'&&*m<='Z')
	{
	 *m-='A';
	 continue;
	}
	if(*m>='a'&&*m<='z')
	{
	 *m-='a';
	 *m+=26;
	 continue;
	}
	if(*m=='+')
	{
	 *m=62;
	 continue;
	}
	if(*m=='/')
	{
	 *m=63;
	 continue;
	}
	if(*m=='=')
	{
	 *m=0;
	 continue;
	}
	*m-='0';
	*m+=52;

参考代码

方法二

直接对字符串进行转换

	//base64.h
#pragma once
#ifndef BASE64_H_INCLUDED
#define BASE64_H_INCLUDED

#include <stdio.h>
#include <stdlib.h>
#include<windows.h>
#include <string.h>

char* base64_encode(char* binData, char* base64, int binLength);
char* base64_decode(char const* base64Str, char* debase64Str, int encodeStrLen);
void Menu();
void decode();
void encode();

#endif // BASE64_H_INCLUDED
	//base64.c
#pragma warning(disable:4996)
#include"base64.h"

char base64char[] = {
        'A','B','C','D','E','F','G','H','I','J',
        'K','L','M','N','O','P','Q','R','S','T',
        'U','V','W','X','Y','Z','a','b','c','d',
        'e','f','g','h','i','j','k','l','m','n',
        'o','p','q','r','s','t','u','v','w','x',
        'y','z','0','1','2','3','4','5','6','7',
        '8','9','+', '/', '\0'
};

char c;

void Menu()
{
    printf("***************\n");
    printf("*1、base64加密\n");
    printf("*2、base64解密\n");
    printf("*3、退出程序\n");
    printf("***************\n");
}

void encode()
{
    do
    {
        system("cls");
        printf(" ---- base64_encode ----\n\n");
        char soursedata[1024];
        scanf("%s", &soursedata);
        
        getchar();  //吸收缓冲区的换行符
        char* result = (char*)malloc(sizeof(char) * 1024);	//申请返回字符串空间
        memset(result, 0, sizeof(char) * 1024);		//初始化字符串空间
        
        printf("\t\t\n%s\n", base64_encode(soursedata, result, (int)strlen(soursedata)));
        printf("\nWhether to continue:(Y/N)\n");	//是否继续进行操作
    } while ((c = getch())!='N'&& c != 'n');
}

void decode()
{
    do {
        system("cls");
        printf(" ---- base64_dncode ----\n\n");
        char soursedata[1024];
        scanf("%s", &soursedata);
        getchar();  //吸收缓冲区的换行符
        
        char* result = (char*)malloc(sizeof(char) * 1024);
        memset(result, 0, sizeof(char) * 1024);
        
        printf("\t\t\n%s\n",base64_decode((char const*)soursedata, result, (int)strlen(soursedata)));
        printf("\nWhether to continue:(Y/N)\n");
    } while ((c = getch()) != 'N' && c != 'n');
}

char* base64_encode(char* binData, char* base64, int binLength)
{
    int i = 0;
    int j = 0;
    int current = 0;
    for (i = 0; i < binLength; i += 3) {
        //获取第一个6位
        current = (*(binData + i) >> 2) & 0x3F;
        *(base64 + j++) = base64char[current];
        //获取第二个6位的前两位
        current = (*(binData + i) << 4) & 0x30;
        //如果只有一个字符,那么需要做特殊处理
        if (binLength <= (i + 1)) {
            *(base64 + j++) = base64char[current];
            *(base64 + j++) = '=';
            *(base64 + j++) = '=';
            break;
        }
        //获取第二个6位的后四位
        current |= (*(binData + i + 1) >> 4) & 0xf;
        *(base64 + j++) = base64char[current];
        //获取第三个6位的前四位
        current = (*(binData + i + 1) << 2) & 0x3c;
        if (binLength <= (i + 2)) {
            *(base64 + j++) = base64char[current];
            *(base64 + j++) = '=';
            break;
        }
        //获取第三个6位的后两位
        current |= (*(binData + i + 2) >> 6) & 0x03;
        *(base64 + j++) = base64char[current];
        //获取第四个6位
        current = *(binData + i + 2) & 0x3F;
        *(base64 + j++) = base64char[current];
    }
    *(base64 + j) = '\0';
    return base64;
}

char* base64_decode(char const* base64Str, char* debase64Str, int encodeStrLen)
{
    int i = 0;
    int j = 0;
    int k = 0;
    char temp[4] = "";

    for (i = 0; i < encodeStrLen; i += 4) {
        for (j = 0; j < 64; j++) {
            if (*(base64Str + i) == base64char[j]) {
                temp[0] = j;
            }
        }
        
        for (j = 0; j < 64; j++) {
            if (*(base64Str + i + 1) == base64char[j]) {
                temp[1] = j;
            }
        }

        for (j = 0; j < 64; j++) {
            if (*(base64Str + i + 2) == base64char[j]) {
                temp[2] = j;
            }
        }

        for (j = 0; j < 64; j++) {
            if (*(base64Str + i + 3) == base64char[j]) {
                temp[3] = j;
            }
        }

        *(debase64Str + k++) = ((temp[0] << 2) & 0xFC) | ((temp[1] >> 4) & 0x03);
        if (*(base64Str + i + 2) == '=')
            break;

        *(debase64Str + k++) = ((temp[1] << 4) & 0xF0) | ((temp[2] >> 2) & 0x0F);
        if (*(base64Str + i + 3) == '=')
            break;

        *(debase64Str + k++) = ((temp[2] << 6) & 0xF0) | (temp[3] & 0x3F);
    }
    return debase64Str;
}

	//main.c
#pragma warning(disable:4996)
#include"base64.h"

int main()
{
    Menu();
    char a;
    scanf("%c", &a);
    switch (a)
    {
    case '1':
        encode();
        break;
    case '2':
        decode();
        break;
    case '3':
        exit(0);
    }
    return 0;
}
  • 12
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值