snac2/xs_openssl.h

262 lines
6.1 KiB
C
Raw Permalink Normal View History

2023-01-17 08:50:16 +00:00
/* copyright (c) 2022 - 2023 grunfink / MIT license */
2022-09-19 18:41:11 +00:00
#ifndef _XS_OPENSSL_H
#define _XS_OPENSSL_H
2023-01-28 16:49:02 +00:00
xs_str *xs_md5_hex(const xs_val *input, int size);
xs_str *xs_sha1_hex(const xs_val *input, int size);
xs_str *xs_sha256_hex(const xs_val *input, int size);
xs_str *xs_sha256_base64(const xs_val *input, int size);
xs_dict *xs_rsa_genkey(int bits);
xs_str *xs_rsa_sign(const char *secret, const char *mem, int size);
2022-10-08 05:00:05 +00:00
int xs_rsa_verify(const char *pubkey, const char *mem, int size, const char *b64sig);
2023-01-28 16:49:02 +00:00
xs_str *xs_evp_sign(const char *secret, const char *mem, int size);
2022-10-08 05:00:05 +00:00
int xs_evp_verify(const char *pubkey, const char *mem, int size, const char *b64sig);
2022-09-19 18:41:11 +00:00
#ifdef XS_IMPLEMENTATION
#include "openssl/md5.h"
#include "openssl/sha.h"
#include "openssl/rsa.h"
#include "openssl/pem.h"
2022-09-26 12:44:53 +00:00
#include "openssl/evp.h"
2022-09-19 18:41:11 +00:00
2023-01-28 16:49:02 +00:00
xs_str *xs_md5_hex(const xs_val *input, int size)
2022-09-19 18:41:11 +00:00
{
unsigned char md5[16];
MD5_CTX ctx;
MD5_Init(&ctx);
MD5_Update(&ctx, input, size);
MD5_Final(md5, &ctx);
return xs_hex_enc((char *)md5, sizeof(md5));
}
2023-01-28 16:49:02 +00:00
xs_str *xs_sha1_hex(const xs_val *input, int size)
2022-09-19 18:41:11 +00:00
{
unsigned char sha1[20];
SHA_CTX ctx;
SHA1_Init(&ctx);
SHA1_Update(&ctx, input, size);
SHA1_Final(sha1, &ctx);
return xs_hex_enc((char *)sha1, sizeof(sha1));
}
2022-09-21 07:17:59 +00:00
unsigned char *_xs_sha256(const void *input, int size, unsigned char *sha256)
2022-09-19 18:41:11 +00:00
{
SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, input, size);
SHA256_Final(sha256, &ctx);
2022-09-21 07:17:59 +00:00
return sha256;
}
2023-01-28 16:49:02 +00:00
xs_str *xs_sha256_hex(const xs_val *input, int size)
2022-09-21 07:17:59 +00:00
{
unsigned char sha256[32];
_xs_sha256(input, size, sha256);
2022-09-19 18:41:11 +00:00
return xs_hex_enc((char *)sha256, sizeof(sha256));
}
2023-01-28 16:49:02 +00:00
xs_str *xs_sha256_base64(const xs_val *input, int size)
2022-09-21 07:17:59 +00:00
{
unsigned char sha256[32];
_xs_sha256(input, size, sha256);
return xs_base64_enc((char *)sha256, sizeof(sha256));
}
2023-01-28 16:49:02 +00:00
xs_dict *xs_rsa_genkey(int bits)
2022-09-19 18:41:11 +00:00
/* generates an RSA keypair */
{
BIGNUM *bne;
RSA *rsa;
2023-01-28 16:49:02 +00:00
xs_dict *keypair = NULL;
2022-09-19 18:41:11 +00:00
if ((bne = BN_new()) != NULL) {
if (BN_set_word(bne, RSA_F4) == 1) {
if ((rsa = RSA_new()) != NULL) {
if (RSA_generate_key_ex(rsa, bits, bne, NULL) == 1) {
BIO *bs = BIO_new(BIO_s_mem());
BIO *bp = BIO_new(BIO_s_mem());
BUF_MEM *sptr;
BUF_MEM *pptr;
PEM_write_bio_RSAPrivateKey(bs, rsa, NULL, NULL, 0, 0, NULL);
BIO_get_mem_ptr(bs, &sptr);
PEM_write_bio_RSA_PUBKEY(bp, rsa);
BIO_get_mem_ptr(bp, &pptr);
keypair = xs_dict_new();
keypair = xs_dict_append(keypair, "secret", sptr->data);
keypair = xs_dict_append(keypair, "public", pptr->data);
BIO_free(bs);
BIO_free(bp);
}
}
}
}
return keypair;
}
2023-01-28 16:49:02 +00:00
xs_str *xs_rsa_sign(const char *secret, const char *mem, int size)
2022-09-19 18:41:11 +00:00
/* signs a memory block (secret is in PEM format) */
{
2023-01-28 16:49:02 +00:00
xs_str *signature = NULL;
2022-09-19 18:41:11 +00:00
BIO *b;
RSA *rsa;
unsigned char *sig;
unsigned int sig_len;
/* un-PEM the key */
b = BIO_new_mem_buf(secret, strlen(secret));
rsa = PEM_read_bio_RSAPrivateKey(b, NULL, NULL, NULL);
/* alloc space */
2022-10-07 11:48:53 +00:00
sig = xs_realloc(NULL, RSA_size(rsa));
2022-09-19 18:41:11 +00:00
if (RSA_sign(NID_sha256, (unsigned char *)mem, size, sig, &sig_len, rsa) == 1)
signature = xs_base64_enc((char *)sig, sig_len);
BIO_free(b);
RSA_free(rsa);
2022-10-25 07:32:41 +00:00
xs_free(sig);
2022-09-19 18:41:11 +00:00
return signature;
}
2022-10-08 05:00:05 +00:00
int xs_rsa_verify(const char *pubkey, const char *mem, int size, const char *b64sig)
2022-09-19 18:41:11 +00:00
/* verifies a base64 block, returns non-zero on ok */
{
int r = 0;
BIO *b;
RSA *rsa;
/* un-PEM the key */
b = BIO_new_mem_buf(pubkey, strlen(pubkey));
rsa = PEM_read_bio_RSA_PUBKEY(b, NULL, NULL, NULL);
if (rsa != NULL) {
2022-09-29 12:16:20 +00:00
xs *sig = NULL;
2022-09-19 18:41:11 +00:00
int s_size;
/* de-base64 */
sig = xs_base64_dec(b64sig, &s_size);
if (sig != NULL)
r = RSA_verify(NID_sha256, (unsigned char *)mem, size,
(unsigned char *)sig, s_size, rsa);
}
BIO_free(b);
RSA_free(rsa);
return r;
}
2022-09-26 12:44:53 +00:00
2023-01-28 16:49:02 +00:00
xs_str *xs_evp_sign(const char *secret, const char *mem, int size)
2022-09-26 12:44:53 +00:00
/* signs a memory block (secret is in PEM format) */
{
2023-01-28 16:49:02 +00:00
xs_str *signature = NULL;
2022-09-26 12:44:53 +00:00
BIO *b;
unsigned char *sig;
unsigned int sig_len;
EVP_PKEY *pkey;
EVP_MD_CTX *mdctx;
const EVP_MD *md;
/* un-PEM the key */
b = BIO_new_mem_buf(secret, strlen(secret));
pkey = PEM_read_bio_PrivateKey(b, NULL, NULL, NULL);
2022-09-26 16:40:46 +00:00
/* I've learnt all these magical incantations by watching
the Python module code and the OpenSSL manual pages */
2022-09-27 08:03:41 +00:00
/* Well, "learnt" may be an overstatement */
2022-09-26 16:40:46 +00:00
2022-09-26 12:44:53 +00:00
md = EVP_get_digestbyname("sha256");
mdctx = EVP_MD_CTX_new();
sig_len = EVP_PKEY_size(pkey);
2022-10-07 11:48:53 +00:00
sig = xs_realloc(NULL, sig_len);
2022-09-26 12:44:53 +00:00
EVP_SignInit(mdctx, md);
EVP_SignUpdate(mdctx, mem, size);
if (EVP_SignFinal(mdctx, sig, &sig_len, pkey) == 1)
signature = xs_base64_enc((char *)sig, sig_len);
EVP_MD_CTX_free(mdctx);
2022-09-29 12:16:20 +00:00
EVP_PKEY_free(pkey);
2022-09-26 12:44:53 +00:00
BIO_free(b);
2022-10-25 07:32:41 +00:00
xs_free(sig);
2022-09-26 12:44:53 +00:00
return signature;
}
2022-10-08 05:00:05 +00:00
int xs_evp_verify(const char *pubkey, const char *mem, int size, const char *b64sig)
2022-09-29 12:16:20 +00:00
/* verifies a base64 block, returns non-zero on ok */
{
int r = 0;
BIO *b;
EVP_PKEY *pkey;
EVP_MD_CTX *mdctx;
const EVP_MD *md;
/* un-PEM the key */
b = BIO_new_mem_buf(pubkey, strlen(pubkey));
pkey = PEM_read_bio_PUBKEY(b, NULL, NULL, NULL);
md = EVP_get_digestbyname("sha256");
mdctx = EVP_MD_CTX_new();
if (pkey != NULL) {
xs *sig = NULL;
int s_size;
/* de-base64 */
sig = xs_base64_dec(b64sig, &s_size);
if (sig != NULL) {
EVP_VerifyInit(mdctx, md);
EVP_VerifyUpdate(mdctx, mem, size);
r = EVP_VerifyFinal(mdctx, (unsigned char *)sig, s_size, pkey);
}
}
EVP_MD_CTX_free(mdctx);
EVP_PKEY_free(pkey);
BIO_free(b);
return r;
}
2022-09-19 18:41:11 +00:00
#endif /* XS_IMPLEMENTATION */
#endif /* _XS_OPENSSL_H */