commit 37a2f72
V. Luna
·
2026-10-07 06:24:59 +0000 UTC
parent bfa71e7
base64 encoding
5 files changed,
+395,
-244
+8,
-0
1@@ -0,0 +1,8 @@
2+My dictionary for this babygronks vibed out code
3+
4+xs = "stb" wannabe single header library
5+sz = size of something
6+s = string
7+n = could literally be anything apparently
8+b = buffer?
9+
+61,
-0
1@@ -0,0 +1,61 @@
2+#include <stdio.h>
3+#include <stdlib.h>
4+#include <string.h>
5+
6+#define MASK 0x3f
7+#define PAD '='
8+
9+static const char b64_tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
10+int get_block_size(int size) {
11+ int block_size = 4096;
12+
13+ if (size < 256) {
14+ block_size = 32;
15+ } else if (size < 4096) {
16+ block_size = 256;
17+ }
18+
19+ return ((((size) + block_size) / block_size) * block_size);
20+}
21+
22+char* encode(const unsigned char* data, int size) {
23+ const int b64_bytes = 3;
24+ const int b64_chars = 4;
25+
26+ int output_len = ((size + b64_bytes - 1) / b64_bytes) * b64_chars;
27+ char* s = realloc(NULL, get_block_size(output_len + 1));
28+
29+ int i = 0, j = 0;
30+ while (i + b64_bytes - 1 < size) {
31+ unsigned int v = (data[i] << 16) | (data[i + 1] << 8) | data[i + 2];
32+
33+ s[j++] = b64_tab[(v >> 18) & MASK];
34+ s[j++] = b64_tab[(v >> 12) & MASK];
35+ s[j++] = b64_tab[(v >> 6) & MASK];
36+ i += b64_bytes;
37+ }
38+
39+ if (i < size) {
40+ unsigned int v = data[i] << 16;
41+ int rem = size - i;
42+
43+ if (rem == 2) { v |= data[i + 1] << 8; }
44+
45+ s[j++] = b64_tab[(v >> 18) & MASK];
46+ s[j++] = b64_tab[(v >> 12) & MASK];
47+ s[j++] = (rem == 2) ? b64_tab[(v >> 6) & MASK] : PAD;
48+ s[j++] = PAD;
49+ }
50+
51+ s[j] = '\0';
52+
53+ return s;
54+}
55+
56+int main(int argc, char* argv[]) {
57+ const char* s = "hello";
58+ const unsigned char* msg = (const unsigned char *)s;
59+
60+ char* code = encode(msg, strlen(s));
61+ printf("code: %s\n", code);
62+}
M
xs.h
+1,
-0
1@@ -247,6 +247,7 @@ void _xs_destroy(char **var)
2 }
3
4
5+/// Get block size
6 int _xs_blk_size(int sz)
7 /* calculates the block size */
8 {
+81,
-0
1@@ -0,0 +1,81 @@
2+#ifndef _XS_BEARSSL_H
3+#define _XS_BEARSSL_H
4+
5+#include "xs.h"
6+
7+#ifndef _XS_BASE64_H
8+xs_str* xs_base64_enc(const xs_val *data, int size);
9+#endif // _XS_BASE64_H
10+
11+#ifdef XS_IMPLEMENTATION
12+
13+#include "bearssl_rsa.h"
14+#include "bearssl_pem.h"
15+
16+#ifndef _XS_BASE64_H
17+/* *
18+ * Ok after reading the bearSSL code for a while I found they expose nothing for base64
19+ * encoding, they do mention it in the header files but they only use it internally for
20+ * their pem encoding and I can't even really copy the code because it's written in some
21+ * weird uxn like language that only Thomas Pornin (that is actually his last name lol)
22+ * knows.
23+ *
24+ * So that just leaves me to handroll the base64 encoding! Shrub I don't know why you
25+ * meatride this lib so much but I hope this gets you to join minx cafe.
26+ * */
27+
28+#define MASK 0x3f
29+#define PAD '='
30+static const char b64_tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
31+
32+static int base64_val(int c) {
33+ if (c >= 'A' && c <= 'Z') return c - 'A';
34+ if (c >= 'a' && c <= 'z') return c - 'a' + 26;
35+ if (c >= '0' && c <= '9') return c - '0' + 52;
36+ if (c == '+') return 62;
37+ if (c == '/') return 63;
38+ return -1;
39+}
40+
41+xs_str* xs_base64_enc(const xs_val* data, int size) { // NOLINT
42+ const int b64_bytes = 3;
43+ const int b64_chars = 4;
44+
45+ const unsigned char *d = (const unsigned char *)data;
46+
47+ int output_len = ((size + b64_bytes - 1) / b64_bytes) * b64_chars;
48+ // thank you baby gronk for making this a macro so clangd would
49+ // bitch about this failing relentlessly you're the best
50+ xs_str* s = xs_realloc(NULL, _xs_blk_size(output_len + 1));
51+
52+ int i = 0, j = 0;
53+ while (i + b64_bytes - 1 < size) {
54+ unsigned int v = (d[i] << 16) | (d[i + 1] << 8) | d[i + 2];
55+
56+ s[j++] = b64_tab[(v >> 18) & MASK];
57+ s[j++] = b64_tab[(v >> 12) & MASK];
58+ s[j++] = b64_tab[(v >> 6) & MASK];
59+ i += b64_bytes;
60+ }
61+
62+ if (i < size) {
63+ unsigned int v = d[i] << 16;
64+ int rem = size - i;
65+
66+ if (rem == 2) { v |= d[i + 1] << 8; }
67+
68+ s[j++] = b64_tab[(v >> 18) & MASK];
69+ s[j++] = b64_tab[(v >> 12) & MASK];
70+ s[j++] = (rem == 2) ? b64_tab[(v >> 6) & MASK] : PAD;
71+ s[j++] = PAD;
72+ }
73+
74+ s[j] = '\0';
75+
76+ return s;
77+}
78+#endif // _XS_BASE64_H
79+
80+#endif // XS_IMPLEMENTATION
81+
82+#endif // _XS_BEARSSL_H
+244,
-244
1@@ -1,245 +1,245 @@
2 /* copyright (c) 2022 - 2026 grunfink et al. / MIT license */
3-
4-#ifndef _XS_OPENSSL_H
5-
6-#define _XS_OPENSSL_H
7-
8-#include "xs.h"
9-#include "xs_hex.h"
10-
11-xs_str *_xs_digest(const xs_val *input, int size, const char *digest, int as_hex);
12-
13-#ifndef _XS_MD5_H
14-#define xs_md5_hex(input, size) _xs_digest(input, size, "md5", 1)
15-#endif /* XS_MD5_H */
16-
17-#ifndef _XS_BASE64_H
18-xs_str *xs_base64_enc(const xs_val *data, int sz);
19-xs_val *xs_base64_dec(const xs_str *data, int *size);
20-#endif /* XS_BASE64_H */
21-
22-#define xs_sha1_hex(input, size) _xs_digest(input, size, "sha1", 1)
23-#define xs_sha256_hex(input, size) _xs_digest(input, size, "sha256", 1)
24-#define xs_sha256_base64(input, size) _xs_digest(input, size, "sha256", 0)
25-
26-xs_dict *xs_evp_genkey(int bits);
27-xs_str *xs_evp_sign(const char *secret, const char *mem, int size);
28-int xs_evp_verify(const char *pubkey, const char *mem, int size, const char *b64sig);
29-
30-
31-#ifdef XS_IMPLEMENTATION
32-
33-#include "openssl/rsa.h"
34-#include "openssl/pem.h"
35-#include "openssl/evp.h"
36-
37-
38-#ifndef _XS_BASE64_H
39-
40-xs_str *xs_base64_enc(const xs_val *data, int sz)
41-/* encodes data to base64 */
42-{
43- BIO *mem, *b64;
44- BUF_MEM *bptr;
45-
46- b64 = BIO_new(BIO_f_base64());
47- mem = BIO_new(BIO_s_mem());
48- b64 = BIO_push(b64, mem);
49-
50- BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
51-
52- BIO_write(b64, data, sz);
53- BIO_flush(b64);
54- BIO_get_mem_ptr(b64, &bptr);
55-
56- int n = bptr->length;
57- xs_str *s = xs_realloc(NULL, _xs_blk_size(n + 1));
58-
59- memcpy(s, bptr->data, n);
60- s[n] = '\0';
61-
62- BIO_free_all(b64);
63-
64- return s;
65-}
66-
67-
68-xs_val *xs_base64_dec(const xs_str *data, int *size)
69-/* decodes data from base64 */
70-{
71- BIO *b64, *mem;
72-
73- *size = strlen(data);
74-
75- b64 = BIO_new(BIO_f_base64());
76- mem = BIO_new_mem_buf(data, *size);
77- b64 = BIO_push(b64, mem);
78-
79- BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
80-
81- /* alloc a very big buffer */
82- xs_str *s = xs_realloc(NULL, *size);
83-
84- *size = BIO_read(b64, s, *size);
85-
86- /* adjust to current size */
87- s = xs_realloc(s, _xs_blk_size(*size + 1));
88- s[*size] = '\0';
89-
90- BIO_free_all(b64);
91-
92- return s;
93-}
94-
95-#endif /* _XS_BASE64_H */
96-
97-
98-xs_str *_xs_digest(const xs_val *input, int size, const char *digest, int as_hex)
99-/* generic function for generating and encoding digests */
100-{
101- const EVP_MD *md;
102-
103- if ((md = EVP_get_digestbyname(digest)) == NULL)
104- return NULL;
105-
106- unsigned char output[1024];
107- unsigned int out_size;
108- EVP_MD_CTX *mdctx;
109-
110- mdctx = EVP_MD_CTX_new();
111- EVP_DigestInit_ex(mdctx, md, NULL);
112- EVP_DigestUpdate(mdctx, input, size);
113- EVP_DigestFinal_ex(mdctx, output, &out_size);
114- EVP_MD_CTX_free(mdctx);
115-
116- return as_hex ? xs_hex_enc ((char *)output, out_size) :
117- xs_base64_enc((char *)output, out_size);
118-}
119-
120-
121-xs_dict *xs_evp_genkey(int bits)
122-/* generates an RSA keypair using the EVP interface */
123-{
124- xs_dict *keypair = NULL;
125- EVP_PKEY_CTX *ctx = NULL;
126- EVP_PKEY *pkey = NULL;
127-
128- if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL)
129- return NULL;
130-
131- if (EVP_PKEY_keygen_init(ctx) <= 0 ||
132- EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0 ||
133- EVP_PKEY_keygen(ctx, &pkey) <= 0)
134- return NULL;
135-
136- BIO *bs = BIO_new(BIO_s_mem());
137- BIO *bp = BIO_new(BIO_s_mem());
138- BUF_MEM *sptr;
139- BUF_MEM *pptr;
140-
141- PEM_write_bio_PrivateKey(bs, pkey, NULL, NULL, 0, 0, NULL);
142- BIO_get_mem_ptr(bs, &sptr);
143-
144- PEM_write_bio_PUBKEY(bp, pkey);
145- BIO_get_mem_ptr(bp, &pptr);
146-
147- keypair = xs_dict_new();
148-
149- xs *secret = xs_str_new_sz(sptr->data, sptr->length);
150- xs *public = xs_str_new_sz(pptr->data, pptr->length);
151- keypair = xs_dict_append(keypair, "secret", secret);
152- keypair = xs_dict_append(keypair, "public", public);
153-
154- BIO_free(bs);
155- BIO_free(bp);
156-
157- EVP_PKEY_free(pkey);
158- EVP_PKEY_CTX_free(ctx);
159-
160- return keypair;
161-}
162-
163-
164-xs_str *xs_evp_sign(const char *secret, const char *mem, int size)
165-/* signs a memory block (secret is in PEM format) */
166-{
167- xs_str *signature = NULL;
168- BIO *b;
169- unsigned char *sig;
170- unsigned int sig_len;
171- EVP_PKEY *pkey;
172- EVP_MD_CTX *mdctx;
173- const EVP_MD *md;
174-
175- /* un-PEM the key */
176- b = BIO_new_mem_buf(secret, strlen(secret));
177- pkey = PEM_read_bio_PrivateKey(b, NULL, NULL, NULL);
178-
179- /* I've learnt all these magical incantations by watching
180- the Python module code and the OpenSSL manual pages */
181- /* Well, "learnt" may be an overstatement */
182-
183- md = EVP_get_digestbyname("sha256");
184-
185- mdctx = EVP_MD_CTX_new();
186-
187- sig_len = EVP_PKEY_size(pkey);
188- sig = xs_realloc(NULL, sig_len);
189-
190- EVP_SignInit(mdctx, md);
191- EVP_SignUpdate(mdctx, mem, size);
192-
193- if (EVP_SignFinal(mdctx, sig, &sig_len, pkey) == 1)
194- signature = xs_base64_enc((char *)sig, sig_len);
195-
196- EVP_MD_CTX_free(mdctx);
197- EVP_PKEY_free(pkey);
198- BIO_free(b);
199- xs_free(sig);
200-
201- return signature;
202-}
203-
204-
205-int xs_evp_verify(const char *pubkey, const char *mem, int size, const char *b64sig)
206-/* verifies a base64 block, returns non-zero on ok */
207-{
208- int r = 0;
209- BIO *b;
210- EVP_PKEY *pkey;
211- EVP_MD_CTX *mdctx;
212- const EVP_MD *md;
213-
214- /* un-PEM the key */
215- b = BIO_new_mem_buf(pubkey, strlen(pubkey));
216- pkey = PEM_read_bio_PUBKEY(b, NULL, NULL, NULL);
217-
218- md = EVP_get_digestbyname("sha256");
219- mdctx = EVP_MD_CTX_new();
220-
221- if (pkey != NULL) {
222- xs *sig = NULL;
223- int s_size;
224-
225- /* de-base64 */
226- sig = xs_base64_dec(b64sig, &s_size);
227-
228- if (sig != NULL) {
229- EVP_VerifyInit(mdctx, md);
230- EVP_VerifyUpdate(mdctx, mem, size);
231-
232- r = EVP_VerifyFinal(mdctx, (unsigned char *)sig, s_size, pkey);
233- }
234- }
235-
236- EVP_MD_CTX_free(mdctx);
237- EVP_PKEY_free(pkey);
238- BIO_free(b);
239-
240- return r;
241-}
242-
243-
244-#endif /* XS_IMPLEMENTATION */
245-
246-#endif /* _XS_OPENSSL_H */
247+//
248+// #ifndef _XS_OPENSSL_H
249+//
250+// #define _XS_OPENSSL_H
251+//
252+// #include "xs.h"
253+// #include "xs_hex.h"
254+//
255+// xs_str *_xs_digest(const xs_val *input, int size, const char *digest, int as_hex);
256+//
257+// #ifndef _XS_MD5_H
258+// #define xs_md5_hex(input, size) _xs_digest(input, size, "md5", 1)
259+// #endif /* XS_MD5_H */
260+//
261+// #ifndef _XS_BASE64_H
262+// xs_str *xs_base64_enc(const xs_val *data, int sz);
263+// xs_val *xs_base64_dec(const xs_str *data, int *size);
264+// #endif /* XS_BASE64_H */
265+//
266+// #define xs_sha1_hex(input, size) _xs_digest(input, size, "sha1", 1)
267+// #define xs_sha256_hex(input, size) _xs_digest(input, size, "sha256", 1)
268+// #define xs_sha256_base64(input, size) _xs_digest(input, size, "sha256", 0)
269+//
270+// xs_dict *xs_evp_genkey(int bits);
271+// xs_str *xs_evp_sign(const char *secret, const char *mem, int size);
272+// int xs_evp_verify(const char *pubkey, const char *mem, int size, const char *b64sig);
273+//
274+//
275+// #ifdef XS_IMPLEMENTATION
276+//
277+// #include "openssl/rsa.h"
278+// #include "openssl/pem.h"
279+// #include "openssl/evp.h"
280+//
281+//
282+// #ifndef _XS_BASE64_H
283+//
284+// xs_str *xs_base64_enc(const xs_val *data, int sz)
285+// /* encodes data to base64 */
286+// {
287+// BIO *mem, *b64;
288+// BUF_MEM *bptr;
289+//
290+// b64 = BIO_new(BIO_f_base64());
291+// mem = BIO_new(BIO_s_mem());
292+// b64 = BIO_push(b64, mem);
293+//
294+// BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
295+//
296+// BIO_write(b64, data, sz);
297+// BIO_flush(b64);
298+// BIO_get_mem_ptr(b64, &bptr);
299+//
300+// int n = bptr->length;
301+// xs_str *s = xs_realloc(NULL, _xs_blk_size(n + 1));
302+//
303+// memcpy(s, bptr->data, n);
304+// s[n] = '\0';
305+//
306+// BIO_free_all(b64);
307+//
308+// return s;
309+// }
310+//
311+//
312+// xs_val *xs_base64_dec(const xs_str *data, int *size)
313+// /* decodes data from base64 */
314+// {
315+// BIO *b64, *mem;
316+//
317+// *size = strlen(data);
318+//
319+// b64 = BIO_new(BIO_f_base64());
320+// mem = BIO_new_mem_buf(data, *size);
321+// b64 = BIO_push(b64, mem);
322+//
323+// BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
324+//
325+// /* alloc a very big buffer */
326+// xs_str *s = xs_realloc(NULL, *size);
327+//
328+// *size = BIO_read(b64, s, *size);
329+//
330+// /* adjust to current size */
331+// s = xs_realloc(s, _xs_blk_size(*size + 1));
332+// s[*size] = '\0';
333+//
334+// BIO_free_all(b64);
335+//
336+// return s;
337+// }
338+//
339+// #endif /* _XS_BASE64_H */
340+//
341+//
342+// xs_str *_xs_digest(const xs_val *input, int size, const char *digest, int as_hex)
343+// /* generic function for generating and encoding digests */
344+// {
345+// const EVP_MD *md;
346+//
347+// if ((md = EVP_get_digestbyname(digest)) == NULL)
348+// return NULL;
349+//
350+// unsigned char output[1024];
351+// unsigned int out_size;
352+// EVP_MD_CTX *mdctx;
353+//
354+// mdctx = EVP_MD_CTX_new();
355+// EVP_DigestInit_ex(mdctx, md, NULL);
356+// EVP_DigestUpdate(mdctx, input, size);
357+// EVP_DigestFinal_ex(mdctx, output, &out_size);
358+// EVP_MD_CTX_free(mdctx);
359+//
360+// return as_hex ? xs_hex_enc ((char *)output, out_size) :
361+// xs_base64_enc((char *)output, out_size);
362+// }
363+//
364+//
365+// xs_dict *xs_evp_genkey(int bits)
366+// /* generates an RSA keypair using the EVP interface */
367+// {
368+// xs_dict *keypair = NULL;
369+// EVP_PKEY_CTX *ctx = NULL;
370+// EVP_PKEY *pkey = NULL;
371+//
372+// if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL)
373+// return NULL;
374+//
375+// if (EVP_PKEY_keygen_init(ctx) <= 0 ||
376+// EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0 ||
377+// EVP_PKEY_keygen(ctx, &pkey) <= 0)
378+// return NULL;
379+//
380+// BIO *bs = BIO_new(BIO_s_mem());
381+// BIO *bp = BIO_new(BIO_s_mem());
382+// BUF_MEM *sptr;
383+// BUF_MEM *pptr;
384+//
385+// PEM_write_bio_PrivateKey(bs, pkey, NULL, NULL, 0, 0, NULL);
386+// BIO_get_mem_ptr(bs, &sptr);
387+//
388+// PEM_write_bio_PUBKEY(bp, pkey);
389+// BIO_get_mem_ptr(bp, &pptr);
390+//
391+// keypair = xs_dict_new();
392+//
393+// xs *secret = xs_str_new_sz(sptr->data, sptr->length);
394+// xs *public = xs_str_new_sz(pptr->data, pptr->length);
395+// keypair = xs_dict_append(keypair, "secret", secret);
396+// keypair = xs_dict_append(keypair, "public", public);
397+//
398+// BIO_free(bs);
399+// BIO_free(bp);
400+//
401+// EVP_PKEY_free(pkey);
402+// EVP_PKEY_CTX_free(ctx);
403+//
404+// return keypair;
405+// }
406+//
407+//
408+// xs_str *xs_evp_sign(const char *secret, const char *mem, int size)
409+// /* signs a memory block (secret is in PEM format) */
410+// {
411+// xs_str *signature = NULL;
412+// BIO *b;
413+// unsigned char *sig;
414+// unsigned int sig_len;
415+// EVP_PKEY *pkey;
416+// EVP_MD_CTX *mdctx;
417+// const EVP_MD *md;
418+//
419+// /* un-PEM the key */
420+// b = BIO_new_mem_buf(secret, strlen(secret));
421+// pkey = PEM_read_bio_PrivateKey(b, NULL, NULL, NULL);
422+//
423+// /* I've learnt all these magical incantations by watching
424+// the Python module code and the OpenSSL manual pages */
425+// /* Well, "learnt" may be an overstatement */
426+//
427+// md = EVP_get_digestbyname("sha256");
428+//
429+// mdctx = EVP_MD_CTX_new();
430+//
431+// sig_len = EVP_PKEY_size(pkey);
432+// sig = xs_realloc(NULL, sig_len);
433+//
434+// EVP_SignInit(mdctx, md);
435+// EVP_SignUpdate(mdctx, mem, size);
436+//
437+// if (EVP_SignFinal(mdctx, sig, &sig_len, pkey) == 1)
438+// signature = xs_base64_enc((char *)sig, sig_len);
439+//
440+// EVP_MD_CTX_free(mdctx);
441+// EVP_PKEY_free(pkey);
442+// BIO_free(b);
443+// xs_free(sig);
444+//
445+// return signature;
446+// }
447+//
448+//
449+// int xs_evp_verify(const char *pubkey, const char *mem, int size, const char *b64sig)
450+// /* verifies a base64 block, returns non-zero on ok */
451+// {
452+// int r = 0;
453+// BIO *b;
454+// EVP_PKEY *pkey;
455+// EVP_MD_CTX *mdctx;
456+// const EVP_MD *md;
457+//
458+// /* un-PEM the key */
459+// b = BIO_new_mem_buf(pubkey, strlen(pubkey));
460+// pkey = PEM_read_bio_PUBKEY(b, NULL, NULL, NULL);
461+//
462+// md = EVP_get_digestbyname("sha256");
463+// mdctx = EVP_MD_CTX_new();
464+//
465+// if (pkey != NULL) {
466+// xs *sig = NULL;
467+// int s_size;
468+//
469+// /* de-base64 */
470+// sig = xs_base64_dec(b64sig, &s_size);
471+//
472+// if (sig != NULL) {
473+// EVP_VerifyInit(mdctx, md);
474+// EVP_VerifyUpdate(mdctx, mem, size);
475+//
476+// r = EVP_VerifyFinal(mdctx, (unsigned char *)sig, s_size, pkey);
477+// }
478+// }
479+//
480+// EVP_MD_CTX_free(mdctx);
481+// EVP_PKEY_free(pkey);
482+// BIO_free(b);
483+//
484+// return r;
485+// }
486+//
487+//
488+// #endif /* XS_IMPLEMENTATION */
489+//
490+// #endif /* _XS_OPENSSL_H */