commit e6def96

V. Luna  ·  2026-10-08 02:27:31 +0000 UTC
parent b355650
evp sign
1 files changed,  +215, -10
+215, -10
  1@@ -10,7 +10,10 @@ xs_str* xs_base64_enc(const xs_val *data, int size);
  2 
  3 #ifdef XS_IMPLEMENTATION
  4 
  5+#include "bearssl_x509.h"
  6 #include "bearssl_hash.h"
  7+#include "bearssl_pem.h"
  8+#include "bearssl_rsa.h"
  9 
 10 #ifndef _XS_BASE64_H
 11 /* *
 12@@ -24,9 +27,9 @@ xs_str* xs_base64_enc(const xs_val *data, int size);
 13  * meatride this lib so much but I hope this gets you to join minx cafe.
 14  * */
 15 
 16-static const char b64_tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 17+static const char _b64_tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 18 
 19-static int b64_val(int c) {
 20+static int _b64_val(int c) {
 21         if (c >= 'A' && c <= 'Z') return c - 'A';
 22         if (c >= 'a' && c <= 'z') return c - 'a' + 26;
 23         if (c >= '0' && c <= '9') return c - '0' + 52;
 24@@ -50,10 +53,10 @@ xs_str* xs_base64_enc(const xs_val* data, int size) { // NOLINT
 25         while (i + b64_bytes - 1 < size) {
 26                 unsigned int v = (d[i] << 16) | (d[i + 1] << 8) | d[i + 2];
 27 
 28-                s[j++] = b64_tab[(v >> 18) & 0x3f];
 29-                s[j++] = b64_tab[(v >> 12) & 0x3f];
 30-                s[j++] = b64_tab[(v >> 6) & 0x3f];
 31-                s[j++] = b64_tab[v & 0x3f];
 32+                s[j++] = _b64_tab[(v >> 18) & 0x3f];
 33+                s[j++] = _b64_tab[(v >> 12) & 0x3f];
 34+                s[j++] = _b64_tab[(v >> 6) & 0x3f];
 35+                s[j++] = _b64_tab[v & 0x3f];
 36                 i += b64_bytes;
 37         }
 38 
 39@@ -63,9 +66,9 @@ xs_str* xs_base64_enc(const xs_val* data, int size) { // NOLINT
 40 
 41                 if (rem == 2) { v |= d[i + 1] << 8; }
 42 
 43-                s[j++] = b64_tab[(v >> 18) & 0x3f];
 44-                s[j++] = b64_tab[(v >> 12) & 0x3f];
 45-                s[j++] = (rem == 2) ? b64_tab[(v >> 6) & 0x3f] : '=';
 46+                s[j++] = _b64_tab[(v >> 18) & 0x3f];
 47+                s[j++] = _b64_tab[(v >> 12) & 0x3f];
 48+                s[j++] = (rem == 2) ? _b64_tab[(v >> 6) & 0x3f] : '=';
 49                 s[j++] = '=';
 50         }
 51 
 52@@ -88,7 +91,7 @@ xs_val* xs_base64_dec(const xs_str* data, int* size) {
 53                         continue;
 54                 }
 55 
 56-                v = b64_val(c);
 57+                v = _b64_val(c);
 58                 if (v < 0) { continue; }
 59 
 60                 acc = (acc << 6) | v;
 61@@ -146,6 +149,208 @@ xs_str* _xs_digest(const xs_val* input, int size, const char* digest, int as_hex
 62         return as_hex ? xs_hex_enc((char*)out, n) : xs_base64_enc((char*)out, n);
 63 }
 64 
 65+struct _pembuf {
 66+        unsigned char* ptr;
 67+        size_t len;
 68+        size_t cap;
 69+};
 70+
 71+static void _pem_sink(void* vctx, const void* data, size_t len) {
 72+        struct _pembuf* buf = vctx;
 73+
 74+        if (buf->len + len > buf->cap) {
 75+                buf->cap = (buf->len + len) * 2 + 64;
 76+                buf->ptr = xs_realloc(buf->ptr, (int)buf->cap);
 77+        }
 78+        
 79+        memcpy(buf->ptr + buf->len, data, len);
 80+        buf->len += len;
 81+}
 82+
 83+static unsigned char* _pem_to_der(const char* pem, size_t* out_len) {
 84+        br_pem_decoder_context pctx;
 85+        struct _pembuf buf = {0};
 86+
 87+        const char* src = pem;
 88+        
 89+        br_pem_decoder_init(&pctx);
 90+        br_pem_decoder_setdest(&pctx, _pem_sink, &buf);
 91+
 92+        size_t pem_len = strlen(pem);
 93+        int done = 0;
 94+        while (pem_len > 0 && !done) {
 95+                size_t n = br_pem_decoder_push(&pctx, src, pem_len);
 96+                int ev;
 97+
 98+                src += n;
 99+                pem_len -= n;
100+                ev = br_pem_decoder_event(&pctx);
101+
102+                if (ev == BR_PEM_END_OBJ) {
103+                        done = 1;
104+                } 
105+
106+                if (ev == BR_PEM_ERROR) {
107+                        xs_free(buf.ptr);
108+                        return NULL;
109+                }
110+
111+                if (n == 0 && ev == 0) { break; }
112+        }
113+
114+        if (!done || buf.ptr == NULL) {
115+                xs_free(buf.ptr);
116+                return NULL;
117+        }
118+
119+        *out_len = buf.len;
120+        return buf.ptr;
121+}
122+
123+static int _der_tlv(const unsigned char* p[], const unsigned char* end, unsigned char* tag, size_t* len, const unsigned char* val[]) {
124+        const unsigned char *b = *p;
125+        size_t l;
126+
127+        if (b >= end) { return 0; }
128+
129+        *tag = *b++;
130+
131+        if (b >= end) { return 0; }
132+
133+        l = *b++;
134+
135+        if (l & 0x80) {
136+                int nb = l & 0x7f;
137+
138+                if (nb == 0 || nb > 4) {return 0; }
139+
140+                l = 0;
141+                while (nb--) {
142+                        if (b >= end) { return 0; }
143+
144+                        l = (l << 8) | *b++;
145+                }
146+        }
147+
148+        if ((size_t)(end - b) < l) { return 0; }
149+
150+        *len = l;
151+        *val = b;
152+        *p = b + l;
153+
154+        return 1;
155+}
156+
157+static size_t _der_put(unsigned char* dst, unsigned char tag, const unsigned char* content, size_t c_len) {
158+        size_t hl;
159+
160+        if (c_len < 128) {
161+                dst[0] = tag;
162+                dst[1] = (unsigned char)c_len;
163+                hl = 2;
164+        } else if (c_len < 256) {
165+                dst[0] = tag;
166+                dst[1] = 0x81;
167+                dst[2] = (unsigned char)c_len;
168+                hl = 3;
169+        } else {
170+                dst[0] = tag;
171+                dst[1] = 0x82;
172+                dst[2] = (unsigned char)(c_len >> 8);
173+                dst[3] = (unsigned char)c_len;
174+                hl = 4;
175+        } 
176+
177+        if (content) { memmove(dst + hl, content, c_len); }
178+
179+        return hl + c_len;
180+}
181+
182+static size_t _der_uint(unsigned char *dst, const unsigned char *v, size_t len) {
183+        unsigned char tmp[600];
184+        int pad;
185+        size_t clen;
186+
187+        while (len > 1 && v[0] == 0) {
188+                v++;
189+                len--;
190+        }
191+
192+        pad = (len > 0 && (v[0] & 0x80)) ? 1 : 0;
193+        clen = len + pad;
194+
195+        if (pad) { tmp[0] = 0; } 
196+
197+        memcpy(tmp + pad, v, len);
198+
199+        return _der_put(dst, 0x02, tmp, clen);
200+}
201+
202+// TODO: this
203+static int _parse_spki(const unsigned char* der, size_t len, br_rsa_public_key* pk) {
204+        const unsigned char* p = der, *end = der + len;
205+        const unsigned char* v;
206+        unsigned char tag;
207+        size_t l;
208+
209+        // if (!der_tlv(&p))
210+
211+        return 0;
212+}
213+
214+/* RSA sign / verify / keygen */
215+xs_str* xs_evp_sign(const char* secret, const char* mem, int size) {
216+        xs_str* signature = NULL;
217+        unsigned char* der;
218+        size_t der_len;
219+
220+        der = _pem_to_der(secret, &der_len);
221+
222+        if (der != NULL) {
223+                br_skey_decoder_context skey_ctx;
224+                const br_rsa_private_key* skey;
225+
226+                br_skey_decoder_init(&skey_ctx);
227+                br_skey_decoder_push(&skey_ctx, der, der_len);
228+                skey = br_skey_decoder_get_rsa(&skey_ctx);
229+
230+                if (skey != NULL) {
231+                        unsigned char hash[32];
232+                        br_sha256_context sha_ctx;
233+                        size_t sig_len = (skey->n_bitlen + 7) / 8;
234+                        unsigned char* sig = xs_realloc(NULL, (int)sig_len);
235+
236+                        br_sha256_init(&sha_ctx);
237+                        br_sha256_update(&sha_ctx, mem, size);
238+                        br_sha256_out(&sha_ctx, hash);
239+
240+                        if (br_rsa_i31_pkcs1_sign(BR_HASH_OID_SHA256, hash, 32, skey, sig)) {
241+                                signature = xs_base64_enc((char*)sig, (int)sig_len);
242+                        }
243+
244+                        xs_free(sig);
245+                }
246+
247+                xs_free(der);
248+        }
249+
250+        return signature;
251+}
252+
253+int xs_evp_verify(const char* pubkey, const char* mem, int size, const char* b64_sig) {
254+        unsigned char* der;
255+        size_t der_len;
256+
257+        der = _pem_to_der(pubkey, &der_len);
258+
259+        int r = 0;
260+        if (der != NULL) {
261+                br_rsa_public_key pkey;
262+        }
263+
264+        // TODO: 
265+}
266+
267 #endif // XS_IMPLEMENTATION
268 
269 #endif // _XS_BEARSSL_H