0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【安全算法之base64】base64加解密的C语言源码实现

嵌入式物联网开发 来源:嵌入式物联网开发 作者:嵌入式物联网开发 2022-09-18 09:31 次阅读

​ 最近,有项目中需要用到base64的加解密,所以用C语言实现了一遍,测试效果还不错,代码量和RAM消耗都比较低,可以提供给大家参考下。

#include 
#include 
#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;
    else                                    return 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 '/';
    else                                    return '=';
}

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 parameter
        return 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] = '';

    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 parameter
        return BASE64_ERROR;
    }

    in_data_cnt = 0;
    while (in[i] != '') {
        c = get_index_from_char(in[i++]);
        if (c == 255) {
            //MSG_PRINTF(LOG_ERR, "INVALID MESSAGE CODEn");
            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 ''
    if (in_data_cnt == 3) {          // 3 chars before '=', encoded msg like xxx= OR
        tmp = (tmp << 6);           // 3 chars before '', encoded msg like xxx, considered '=' omitted
        out[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== OR
        tmp = (tmp << 6);           // 2 chars before '', encoded msg like xx, considered '=' omitted
        tmp = (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);
}
poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

简单写了一个测试demo,有兴趣的可以一起看下。


#include 
#include 

#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):rn", title, len);
    printf("%srn", dimm);
    printf("| Offset  : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F   0123456789ABCDEF |rn");
    printf("%srn", 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] = '';
        printf("%s |rn", str);
    }

    printf("%srn", 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: %sn", base64_enc_calc);
		printf("BASE64 encryption test OKn");
	} else {
		printf("base64_enc_calc: %sn", base64_enc_calc);
        printf("base64_enc_exp : %sn", base64_enc_exp);
		printf("BASE64 encryption test FAILn");
	}

    ret = base64_decode(base64_enc_calc, base64_dec_calc, &base64_dec_len);
    printf("ret: %dn", ret);
    if (!ret && !strcmp((char *)base64_dec_calc, p_calc)) {
        printf("base64_dec_calc: %sn", base64_dec_calc);
        printf("BASE64 decryption test OKn");
    } else {
        printf("base64_dec_calc: %sn", base64_dec_calc);
        printf("base64_org_data: %sn", p_calc);
        printf("BASE64 decryption test FAILn");
    }

	return 0;
}
poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

测试结果,还挺正常的。

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




审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • RAM
    RAM
    +关注

    关注

    7

    文章

    1307

    浏览量

    113644
  • C语言
    +关注

    关注

    180

    文章

    7513

    浏览量

    124279
  • 加解密
    +关注

    关注

    0

    文章

    16

    浏览量

    6476
收藏 人收藏

    评论

    相关推荐

    ArkTS语言基础类库-解析

    统一资源定位符,可以提供找到该资源的路径。 提供常见的[字符串和二进制数据处理]的能力,以及[控制台打印]的相关能力。 字符串编解码功能。 基于Base64的字节编码和解码功能。 提供常见的有理数操作
    发表于 02-20 16:44

    基于FPGA的可编程AES加解密IP

    可编程AES加解密IP内建密钥扩展功能,使用初始密钥产生扩展密钥,用于加解密过程。可编程AES加解密IP处理128-bit分组数据,并且支持可编程的密钥长度:128-bit,192-bit和256-bit。
    发表于 01-09 10:49 199次阅读
    基于FPGA的可编程AES<b class='flag-5'>加解密</b>IP

    单对以太网:如何实现 10Base-T1L

    单对以太网:如何实现 10Base-T1L
    的头像 发表于 12-06 15:50 259次阅读
    单对以太网:如何<b class='flag-5'>实现</b> 10<b class='flag-5'>Base</b>-T1L

    什么是Empty Base Optimization?

    看见了吧?就算Base不包含任何的成员,编译器也会让Base占1 byte。这是因为如果一个类的内存占用为0,那么连续的分配对象有可能会有同一个内存地址,这个是不合理的。所以编译器为了避免这种情况,让空的类也会占有1 byte的大小。
    的头像 发表于 10-30 16:31 160次阅读

    探秘STM32U5安全特性|硬件加解密引擎与软件算法对比

    探秘STM32U5安全特性|硬件加解密引擎与软件算法对比
    的头像 发表于 10-27 10:23 749次阅读
    探秘STM32U5<b class='flag-5'>安全</b>特性|硬件<b class='flag-5'>加解密</b>引擎与软件<b class='flag-5'>算法</b>对比

    基于FPGA的PCI硬件加解密卡的设计方案

    电子发烧友网站提供《基于FPGA的PCI硬件加解密卡的设计方案.pdf》资料免费下载
    发表于 10-18 11:18 0次下载
    基于FPGA的PCI硬件<b class='flag-5'>加解密</b>卡的设计方案

    BASE64编码的逆向分析

    其中1至7行是程序编译过程中系统预置的,可以不用理解。
    的头像 发表于 09-20 17:24 784次阅读
    对<b class='flag-5'>BASE64</b>编码的逆向分析

    STM32加解密技术

    没有加解密技术是万万不能的• 通讯安全• 平台安全• *例外:STM32 RDP保护知识产权• 加解密技术不是万能的• 只是工具• 无法代替其它STM32
    发表于 09-08 08:18

    STM32的加解密硬件模块

    基于物理噪声源的随机数产生器• 生成32位随机数• AHB 从设备,不使用时可关闭它以节省功耗• 广泛运用于加解密算法和协议中• 密钥的生成• “Challenge- Acknowledge”认证模式中,充当Challenges(质询)• 初始向量(IV)• 随机数(No
    发表于 09-08 07:54

    硬件加解密主要优点及引擎种类

    IoT联网装置日渐普及,大家在享受联网装置所带来便利性的同时,也必须同时承担联网装置的风险,即数据在传输过程可能遭窃取、伪造,因此数据传输过程的安全性,对于IoT联网装置是基本的要求,而利用加解密
    发表于 08-28 07:29

    【触觉智能 Purple Pi OH 开发板体验】python 简单web显示图片

    import Flask from flask import render_template import os import base64 app = Flask(__name__
    发表于 08-20 13:10

    单对以太网:如何实现10Base-T1L

    单对以太网:如何实现10Base-T1L
    的头像 发表于 08-16 16:26 547次阅读
    单对以太网:如何<b class='flag-5'>实现</b>10<b class='flag-5'>Base</b>-T1L

    铜墙铁壁的最佳安全保护-硬件加解密MCU

    铜墙铁壁的最佳安全保护-硬件加解密MCU
    的头像 发表于 08-11 14:44 210次阅读

    STM32的加解密硬件模块

    电子发烧友网站提供《STM32的加解密硬件模块.pdf》资料免费下载
    发表于 08-02 09:14 0次下载
    STM32的<b class='flag-5'>加解密</b>硬件模块

    labview base64转16进制

    需要用到base64编码方式的可以下载一下,程序还可以自己优化
    发表于 06-14 17:42