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