tbase64.c - sick - sign and check files using ed25519
 (HTM) git clone git://z3bra.org/sick
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tbase64.c (2667B)
       ---
            1 #include <stdint.h>
            2 #include <stdio.h>
            3 #include <stdlib.h>
            4 #include <string.h>
            5 #include <unistd.h>
            6 #include <limits.h>
            7 
            8 #include "base64.h"
            9 
           10 #define BASE64_FOLD 76
           11 
           12 int base64_index(const char *, char);
           13 
           14 const char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
           15 
           16 /*
           17  * Return the index of a base64 char in the table
           18  */
           19 int
           20 base64_index(const char *base64, char ch)
           21 {
           22         uint8_t idx = 0;
           23 
           24         for (idx = 0; idx < 64; idx++)
           25                 if (base64[idx] == ch)
           26                         return idx;
           27 
           28         return ch == '=' ? 0 : -1;
           29 }
           30 
           31 /*
           32  * Encode the given message in base64, allocate memory to store the encoded
           33  * message, and return the size allocated.
           34  */
           35 size_t
           36 base64_encode(char **buf, const unsigned char *msg, size_t len)
           37 {
           38         size_t i, j;
           39         uint64_t b64;
           40         size_t size;
           41 
           42         /* calculate size needed for the base64 buffer */
           43         size = (len / 3) * 4 + (len % 3 ? 4 : 0);
           44 
           45         *buf = malloc(size);
           46         memset(*buf, 0, size);
           47 
           48         for (i = j = 0; i < len; i+=3) {
           49                 /* concatenate 3 bytes into one 24 bits quantum, or 0 */
           50                 b64 = 0;
           51                 b64 |= (msg[i]<<16);
           52                 b64 |= ((i+1 < len ? msg[i+1] : 0) << 8);
           53                 b64 |= i+2 < len ? msg[i+2] : 0;
           54 
           55                 /* extract 4 base64 values from it */
           56                 (*buf)[j++] = base64_table[63 & (b64>>18)];
           57                 (*buf)[j++] = base64_table[63 & (b64>>12)];
           58                 (*buf)[j++] = i+1 < len ? base64_table[63 & (b64>>6)] : '=';
           59                 (*buf)[j++] = i+2 < len ? base64_table[63 & b64] : '=';
           60         }
           61 
           62         return size;
           63 }
           64 
           65 /*
           66  * Allocate size to decode a base64 message, decode it in the buffer and
           67  * return the allocated size.
           68  */
           69 size_t
           70 base64_decode(char **buf, const unsigned char *msg, size_t len)
           71 {
           72         uint64_t b64;
           73         size_t size, i, j;
           74 
           75         size = (len / 4) * 3;
           76         size -= msg[len - 1] == '=' ? 1 : 0;
           77         size -= msg[len - 2] == '=' ? 1 : 0;
           78 
           79         *buf = malloc(size);
           80         if (*buf == NULL)
           81                 return 0;
           82         memset(*buf, 0, size);
           83 
           84         for (i = j = 0; i < len; i+=4) {
           85                 b64 = 0;
           86                 b64 |= (base64_index(base64_table, msg[i])<<18);
           87                 b64 |= (base64_index(base64_table, msg[i+1])<<12);
           88                 b64 |= i + 2 < len ? (base64_index(base64_table, msg[i+2])<<6) : 0;
           89                 b64 |= i + 3 < len ? (base64_index(base64_table, msg[i+3])) : 0;
           90 
           91                 if (j < size)
           92                         (*buf)[j++] = 255 & (b64>>16);
           93                 if (j < size)
           94                         (*buf)[j++] = 255 & (b64>>8);
           95                 if (j < size)
           96                         (*buf)[j++] = 255 & (b64);
           97         }
           98 
           99         return size;
          100 }
          101 
          102 /*
          103  * Write a base64 encoded message to the given file pointer, folded at the
          104  * given width (defaults to BASE64_FOLD if specified width is 0).
          105  */
          106 size_t
          107 base64_fold(FILE *fp, char *base64, size_t len, size_t fold)
          108 {
          109         size_t i;
          110 
          111         fold = fold > 0 ? fold : BASE64_FOLD;
          112 
          113         for (i = 0; i < len; i += BASE64_FOLD) {
          114                 fwrite(base64+i, 1, i+BASE64_FOLD>len?len-i:BASE64_FOLD, fp);
          115                 fwrite("\n", 1, 1, fp);
          116         }
          117 
          118         return fold;
          119 }