diff --git a/packages/atchops/include/atchops/rsa_key.h b/packages/atchops/include/atchops/rsa_key.h index c41894a4..35ad5b46 100644 --- a/packages/atchops/include/atchops/rsa_key.h +++ b/packages/atchops/include/atchops/rsa_key.h @@ -45,6 +45,14 @@ int atchops_rsa_key_public_key_clone(const atchops_rsa_key_public_key *src, atch */ int atchops_rsa_key_private_key_clone(const atchops_rsa_key_private_key *src, atchops_rsa_key_private_key *dst); +/** + * @brief Generate a new RSA 2048 key pair (public and private) + * + * @param public_key the public key struct to populate, assumed to be allocated and initialized. initialized via atchops_rsa_key_public_key_init + * @param private_key the private key struct to populate, assumed to be allocated and initialized. initialized via atchops_rsa_key_private_key_init + */ +int atchops_rsa_key_generate(atchops_rsa_key_public_key *public_key, atchops_rsa_key_private_key *private_key); + /** * @brief Populate a public key struct from a base64 string * diff --git a/packages/atchops/src/rsa.c b/packages/atchops/src/rsa.c index b1199dee..628f89c9 100644 --- a/packages/atchops/src/rsa.c +++ b/packages/atchops/src/rsa.c @@ -407,9 +407,3 @@ exit: { return ret; } } - -int atchops_rsa_generate(atchops_rsa_key_public_key *public_key, atchops_rsa_key_private_key *private_key, - const unsigned int key_size) { - // TODO maybe also introduce `enum atchops_rsa_key_size` ? - return 1; // TODO: implement -} diff --git a/packages/atchops/src/rsa_key.c b/packages/atchops/src/rsa_key.c index 45d52347..8ff64c9d 100644 --- a/packages/atchops/src/rsa_key.c +++ b/packages/atchops/src/rsa_key.c @@ -1,5 +1,6 @@ #include "atchops/rsa_key.h" #include "atchops/base64.h" +#include "atchops/constants.h" #include "atchops/mbedtls.h" #include #include @@ -8,8 +9,6 @@ #define TAG "rsa_key" -#define BASE64_DECODED_KEY_BUFFER_SIZE 8192 // the max buffer size of a decoded RSA key - void atchops_rsa_key_public_key_init(atchops_rsa_key_public_key *public_key) { /* * 1. Validate arguments @@ -177,6 +176,232 @@ int atchops_rsa_key_private_key_clone(const atchops_rsa_key_private_key *src, at exit: { return ret; } } +int atchops_rsa_key_generate(atchops_rsa_key_public_key *public_key, atchops_rsa_key_private_key *private_key) { + int ret = 1; + + /* + * 1. Validate arguments + */ + if (public_key == NULL) { + ret = 1; + atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "public_key is null\n"); + return ret; + } + + if (private_key == NULL) { + ret = 1; + atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "private_key is null\n"); + return ret; + } + + /* + * 2. Variables + */ + mbedtls_entropy_context entropy; + mbedtls_entropy_init(&entropy); + + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ctr_drbg_init(&ctr_drbg); + + mbedtls_pk_context pk; + mbedtls_pk_init(&pk); + + const size_t public_key_base64_size = 1024; // 1024 bytes is sufficient size for a 2048 bit RSA key base64 encoded + char public_key_base64[public_key_base64_size]; + memset(public_key_base64, 0, sizeof(char) * public_key_base64_size); + + const size_t private_key_base64_size = 2048; // 2048 bytes is sufficient size for a 2048 bit RSA key base64 encoded + char private_key_base64[private_key_base64_size]; + memset(private_key_base64, 0, sizeof(char) * private_key_base64_size); + + unsigned char *private_key_non_base64 = + NULL; // holds the raw bytes of the 9 element SEQUENCE of the numbers (0, N, E, D, P, Q, DP, DQ, QP), free later + + unsigned char *private_key_pkcs8 = NULL; // buffer for building the pkcs_8 formatted private key, free later + char *private_key_pkcs8_base64 = NULL; // to hold the base64-encoded pkcs 8 formatted private key, free later + + const size_t temp_buf_size = 4096; // sufficient to hold a private RSA Key in format ----BEGIN .... + unsigned char temp_buf[temp_buf_size]; + + /* + * 3. Seed RNG + */ + if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *)ATCHOPS_RNG_PERSONALIZATION, + strlen(ATCHOPS_RNG_PERSONALIZATION))) != 0) { + atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to seed random number generator\n"); + goto exit; + } + + /* + * 4. Use MbedTLS to generate RSA key pair + */ + if ((ret = mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA))) != 0) { + atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to setup RSA key\n"); + goto exit; + } + + if ((ret = mbedtls_rsa_gen_key(mbedtls_pk_rsa(pk), mbedtls_ctr_drbg_random, &ctr_drbg, 2048, 65537)) != 0) { + atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to generate RSA key\n"); + goto exit; + } + + /* + * 5. Write to public_key_base64 buffer + */ + memset(temp_buf, 0, sizeof(temp_buf)); + if ((ret = mbedtls_pk_write_pubkey_pem(&pk, temp_buf, temp_buf_size)) != 0) { + atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to write public key\n"); + goto exit; + } + + size_t public_key_base64_len = 0; + char *begin = strstr((char *)temp_buf, "-----BEGIN PUBLIC KEY-----"); + char *end = strstr((char *)temp_buf, "-----END PUBLIC KEY-----"); + if (begin != NULL && end != NULL) { + + begin += strlen("-----BEGIN PUBLIC KEY-----"); + while (*begin == '\n' || *begin == '\r' || *begin == ' ') + begin++; + + for (char *src = begin, *dest = public_key_base64; src < end; ++src) { + if (*src != '\n' && *src != '\r') { + *dest++ = *src; + public_key_base64_len++; + } + } + } + + /* + * 6. Write to private_key_base64 buffer (PKCS#8 format) + */ + memset(temp_buf, 0, sizeof(unsigned char) * temp_buf_size); + if ((ret = mbedtls_pk_write_key_pem(&pk, temp_buf, temp_buf_size)) != 0) { + atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to write private key (PKCS#8 format)\n"); + goto exit; + } + + size_t private_key_base64_len = 0; + begin = strstr((char *)temp_buf, "-----BEGIN RSA PRIVATE KEY-----"); + end = strstr((char *)temp_buf, "-----END RSA PRIVATE KEY-----"); + if (begin != NULL && end != NULL) { + begin += strlen("-----BEGIN RSA PRIVATE KEY-----"); + while (*begin == '\n' || *begin == '\r' || *begin == ' ') + begin++; + + for (char *src = begin, *dest = private_key_base64; src < end; ++src) { + if (*src != '\n' && *src != '\r') { + *dest++ = *src; + private_key_base64_len++; + } + } + } + + const size_t private_key_non_base64_size = atchops_base64_decoded_size(private_key_base64_len); + private_key_non_base64 = (unsigned char *)malloc(private_key_non_base64_size); + if (private_key_non_base64 == NULL) { + atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to allocate memory for private_key_non_base64\n"); + goto exit; + } + + size_t private_key_non_base64_len = 0; + if ((ret = atchops_base64_decode((const unsigned char *)private_key_base64, private_key_base64_len, + private_key_non_base64, private_key_non_base64_size, &private_key_non_base64_len)) != + 0) { + atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to decode private key\n"); + goto exit; + } + + const size_t private_key_pkcs8_size = private_key_non_base64_len + 22; + private_key_pkcs8 = (unsigned char *)malloc(private_key_pkcs8_size); + if (private_key_pkcs8 == NULL) { + atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to allocate memory for private_key_pkcs8\n"); + goto exit; + } + memset(private_key_pkcs8, 0, sizeof(unsigned char) * private_key_pkcs8_size); + + + // https://lapo.it/asn1js/ use this to debug + // PrivateKeyInfo SEQUENCE (3 elements) + private_key_pkcs8[0] = 0x30; // constructed sequence tag + private_key_pkcs8[1] = 0x82; // 8 --> 1000 0000 (1 in MSB means that it is long form) and 2 --> 0010 0000 (the next 2 + // bytes are the length of data) + private_key_pkcs8[2] = (unsigned char)((private_key_pkcs8_size >> 8) & 0xFF); + private_key_pkcs8[3] = (unsigned char)(private_key_pkcs8_size & 0xFF); + + // version INTEGER 0 + private_key_pkcs8[4] = 0x02; // integer tag + private_key_pkcs8[5] = 0x01; // length of data + private_key_pkcs8[6] = 0x00; // data + + // private key algorithm identifier + private_key_pkcs8[7] = 0x30; // constructed sequence tag + private_key_pkcs8[8] = 0x0D; // there are 2 elements in the sequence + private_key_pkcs8[9] = 0x06; + private_key_pkcs8[10] = 0x09; + private_key_pkcs8[11] = 0x2A; + private_key_pkcs8[12] = 0x86; + private_key_pkcs8[13] = 0x48; + private_key_pkcs8[14] = 0x86; + private_key_pkcs8[15] = 0xF7; + private_key_pkcs8[16] = 0x0D; + private_key_pkcs8[17] = 0x01; + private_key_pkcs8[18] = 0x01; + private_key_pkcs8[19] = 0x01; + private_key_pkcs8[20] = 0x05; + private_key_pkcs8[21] = 0x00; + + // PrivateKey OCTET STRING + private_key_pkcs8[22] = 0x04; // octet string tag + private_key_pkcs8[23] = 0x82; // 8 --> 1000 0000 (1 in MSB means that it is long form) and 2 --> 0010 0000 (the next 2 + // bytes are the length of data) + private_key_pkcs8[24] = (unsigned char)((private_key_non_base64_len >> 8) & 0xFF); // length of data + private_key_pkcs8[25] = (unsigned char)(private_key_non_base64_len & 0xFF); // length of data + + memcpy(private_key_pkcs8 + 26, private_key_non_base64, private_key_non_base64_len); + + const size_t private_key_base64_pkcs8_size = atchops_base64_encoded_size(private_key_non_base64_len); + private_key_pkcs8_base64 = (char *)malloc(private_key_base64_pkcs8_size); + if (private_key_pkcs8_base64 == NULL) { + atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to allocate memory for private_key_pkcs8_base64\n"); + goto exit; + } + memset(private_key_pkcs8_base64, 0, sizeof(char) * private_key_base64_pkcs8_size); + + size_t private_key_base64_pkcs8_len = 0; + if ((ret = atchops_base64_encode(private_key_pkcs8, 26 + private_key_non_base64_len, private_key_pkcs8_base64, + private_key_base64_pkcs8_size, &private_key_base64_pkcs8_len)) != 0) { + atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to encode private key\n"); + goto exit; + } + + /* + * 7. Populate the atchops_rsa_key_public_key and atchops_rsa_key_private_key structs + */ + + if ((ret = atchops_rsa_key_populate_public_key(public_key, (const char *)public_key_base64, public_key_base64_len)) != + 0) { + atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to populate public key\n"); + goto exit; + } + + if ((ret = atchops_rsa_key_populate_private_key(private_key, (const char *)private_key_pkcs8_base64, + private_key_base64_pkcs8_len)) != 0) { + atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to populate private key\n"); + goto exit; + } + +exit: { + mbedtls_pk_free(&pk); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + free(private_key_non_base64); + free(private_key_pkcs8_base64); + free(private_key_pkcs8); + return ret; +} +} + int atchops_rsa_key_populate_public_key(atchops_rsa_key_public_key *public_key, const char *public_key_base64, const size_t public_key_base64_len) { int ret = 1; @@ -207,7 +432,7 @@ int atchops_rsa_key_populate_public_key(atchops_rsa_key_public_key *public_key, */ mbedtls_asn1_sequence *seq = NULL; // free later - const size_t dst_size = BASE64_DECODED_KEY_BUFFER_SIZE; + const size_t dst_size = 2048; // sufficient size for a 2048 bit RSA key unsigned char dst[dst_size]; memset(dst, 0, sizeof(unsigned char) * dst_size); size_t dst_len = 0; @@ -305,7 +530,7 @@ int atchops_rsa_key_populate_private_key(atchops_rsa_key_private_key *private_ke */ mbedtls_asn1_sequence *seq = NULL; // free later - const size_t dst_size = BASE64_DECODED_KEY_BUFFER_SIZE; + const size_t dst_size = 4096; // sufficient size for a 2048 bit RSA private key unsigned char dst[dst_size]; memset(dst, 0, sizeof(unsigned char) * dst_size); size_t dst_len = 0; @@ -395,7 +620,8 @@ exit: { } bool atchops_rsa_key_is_public_key_populated(const atchops_rsa_key_public_key *public_key) { - return atchops_rsa_key_public_key_is_n_initialized(public_key) && atchops_rsa_key_public_key_is_e_initialized(public_key); + return atchops_rsa_key_public_key_is_n_initialized(public_key) && + atchops_rsa_key_public_key_is_e_initialized(public_key); } bool atchops_rsa_key_is_private_key_populated(const atchops_rsa_key_private_key *private_key) { @@ -1058,7 +1284,8 @@ bool atchops_rsa_key_private_key_is_q_initialized(const atchops_rsa_key_private_ return private_key->q._is_value_initialized; } -void atchops_rsa_key_private_key_set_q_initialized(atchops_rsa_key_private_key *private_key, const bool is_initialized) { +void atchops_rsa_key_private_key_set_q_initialized(atchops_rsa_key_private_key *private_key, + const bool is_initialized) { /* * 1. Validate arguments */ @@ -1074,7 +1301,7 @@ void atchops_rsa_key_private_key_set_q_initialized(atchops_rsa_key_private_key * } int atchops_rsa_key_private_key_set_q(atchops_rsa_key_private_key *private_key, const unsigned char *q, - const size_t q_len) { + const size_t q_len) { int ret = 1; /* diff --git a/packages/atchops/tests/test_rsa_generate.c b/packages/atchops/tests/test_rsa_generate.c new file mode 100644 index 00000000..621a2cdb --- /dev/null +++ b/packages/atchops/tests/test_rsa_generate.c @@ -0,0 +1,123 @@ + +#include +#include +#include + +#define PLAINTEXT "Hello, World!" + +int main() { + + int ret = 1; + + atlogger_set_logging_level(ATLOGGER_LOGGING_LEVEL_DEBUG); + + atchops_rsa_key_public_key public_key; + atchops_rsa_key_public_key_init(&public_key); + + atchops_rsa_key_private_key private_key; + atchops_rsa_key_private_key_init(&private_key); + + const size_t ciphertext_size = 256; + unsigned char ciphertext[ciphertext_size]; + memset(ciphertext, 0, sizeof(unsigned char) * ciphertext_size); + + const size_t plaintext_size = 256; + unsigned char plaintext[plaintext_size]; + memset(plaintext, 0, sizeof(unsigned char) * plaintext_size); + + if ((ret = atchops_rsa_key_generate(&public_key, &private_key)) != 0) { + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to generate RSA key pair\n"); + goto exit; + } + + // log the public key + if (atchops_rsa_key_is_public_key_populated(&public_key)) { + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_INFO, "Public Key:\n"); + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_INFO, "N: "); + for (size_t i = 0; i < public_key.n.len; i++) { + printf("%02x ", public_key.n.value[i]); + } + printf("\n"); + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_INFO, "E: "); + for (size_t i = 0; i < public_key.e.len; i++) { + printf("%02x ", public_key.e.value[i]); + } + printf("\n"); + } else { + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_ERROR, "Public key is not populated\n"); + goto exit; + } + + // log the private key + if (atchops_rsa_key_is_private_key_populated(&private_key)) { + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_INFO, "Private Key:\n"); + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_INFO, "N: "); + for (size_t i = 0; i < private_key.n.len; i++) { + printf("%02x ", private_key.n.value[i]); + } + printf("\n"); + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_INFO, "E: "); + for (size_t i = 0; i < private_key.e.len; i++) { + printf("%02x ", private_key.e.value[i]); + } + printf("\n"); + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_INFO, "D: "); + for (size_t i = 0; i < private_key.d.len; i++) { + printf("%02x ", private_key.d.value[i]); + } + printf("\n"); + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_INFO, "P: "); + for (size_t i = 0; i < private_key.p.len; i++) { + printf("%02x ", private_key.p.value[i]); + } + printf("\n"); + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_INFO, "Q: "); + for (size_t i = 0; i < private_key.q.len; i++) { + printf("%02x ", private_key.q.value[i]); + } + printf("\n"); + } else { + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_ERROR, "Private key is not populated\n"); + goto exit; + } + + // use the public key to encrypt something + // use the private key to decrypt it + + if((ret = atchops_rsa_encrypt(&public_key, (const unsigned char *)PLAINTEXT, strlen(PLAINTEXT), ciphertext)) != 0) { + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to encrypt plaintext\n"); + goto exit; + } + + // log the ciphertext + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_INFO, "Ciphertext: "); + for (size_t i = 0; i < ciphertext_size; i++) { + printf("%02x ", ciphertext[i]); + } + + size_t plaintext_len = 0; + if((ret = atchops_rsa_decrypt(&private_key, ciphertext, ciphertext_size, plaintext, plaintext_size, &plaintext_len)) != 0) { + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to decrypt ciphertext\n"); + goto exit; + } + + // log the plaintext + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_INFO, "Plaintext: "); + for (size_t i = 0; i < plaintext_len; i++) { + printf("%c", plaintext[i]); + } + printf("\n"); + + // check if plaintext is equal to PLAINTEXT + if (strncmp((const char *)plaintext, PLAINTEXT, strlen(PLAINTEXT)) != 0) { + atlogger_log("test_rsa_generate", ATLOGGER_LOGGING_LEVEL_ERROR, "Plaintext does not match original\n"); + goto exit; + } + + +exit: { + atchops_rsa_key_public_key_free(&public_key); + atchops_rsa_key_private_key_free(&private_key); + return ret; +} +} \ No newline at end of file diff --git a/packages/atchops/tests/test_rsadecrypt.c b/packages/atchops/tests/test_rsadecrypt.c index ba95b16d..66c983e9 100644 --- a/packages/atchops/tests/test_rsadecrypt.c +++ b/packages/atchops/tests/test_rsadecrypt.c @@ -1,9 +1,14 @@ #include "atchops/rsa.h" +#include #include #include #include -#include +// a pkcs8 formatted key in base64 from C SDK generation +// #define PRIVATEKEYBASE64 +// "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzn72C2fNOzP3Uwy3gkSQiYPQalzMIJnyM51amjYzsaP20CNo5y2NQV6Nx1bwcpn1MBoPx4AK26hD7d9ijjOS2lU5glPiSf0ZA68e24zi7NsyRgvD1jhYH2H8coNc7eRlukfy/7BbJsf2H33CBcjLPXEdp46kdABqP6iudbXzG33HQKGnfjaaQWWHePdNU3T1btTQJ8Mv+sH+caJ6DdRu95ZdKuoiVip7qHCZ2jlNHn46BJjSL9r2MiYF2i4G/pkdmSVvC15xnp/x13f+GDKIMAerj62I0UyGasTJQlfEn1wYBNlghKlIyyMSsFpv9Ugi/R06gK3GGTaeL7kZmNQ8JAgMBAAECggEAESCVKGnxyjy/o07tC/Gq+WA3RmXOZuOMkr7oQz9SBaTJNCZ38HTVRm7k1dDke/LgFaS1ZhXPDHPrJJ871/RyRnqcG5d40Dc0krIou+aUnT1PajyLD076CMt661bmzvPwGdvvtrkjPx4qp48FokIqWB1bbdxYXryIy9ovSHaNJEU3IYpuUA0BW3798rshwQK1UlrK0BdStfXPpmN7sCdbymb4atJynFqoZph0BobC4hXgXaxSeNhY5pIGfuQd97etFq9v3sFcn6ZjwDJzRormff4E7TbRHQ9Yl2b0tb1kz2cpUFqAr7ap32Re6LZ8TD32GVTRYVriFAn6v2OmwuXU5QKBgQDdgLiBEE07RUqwLPNR8CmnIiJxopxMld7lJFWcwNOE4fxsOZzLnz2Xwl21f/Xyo33RxAMNuW9PvqIoTfVRT0AfnDINp4GU7GlvFdtWWQ7kJLAAqklzEyU/57g9s3m34fpzIOOTxABucUGgfonfm2EdJ07FdEUoGIUaNvONAVJhiwKBgQDPmVFat8PIOcvRiO+KMgHHQmBdGR6NiAOOvpJ93OOMN6+JInNXKxiE1Iv8agw20hCtOx9LewgoACw12UqSHC+4BJHasjTUrrKiklmdDMjFSC9XrZ6PuTpugu/wM6h4fhwf3K9PEVx1mDlAZoSfwhQ4MGkqKbewqvGw9S7oz5Q8OwKBgQCmcFuzd2lhGR8XJJ+tOTZDRQ32r0ac8ZysN9Iw2F/YIOtI8z2Tb9ObXkyF3mIT8a/QWGYnAOjYVhmJCZNFhrRbTEX8JprjKYXMF/NZfdAHtF2gElTgqEk8LMUvb9YNSzujGNqIpSXh1y6GB69YG2wsuOWiz0xL5ajWWuZFVPHvIwKBgDrbuEIlOeAJ6uyki22+Ed0Bx7p9hbkQ6BlPlM8UkntNynnyB4ueT1xRusK8+muMkWfcDFplLoHQ0rgNvGPClBDzUrsTrYDjawhGwBuT5VRxy+Jq+jq7hIKSox6SNuC6uJScCCQ9wt4gY5MLvexhpUPtDdQDce4n+VB3o24kdF3DAoGAc4q30FsexTKZNMUekkDm3ZYdGCYoRDF5+A2JOSTqlSKubb1dfSxGPvBe55dSfO1G0yR7Z8rZcG0+6gdv6tqi+ndRVyVApGuetMK7jhiuyzYEv9dJWdvVBg5T7+ElaKUxzAEapEaLvVplg8XBjq3c1BwFFj08T+6LXd3gy1eu92g=" + +// a pkcs8 formatted key in base64 from Dart SDK generation #define PRIVATEKEYBASE64 \ "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCDc/" \ "uZ5+pmDYY1A+IQdiKeZNhRxttbYCv1aLksIP+5Fk1GJAnKlsBBum+" \ @@ -69,7 +74,5 @@ int main() { goto ret; -ret: { - return ret; -} +ret: { return ret; } }