base64

Base64 encoder and decoder
git clone https://noulin.net/git/base64.git
Log | Files | Refs

commit 047b8ec51537e095f226ffd7428975a1ad973594
Author: Remy Noulin <loader2x@gmail.com>
Date:   Sat,  2 Nov 2019 11:26:17 +0100

base64 encode and decode

.gitignore  |  63 +++++++++++++++++++++
base64.c    | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
base64.h    |   9 +++
demo.c      |  51 +++++++++++++++++
package.yml |  30 ++++++++++
5 files changed, 336 insertions(+)

Diffstat:
A.gitignore | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abase64.c | 183+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abase64.h | 9+++++++++
Ademo.c | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Apackage.yml | 30++++++++++++++++++++++++++++++
5 files changed, 336 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,63 @@ +# Vim +*.sw* + +# Debug +.gdb_history + +# Coverage +*.gcov +*.gcda +*.gcno + +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf diff --git a/base64.c b/base64.c @@ -0,0 +1,183 @@ +#include <string.h> +#include <stdlib.h> + +int base64_encode(unsigned char *source, size_t sourcelen, char *target, size_t targetlen); +size_t base64_encode_size(size_t sourcelen); +void _base64_encode_triple(unsigned char triple[3], char result[4]); +int _base64_char_value(char base64char); +int _base64_decode_triple(char quadruple[4], unsigned char *result); +size_t base64_decode(char *source, unsigned char *target, size_t targetlen); +size_t base64_decode_size(char *source); + +const char *BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +void _base64_encode_triple(unsigned char triple[3], char result[4]) +{ + int tripleValue, i; + + tripleValue = triple[0]; + tripleValue *= 256; + tripleValue += triple[1]; + tripleValue *= 256; + tripleValue += triple[2]; + + for (i=0; i<4; i++) + { + result[3-i] = BASE64_CHARS[tripleValue%64]; + tripleValue /= 64; + } +} + +int base64_encode(unsigned char *source, size_t sourcelen, char *target, size_t targetlen) +{ + if ((sourcelen+2)/3*4 > targetlen-1) + return 0; + + while (sourcelen >= 3) + { + _base64_encode_triple(source, target); + sourcelen -= 3; + source += 3; + target += 4; + } + + if (sourcelen > 0) + { + unsigned char temp[3]; + memset(temp, 0, sizeof(temp)); + memcpy(temp, source, sourcelen); + _base64_encode_triple(temp, target); + target[3] = '='; + if (sourcelen == 1) + target[2] = '='; + + target += 4; + } + + target[0] = 0; + + return 1; +} + +size_t base64_encode_size(size_t sourcelen) +{ + return (sourcelen+2)/3*4+1; +} + +int _base64_char_value(char base64char) +{ + if (base64char >= 'A' && base64char <= 'Z') + return base64char-'A'; + if (base64char >= 'a' && base64char <= 'z') + return base64char-'a'+26; + if (base64char >= '0' && base64char <= '9') + return base64char-'0'+2*26; + if (base64char == '+') + return 2*26+10; + if (base64char == '/') + return 2*26+11; + return -1; +} + +int _base64_decode_triple(char quadruple[4], unsigned char *result) +{ + int i, triple_value, bytes_to_decode = 3, only_equals_yet = 1; + int char_value[4]; + + for (i=0; i<4; i++) + char_value[i] = _base64_char_value(quadruple[i]); + + for (i=3; i>=0; i--) + { + if (char_value[i]<0) + { + if (only_equals_yet && quadruple[i]=='=') + { + char_value[i]=0; + bytes_to_decode--; + continue; + } + return 0; + } + only_equals_yet = 0; + } + + if (bytes_to_decode < 0) + bytes_to_decode = 0; + + triple_value = char_value[0]; + triple_value *= 64; + triple_value += char_value[1]; + triple_value *= 64; + triple_value += char_value[2]; + triple_value *= 64; + triple_value += char_value[3]; + + for (i=bytes_to_decode; i<3; i++) + triple_value /= 256; + for (i=bytes_to_decode-1; i>=0; i--) + { + result[i] = triple_value%256; + triple_value /= 256; + } + + return bytes_to_decode; +} + +size_t base64_decode(char *source, unsigned char *target, size_t targetlen) +{ + char *src, *tmpptr; + char quadruple[4]; + unsigned char tmpresult[3]; + int i, tmplen = 3; + size_t converted = 0; + + src = (char *)malloc(strlen(source)+5); + if (src == NULL) + return -1; + strcpy(src, source); + strcat(src, "===="); + tmpptr = src; + + while (tmplen == 3) + { + for (i=0; i<4; i++) + { + while (*tmpptr != '=' && _base64_char_value(*tmpptr)<0) + tmpptr++; + + quadruple[i] = *(tmpptr++); + } + + tmplen = _base64_decode_triple(quadruple, tmpresult); + + if (targetlen < tmplen) + { + free(src); + return -1; + } + + memcpy(target, tmpresult, tmplen); + target += tmplen; + targetlen -= tmplen; + converted += tmplen; + } + + free(src); + return converted; +} + +size_t base64_decode_size(char *source) { + + if (!source) return -1; + + size_t len = strlen(source); + + if (len < 4) /* invalid base64, minimum is 4 chars */ return -1; + + if (source[len-1] != '=') return len*3/4; + if (source[len-2] != '=') return (len-1)*3/4; + else return (len-2)*3/4; +} + +// vim: set expandtab ts=2 sw=2: diff --git a/base64.h b/base64.h @@ -0,0 +1,9 @@ + +#include <stddef.h> + +size_t base64_encode_size( size_t sourcelen); +int base64_encode (unsigned char *source, size_t sourcelen, char *target, size_t targetlen); +size_t base64_decode_size( char *source); +size_t base64_decode ( char *source, unsigned char *target, size_t targetlen); + +// vim: set expandtab ts=2 sw=2: diff --git a/demo.c b/demo.c @@ -0,0 +1,51 @@ +#! /usr/bin/env sheepy +/* or direct path to sheepy: #! /usr/local/bin/sheepy */ + +/* Libsheepy documentation: https://spartatek.se/libsheepy/ */ +#include "libsheepyObject.h" +#include "base64.h" + +int argc; char **argv; + +/* enable/disable logging */ +/* #undef pLog */ +/* #define pLog(...) */ + +int main(int ARGC, char** ARGV) { + + argc = ARGC; argv = ARGV; + + initLibsheepy(ARGV[0]); + setLogMode(LOG_DATE); + //setLogSymbols(LOG_UTF8); + //disableLibsheepyErrorLogs; + + u8 bytes[] = {0x96,0x5c,0xbc,0x5d,0x00,0x00,0x00,0x00,0xd6,0x45,0xd3,0xd3,0xd0,0x84,0x98,0xaa,0x18,0xd1,0xf3,0xc7,0xef,0x9c,0x8b,0x5c,0x89,0x8b,0xee,0x23,0x86,0xff,0x35,0xf9}; + + u8 s[1024] = init0Var; + + var r = base64_encode(bytes, sizeof(bytes), s, sizeof(s)); + + logVarG(sizeof(bytes)); + logVarG(r); + logVarG(strlen(s)); + logVarG(base64_encode_size(sizeof(bytes))); + logI(s); + + /* char *base64String = "lly8XQAAAADWRdPT0ISYqhjR88fvnItciYvuI4b/Nfk="; */ + char *base64String = s; + + u8 decoded[40]; + + var size = base64_decode(base64String, decoded, sizeof(decoded)); + + logVarG(size); + logVarG(base64_decode_size(base64String)); + logI("Source: 256bits"); + loghex( bytes, MIN(sizeof(decoded), sizeof(bytes))); + put; + logI("Decoded: 256bits"); + loghex(decoded, MIN(sizeof(decoded), sizeof(bytes))); + +} +// vim: set expandtab ts=2 sw=2: diff --git a/package.yml b/package.yml @@ -0,0 +1,30 @@ +--- + name: base64 + version: 0.0.2 + description: "encode bytes to base64 and decode base64 string to bytes" + bin: ./base64.c + #cflags: -DA -ggdb -std=gnu11 -fPIC -pipe + #lflags: -lpcre + repository: + type: git + url: git+https://github.com/USER/base64.git + keywords: + #- utility + - command + author: Remy + license: MIT + bugs: + url: https://github.com/USER/base64/issues + homepage: https://github.com/USER/base64#readme + #compileHelp: # text displayed when there is a compilation error + # Test configuration: + #testBin: ./testBase64.c + #testCflags: -ggdb -std=gnu11 -fPIC -pipe -fprofile-arcs -ftest-coverage -Wall -Wextra + #testLflags: -lcheck_pic -lrt -lm -lsubunit -fprofile-arcs -ftest-coverage -rdynamic + # Memcheck configuration: + #memcheckBin: ./memcheckBase64.c + #memcheckCmd: valgrind --leak-check=full --show-leak-kinds=all + #memcheckCflags: -ggdb -std=gnu11 -fPIC -pipe + #memcheckLflags: -rdynamic + #documentationCmd: # command for generating the documentation with spm doc + private: false # true for private package