Line data Source code
1 : /**
2 : * @file base64.c
3 : * @brief Simple Base64 encoding and decoding functions
4 : *
5 : * Copied and adapted from https://github.com/elzoughby/Base64
6 : *
7 : * @author François Cerbelle (Fanfan), francois@cerbelle.net
8 : *
9 : * @internal
10 : * Created: 25/10/2024
11 : * Revision: none
12 : * Last modified: 2024-11-06 10:36
13 : * Compiler: gcc
14 : * Organization: Cerbelle.net
15 : * Copyright: Copyright (c) 2024, François Cerbelle
16 : *
17 : * This source code is released for free distribution under the terms of the
18 : * GNU General Public License as published by the Free Software Foundation.
19 : */
20 :
21 : #ifdef HAVE_CONFIG_H
22 : #include "config.h"
23 : #endif
24 :
25 : #include "base64.h"
26 :
27 : #include <stdlib.h>
28 : #include <stdio.h> /* perror */
29 : #include <string.h>
30 :
31 : static char base46_map[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
32 : 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
33 : 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
34 : 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2',
35 : '3', '4', '5', '6', '7', '8', '9', '+', '/'
36 : };
37 :
38 :
39 17 : char* base64_encode(char* plain) {
40 17 : unsigned char counts = 0;
41 : char buffer[3];
42 17 : char* cipher = malloc(strlen(plain) * 4 / 3 + 4);
43 17 : int i = 0, c = 0;
44 :
45 17 : if (NULL==cipher) {
46 0 : perror("base64_encode");
47 0 : return NULL;
48 : }
49 :
50 89 : for(i = 0; plain[i] != '\0'; i++) {
51 72 : buffer[counts++] = plain[i];
52 72 : if(counts == 3) {
53 21 : cipher[c++] = base46_map[buffer[0] >> 2];
54 21 : cipher[c++] = base46_map[((buffer[0] & 0x03) << 4) + (buffer[1] >> 4)];
55 21 : cipher[c++] = base46_map[((buffer[1] & 0x0f) << 2) + (buffer[2] >> 6)];
56 21 : cipher[c++] = base46_map[buffer[2] & 0x3f];
57 21 : counts = 0;
58 : }
59 : }
60 :
61 17 : if(counts > 0) {
62 6 : cipher[c++] = base46_map[buffer[0] >> 2];
63 6 : if(counts == 1) {
64 3 : cipher[c++] = base46_map[(buffer[0] & 0x03) << 4];
65 3 : cipher[c++] = '=';
66 : } else { // if counts == 2
67 3 : cipher[c++] = base46_map[((buffer[0] & 0x03) << 4) + (buffer[1] >> 4)];
68 3 : cipher[c++] = base46_map[(buffer[1] & 0x0f) << 2];
69 : }
70 6 : cipher[c++] = '=';
71 : }
72 :
73 17 : cipher[c] = '\0'; /* string padding character */
74 17 : return cipher;
75 : }
76 :
77 8 : char* base64_decode(char* cipher) {
78 :
79 8 : unsigned char counts = 0;
80 : char buffer[4];
81 8 : char* plain = malloc(strlen(cipher) * 3 / 4 + 1);
82 8 : int i = 0, p = 0;
83 :
84 8 : if (NULL==plain) {
85 0 : perror("base64_decode");
86 0 : return NULL;
87 : }
88 :
89 20 : for(i = 0; cipher[i] != '\0'; i++) {
90 : unsigned char k;
91 282 : for(k = 0 ; k < 64 && base46_map[k] != cipher[i]; k++);
92 12 : buffer[counts++] = k;
93 12 : if(counts == 4) {
94 3 : plain[p++] = (buffer[0] << 2) + (buffer[1] >> 4);
95 3 : if(buffer[2] != 64)
96 3 : plain[p++] = (buffer[1] << 4) + (buffer[2] >> 2);
97 3 : if(buffer[3] != 64)
98 3 : plain[p++] = (buffer[2] << 6) + buffer[3];
99 3 : counts = 0;
100 : }
101 : }
102 :
103 8 : plain[p] = '\0'; /* string padding character */
104 8 : return plain;
105 : }
106 :
107 : /* vim: set tw=80: */
|