Last active
July 29, 2022 20:53
-
-
Save rubpy/84b59da6970c764ebefab096c253c172 to your computer and use it in GitHub Desktop.
encrypt_with_bear - a handy wrapper for the low-level BearSSL RSA encryption API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bearssl.h> | |
#include <derdec.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <string.h> | |
/* (RSA-2048) | |
-----BEGIN PUBLIC KEY----- | |
MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBez9MX9NzGasT/wlMKgLPL | |
Ct3zg+OmlJmP+QgRSkbfF4bgwlRqrgboyTH1kdtKJ6+DmiazbKHkLMhJuleofkKl | |
ftbO7T7epaJG6wSrM3LDflbOPcThKOeSp1Qg0JKRgllCxzHgS6rcyO4+5vNkeWnh | |
biNTrBInUe7PCpk7NuRRKjH8Um5hTqRvH1WxfO9gvqPj5y4jUhZs9A/Uv78NPNbi | |
9i3DPPN2VIa13DUL5v1CufZdZ0EaSnFV0MIgRJiYUg6KRFM9tU4HNwm85ePrB36L | |
QOp1LYAsQuGvvr50b8n3E+WOyNEadKHnMlMtY5EMP1XKoL646EC3jBOL1aVuIfVv | |
AgMBAAE= | |
-----END PUBLIC KEY----- | |
-----BEGIN RSA PRIVATE KEY----- | |
MIIEogIBAAKCAQBez9MX9NzGasT/wlMKgLPLCt3zg+OmlJmP+QgRSkbfF4bgwlRq | |
rgboyTH1kdtKJ6+DmiazbKHkLMhJuleofkKlftbO7T7epaJG6wSrM3LDflbOPcTh | |
KOeSp1Qg0JKRgllCxzHgS6rcyO4+5vNkeWnhbiNTrBInUe7PCpk7NuRRKjH8Um5h | |
TqRvH1WxfO9gvqPj5y4jUhZs9A/Uv78NPNbi9i3DPPN2VIa13DUL5v1CufZdZ0Ea | |
SnFV0MIgRJiYUg6KRFM9tU4HNwm85ePrB36LQOp1LYAsQuGvvr50b8n3E+WOyNEa | |
dKHnMlMtY5EMP1XKoL646EC3jBOL1aVuIfVvAgMBAAECggEAIvBlMyPaJAh+ll2v | |
KmSpXP6hMjb9Mor6WBMGhRChM19BJhyW7UU6aJiUH5HjhN1BEbdB4cb7ldFm8byI | |
xx/YQZKPaGwHShcxyP6cltZ7yU0KgjBDGFJxnBqrpvgVuyeU60XqvGRGD9y/51BG | |
i1UuzpM+03vKqNDJt2SJeUfONZZq5Qg/EAws+HMR5zPtERsNk7IMxVOb0AEs7ORD | |
fU46MZnbaYi9c7tp8u8n0xJHtGXr1WoY8q0alfDKn65Hkz1PxMQ9x4jPaZUtvf/j | |
gZkk4jyNwcevlUdE3kp9mFdfcL4YA0uMiEnqS66uygYF4B+xYNPNO39gdy+6Fuz2 | |
XJuJqQKBgQCpHYXsh2P+m+pXzIKrV6/g/JEdUXN21k/pTi2Zoq/LEYZrmV9J7qSE | |
qonGFWifLDsokk0qvlAp9uVID5gnWH+P+vmeEOktfISZcH6B03haGGYL6LLqNhwG | |
BuTawmLbfxCLXB/CUjtxuBbtCETHAD+IWImJMNyFXE2wy4ysdxVl2wKBgQCPhbcV | |
a8UMqMvLO/kxOw51Ehm3ENnEYpMC1bgJeq/neP1lKnJ/Ir7RzNAWjoG655gqy0L6 | |
a48e8Scw65iN2mcjQuXPtYfikfZcH/OStX3sQ8ac45L7qy4C7+jY4qQhwseXnuFT | |
AVo+S/4AEgKwlYyQm110WrQJ5XGygk5zHPSk/QKBgEUkr/vcAzM3NiH9mLNLX7qC | |
KSauhaHhz7xY3WYCUROar7XQeFg2/QbM3xWg7SyfHfThlDFUrFvr+SR0U8ZKdaU9 | |
fM92pI+XaHN/vgmAl6VmclqOIpCF3QFN0kXq0hZiJjaETOvbSTiehqkVB2HBpTgu | |
0tTHqHHSImWVY4ekDJifAoGAOPOgoRlwygM5S15zFfwPUplqJuDC6VEMcTWJoAlV | |
QA8czkY3xQdunSYe9LR7+kTodyLNYz3HP0oGeT0j/jZKcw2az/+C+n9dOVVcfD0U | |
yOpkJ+GOc9uLmJLG3TmiU9tNBHeBhkSlIM9a7YA4HQZbDw732LIde0fXBDT9GGTH | |
F6kCgYEAoibOpeO4NMq8pzFdK9ahGXLgk7ECW+Bk5gXvgLvUdLIMqxKy0hkOTtbn | |
sN75ZEKc5vQzqmiIl9gBR9hVcKwFR7jUH1I3KOdwJc0qxenWe4ZhAj9PDOrhKuDD | |
cqAdRAy5UN2TSpU4AWaF5qpfk2Dorjy+ytqpKGY9QBxjPDaygNA= | |
-----END RSA PRIVATE KEY----- | |
*/ | |
static const uint8_t sample_raw_pkey[] = { | |
0x30, 0x82, 0x01, 0x21, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, | |
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0e, 0x00, | |
0x30, 0x82, 0x01, 0x09, 0x02, 0x82, 0x01, 0x00, 0x5e, 0xcf, 0xd3, 0x17, | |
0xf4, 0xdc, 0xc6, 0x6a, 0xc4, 0xff, 0xc2, 0x53, 0x0a, 0x80, 0xb3, 0xcb, | |
0x0a, 0xdd, 0xf3, 0x83, 0xe3, 0xa6, 0x94, 0x99, 0x8f, 0xf9, 0x08, 0x11, | |
0x4a, 0x46, 0xdf, 0x17, 0x86, 0xe0, 0xc2, 0x54, 0x6a, 0xae, 0x06, 0xe8, | |
0xc9, 0x31, 0xf5, 0x91, 0xdb, 0x4a, 0x27, 0xaf, 0x83, 0x9a, 0x26, 0xb3, | |
0x6c, 0xa1, 0xe4, 0x2c, 0xc8, 0x49, 0xba, 0x57, 0xa8, 0x7e, 0x42, 0xa5, | |
0x7e, 0xd6, 0xce, 0xed, 0x3e, 0xde, 0xa5, 0xa2, 0x46, 0xeb, 0x04, 0xab, | |
0x33, 0x72, 0xc3, 0x7e, 0x56, 0xce, 0x3d, 0xc4, 0xe1, 0x28, 0xe7, 0x92, | |
0xa7, 0x54, 0x20, 0xd0, 0x92, 0x91, 0x82, 0x59, 0x42, 0xc7, 0x31, 0xe0, | |
0x4b, 0xaa, 0xdc, 0xc8, 0xee, 0x3e, 0xe6, 0xf3, 0x64, 0x79, 0x69, 0xe1, | |
0x6e, 0x23, 0x53, 0xac, 0x12, 0x27, 0x51, 0xee, 0xcf, 0x0a, 0x99, 0x3b, | |
0x36, 0xe4, 0x51, 0x2a, 0x31, 0xfc, 0x52, 0x6e, 0x61, 0x4e, 0xa4, 0x6f, | |
0x1f, 0x55, 0xb1, 0x7c, 0xef, 0x60, 0xbe, 0xa3, 0xe3, 0xe7, 0x2e, 0x23, | |
0x52, 0x16, 0x6c, 0xf4, 0x0f, 0xd4, 0xbf, 0xbf, 0x0d, 0x3c, 0xd6, 0xe2, | |
0xf6, 0x2d, 0xc3, 0x3c, 0xf3, 0x76, 0x54, 0x86, 0xb5, 0xdc, 0x35, 0x0b, | |
0xe6, 0xfd, 0x42, 0xb9, 0xf6, 0x5d, 0x67, 0x41, 0x1a, 0x4a, 0x71, 0x55, | |
0xd0, 0xc2, 0x20, 0x44, 0x98, 0x98, 0x52, 0x0e, 0x8a, 0x44, 0x53, 0x3d, | |
0xb5, 0x4e, 0x07, 0x37, 0x09, 0xbc, 0xe5, 0xe3, 0xeb, 0x07, 0x7e, 0x8b, | |
0x40, 0xea, 0x75, 0x2d, 0x80, 0x2c, 0x42, 0xe1, 0xaf, 0xbe, 0xbe, 0x74, | |
0x6f, 0xc9, 0xf7, 0x13, 0xe5, 0x8e, 0xc8, 0xd1, 0x1a, 0x74, 0xa1, 0xe7, | |
0x32, 0x53, 0x2d, 0x63, 0x91, 0x0c, 0x3f, 0x55, 0xca, 0xa0, 0xbe, 0xb8, | |
0xe8, 0x40, 0xb7, 0x8c, 0x13, 0x8b, 0xd5, 0xa5, 0x6e, 0x21, 0xf5, 0x6f, | |
0x02, 0x03, 0x01, 0x00, 0x01, | |
}; | |
static const size_t sample_raw_pkey_len = sizeof(sample_raw_pkey); | |
// -------------------------------------------------- | |
// clang-format off | |
/** | |
* A handy wrapper for the low-level BearSSL RSA encryption API. | |
* | |
* On success, returns 0. | |
* On failure, returns a non-zero value (e.g., -1). | |
* | |
* === Usage === | |
* | |
* ```c | |
* | |
* int main(void) { | |
* derdec_pkey pkey; | |
* | |
* // derdec_decode_pkey(&pkey, ...); | |
* // ... | |
* | |
* const char *plaintext = "hello world"; | |
* uint8_t buf[256]; | |
* | |
* if (encrypt_with_bear( | |
* buf, | |
* sizeof(buf), | |
* plaintext, | |
* strlen(plaintext), | |
* &pkey) != 0) { | |
* fprintf(stderr, "[!] encrypt_with_bear failed\n"); | |
* | |
* return 1; | |
* } | |
* | |
* for (size_t i = 0; i < sizeof(buf); ++i) { | |
* printf("%02x", buf[i]); | |
* } | |
* printf("\n"); | |
* | |
* return 0; | |
* } | |
* | |
* ``` | |
* | |
*/ | |
// clang-format on | |
int encrypt_with_bear(uint8_t *buf, size_t buf_len, const char *const plaintext, | |
size_t plaintext_len, const derdec_pkey *const pkey) { | |
if (buf == NULL || buf_len != 256 || plaintext == NULL || | |
plaintext_len == 0 || pkey == NULL) { | |
// ERROR: invalid arguments. | |
return -1; | |
} | |
memset(buf, 0, buf_len); | |
if (plaintext_len > 245) { | |
// ERROR: plaintext is too long. | |
return -2; | |
} | |
if ((pkey->modulus.start == NULL || pkey->modulus.end == NULL) || | |
(pkey->exponent.start == NULL || pkey->exponent.end == NULL)) { | |
// ERROR: invalid public key given. | |
return -3; | |
} | |
if (derdec_pkcs1(buf, buf_len, (const uint8_t *)plaintext, plaintext_len, | |
0) != DERDEC_OK) { | |
// ERROR: PKCS#1 encoder has failed. | |
return -4; | |
} | |
const br_rsa_public_key pkey_bear = { | |
(unsigned char *)derdec_pkey_modulus(pkey), | |
derdec_pkey_modulus_size(pkey), | |
(unsigned char *)derdec_pkey_exponent(pkey), | |
derdec_pkey_exponent_size(pkey), | |
}; | |
br_rsa_public rsa_pub_engine = br_rsa_public_get_default(); | |
if (!rsa_pub_engine(buf, buf_len, &pkey_bear)) { | |
// ERROR: BearSSL's RSA-2048 encryption engine has failed. | |
return -5; | |
} | |
// OK: plaintext has been encrypted successfully. Result was saved into `buf`. | |
return 0; | |
} | |
// -------------------------------------------------- | |
int main(void) { | |
derdec_pkey pkey; | |
derdec_err err; | |
if ((err = derdec_decode_pkey(&pkey, sample_raw_pkey, sample_raw_pkey_len)) != | |
DERDEC_OK) { | |
fprintf(stderr, "[!] derdec_decode_pkey failed: %s\n", derdec_err_str(err)); | |
return 1; | |
} | |
if (!derdec_pkey_is_pkcs1(&pkey)) { | |
fprintf(stderr, "[!] pkey is not a PKCS1 public key\n"); | |
return 2; | |
} | |
const char *plaintext = "hello world"; | |
uint8_t buf[256]; | |
if (encrypt_with_bear(buf, sizeof(buf), plaintext, strlen(plaintext), | |
&pkey) != 0) { | |
fprintf(stderr, "[!] encrypt_with_bear failed\n"); | |
return 3; | |
} | |
for (size_t i = 0; i < sizeof(buf); ++i) { | |
printf("%02x", buf[i]); | |
} | |
printf("\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment