Генерация pem с openssl в C


Я работаю над библиотекой ключей util, и, к сожалению, у меня возникли небольшие трудности с надежным созданием pem. Я успешно создаю pem, возможно, в 98% случаев, но время от времени я получаю плохой pem. Есть идеи, что происходит?

Я компилирую с gcc key_utils.c tests.c -o key_tests -lcrypto -lssl -Wall

Заголовки:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <openssl/ec.h>
#include <openssl/bn.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
#include <openssl/ecdsa.h>
#include <openssl/pem.h>

.

int generatePem(char **pem) {

    char *pemholder = calloc(224, sizeof(char));
    EC_KEY *eckey = NULL;

    BIO *out = BIO_new(BIO_s_mem());
    BUF_MEM *buf = NULL;
    EC_GROUP *group = NULL;

    group = EC_GROUP_new_by_curve_name(NID_secp256k1);
    buf = BUF_MEM_new();
    eckey = EC_KEY_new();

    createNewKey(group, eckey);

    EC_GROUP_clear_free(group);

    PEM_write_bio_ECPrivateKey(out, eckey, NULL, NULL, 0, NULL, NULL);

    BIO_get_mem_ptr(out, &buf);

    memcpy(pemholder, buf->data, 223);

    if ( buf->data[219] == 'n') {
        pemholder[220] = '';       
        memcpy(*pem, pemholder, 221);
    } else if ( buf->data[221] == 'n') {
        pemholder[222] = '';       
        memcpy(*pem, pemholder, 223);
    } else {
        pemholder[223] = '';
        memcpy(*pem, pemholder, 224);
    }

    free(pemholder);
    EC_KEY_free(eckey);
    BIO_free_all(out);

    return NOERROR;
};

Плохой pem выглядит так:

-----BEGIN EC PRIVATE KEY-----
MHMCAQEEH8kO/hjEyM2hvQk//LSsp1xRBIYNDRjAi4b8N78odyCgBwYFK4EEAAqh
RANCAAQ43017I40ci8YMLJnguD/DHUjohY4blKoJ4lXYbgYqyjWvJfVnsNPMU8H9
o3IdPwAitnJjCOG11n9DIQoS3S/o
-----END EC PRIVATE KEY-----
6T
1 2

1 ответ:

Оказывается, я тупой, и 220 байт-это допустимый PEM.

Вот рабочий код, на случай, если кто-то еще захочет увидеть его в будущем.

int generatePem(char **pem) {
    int returnError = NOERROR;
    char * errorMessage = "";
    char *pemholder = calloc(240, sizeof(char));
    EC_KEY *eckey = NULL;
    BIO *out = NULL;

    if ((out = BIO_new(BIO_s_mem())) == NULL) {
        returnError = ERROR;
        errorMessage = "Error in BIO_new(BIO_s_mem())";
        goto clearVariables;
    }

    BUF_MEM *buf = NULL;
    EC_GROUP *group = NULL;

    if ((group = EC_GROUP_new_by_curve_name(NID_secp256k1)) == NULL) {
        returnError = ERROR;
        errorMessage = "Error in EC_GROUP_new_by_curve_name(NID_secp256k1))";
        goto clearVariables;
    }

    if (((eckey = EC_KEY_new()) == NULL) ||
        ((buf = BUF_MEM_new()) == NULL)) {
        returnError = ERROR;
        errorMessage = "Error in EC_KEY_new())";
        goto clearVariables;
    };

    if (createNewKey(group, eckey) == ERROR) {
        returnError = ERROR;
        errorMessage = "createNewKey(group, eckey)";
        goto clearVariables;
    }

    if (PEM_write_bio_ECPrivateKey(out, eckey, NULL, NULL, 0, NULL, NULL) == 0) {
        printf("PEM_write_bio_ECPrivateKey error");
    }

    BIO_get_mem_ptr(out, &buf);

    memcpy(pemholder, buf->data, 224);
    if (buf->data[218] == '\n') {
        pemholder[219] = '\0';
        memcpy(*pem, pemholder, 220);
    } else if ( buf->data[219] == '\n') {
        pemholder[220] = '\0';       
        memcpy(*pem, pemholder, 221);
    } else if ( buf->data[221] == '\n') {
        pemholder[222] = '\0';       
        memcpy(*pem, pemholder, 223);
    } else if (buf->data[222] == '\n') {
        pemholder[223] = '\0';
        memcpy(*pem, pemholder, 224);
    } else {
        returnError = ERROR;
        errorMessage = "invalid PEM generated";
        goto clearVariables;
    }

    goto clearVariables;

clearVariables:
    if (group != NULL)
        EC_GROUP_clear_free(group);
    if (pemholder != NULL) 
        free(pemholder);
    if (eckey != NULL)
        EC_KEY_free(eckey);
    if (out != NULL)
        BIO_free_all(out);
    if (errorMessage[0] != '\0')
        printf("Error: %s\n", errorMessage);

    return returnError;
};

static int createNewKey(EC_GROUP *group, EC_KEY *eckey) {

    int asn1Flag = OPENSSL_EC_NAMED_CURVE;
    int form = POINT_CONVERSION_UNCOMPRESSED;

    EC_GROUP_set_asn1_flag(group, asn1Flag);
    EC_GROUP_set_point_conversion_form(group, form);
    int setGroupError = EC_KEY_set_group(eckey, group);

    int resultFromKeyGen = EC_KEY_generate_key(eckey);

    if (resultFromKeyGen != 1 || setGroupError != 1){
        return ERROR;
    }

    return NOERROR;
}