feat: add Std::Crypto — SHA-256, HMAC-SHA256, Base64, random bytes

- C runtime (OpenSSL): bux_sha256, bux_hmac_sha256, bux_random_bytes,
  bux_base64_encode, bux_base64_decode, bux_bytes_to_hex
- library/std/Crypto.bux: Crypto_Sha256, Crypto_HmacSha256,
  Crypto_HmacSha256Raw, Crypto_RandomBytes, Crypto_Base64Encode,
  Crypto_Base64Decode
- examples/jwt.bux: full JWT creation with HS256 signature
- Link with -lcrypto in C backend
This commit is contained in:
2026-06-05 21:34:37 +03:00
parent fd9abb12be
commit fe31ddbc4b
6 changed files with 198 additions and 1 deletions
+56
View File
@@ -1248,3 +1248,59 @@ int bux_socket_close(int fd) {
const char* bux_socket_error(void) {
return strerror(errno);
}
/* ============================================================================
* Cryptography primitives (OpenSSL)
* ============================================================================ */
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
void bux_sha256(const char* data, int len, unsigned char* out) {
EVP_MD_CTX* ctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
EVP_DigestUpdate(ctx, data, (size_t)len);
EVP_DigestFinal_ex(ctx, out, NULL);
EVP_MD_CTX_free(ctx);
}
void bux_hmac_sha256(const char* key, int keylen, const char* msg, int msglen, unsigned char* out) {
unsigned int outlen = 32;
HMAC(EVP_sha256(), key, keylen, (const unsigned char*)msg, (size_t)msglen, out, &outlen);
}
int bux_random_bytes(unsigned char* buf, int len) {
return RAND_bytes(buf, len);
}
char* bux_base64_encode(const unsigned char* in, int inlen) {
int outlen = 4 * ((inlen + 2) / 3);
char* out = (char*)bux_alloc(outlen + 1);
int elen = EVP_EncodeBlock((unsigned char*)out, in, inlen);
out[elen] = '\0';
return out;
}
char* bux_base64_decode(const char* in, int inlen, int* outlen) {
int maxlen = 3 * inlen / 4;
char* out = (char*)bux_alloc(maxlen + 1);
*outlen = EVP_DecodeBlock((unsigned char*)out, (const unsigned char*)in, inlen);
if (*outlen < 0) {
*outlen = 0;
out[0] = '\0';
}
return out;
}
char* bux_bytes_to_hex(const unsigned char* data, int len) {
char* out = (char*)bux_alloc((size_t)len * 2 + 1);
const char* hex = "0123456789abcdef";
for (int i = 0; i < len; i++) {
out[i * 2] = hex[(data[i] >> 4) & 0x0F];
out[i * 2 + 1] = hex[data[i] & 0x0F];
}
out[len * 2] = '\0';
return out;
}
+64
View File
@@ -0,0 +1,64 @@
module Std::Crypto {
extern func bux_sha256(data: String, len: int, out: *void);
extern func bux_hmac_sha256(key: String, keylen: int, msg: String, msglen: int, out: *void);
extern func bux_random_bytes(buf: *void, len: int) -> int;
extern func bux_base64_encode(data: String, len: int) -> String;
extern func bux_base64_decode(data: String, len: int, outlen: *int) -> String;
extern func bux_bytes_to_hex(data: *void, len: int) -> String;
/* SHA-256: returns lowercase hex string of the hash */
func Crypto_Sha256(data: String) -> String {
let len: int = String_Len(data) as int;
let hashBuf: *void = Alloc(32);
bux_sha256(data, len, hashBuf);
let result: String = bux_bytes_to_hex(hashBuf as *void, 32);
Free(hashBuf);
return result;
}
/* HMAC-SHA256: returns lowercase hex string */
func Crypto_HmacSha256(key: String, message: String) -> String {
let keylen: int = String_Len(key) as int;
let msglen: int = String_Len(message) as int;
let hmacBuf: *void = Alloc(32);
bux_hmac_sha256(key, keylen, message, msglen, hmacBuf);
let result: String = bux_bytes_to_hex(hmacBuf as *void, 32);
Free(hmacBuf);
return result;
}
/* Random bytes: returns a string of n random bytes */
func Crypto_RandomBytes(n: int) -> String {
if n <= 0 { return ""; }
let buf: *void = Alloc(n as uint);
if bux_random_bytes(buf, n) != 1 {
Free(buf);
return "";
}
let result: String = bux_base64_encode(buf as String, n);
Free(buf);
return result;
}
/* Base64 encode */
func Crypto_Base64Encode(s: String) -> String {
return bux_base64_encode(s, String_Len(s) as int);
}
/* HMAC-SHA256 raw: returns base64 of raw binary hmac */
func Crypto_HmacSha256Raw(key: String, message: String) -> String {
let keylen: int = String_Len(key) as int;
let msglen: int = String_Len(message) as int;
let hmacBuf: *void = Alloc(32);
bux_hmac_sha256(key, keylen, message, msglen, hmacBuf);
let result: String = bux_base64_encode(hmacBuf as String, 32);
Free(hmacBuf);
return result;
}
/* Base64 decode */
func Crypto_Base64Decode(s: String) -> String {
let outlen: int = 0;
return bux_base64_decode(s, String_Len(s) as int, &outlen);
}
}