使用可分辨名称字段创建自签名证书

时间:2013-09-20 08:29:51

标签: c ssl openssl self-signed csr

我正在尝试编写一个应用程序,该应用程序将使用提供的专有名称创建自签名证书。

我有以下应用程序,它创建.key和.csr文件。

#include <stdio.h>
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>

#define _RAND_FILENAME  "/dev/random"
#define _RAND_LOADSIZE  128
#define _RSA_KEYSIZE    1024


int build_and_save_csr(int dn_entries, char *dn_fields[], char *dn_values[], FILE *req_f, FILE *priv_f)
{
    X509_REQ    *req_p;
    EVP_PKEY    *key_p;
    RSA     *rsa_p;
    X509_NAME   *name_p = NULL;
    int     priv_len;
    unsigned char   *priv_p;
    int     i;

    if (!(req_p = X509_REQ_new())) {
        fprintf(stderr, "X509_REQ_new() failed\n");
        return -1;
    }

    if (!(key_p = EVP_PKEY_new())) {
        X509_REQ_free(req_p);
        fprintf(stderr, "EVP_PKEY_new() failed\n");
        return -1;
    }

#if 0
    if (RAND_load_file(_RAND_FILENAME, _RAND_LOADSIZE) != _RAND_LOADSIZE) {
        X509_REQ_free(req_p);
        EVP_PKEY_free(key_p);
        fprintf(stderr, "RAND_load_file() failed\n");
        return -1;
    }
#endif

    if (!(rsa_p = RSA_generate_key(_RSA_KEYSIZE, RSA_F4, NULL, NULL))) {
        X509_REQ_free(req_p);
        EVP_PKEY_free(key_p);
        fprintf(stderr, "RSA key generatione failed\n");
        return -1;
    }

    if (!EVP_PKEY_assign_RSA(key_p, rsa_p)) {
        X509_REQ_free(req_p);
        RSA_free(rsa_p);
        EVP_PKEY_free(key_p);
        return -1;
    }
    /*!!! the memory for rsa_p is now managed by key_p - don't free! */


    if (!X509_REQ_set_version(req_p, 0L)        /* Version 1 */
     || !X509_REQ_set_pubkey(req_p, key_p)) {
        X509_REQ_free(req_p);
        EVP_PKEY_free(key_p);
        fprintf(stderr, "Failed to set stuff on X509_REQ\n");
        return -1;
    }

    if (!(name_p  = X509_REQ_get_subject_name(req_p))) {
        X509_REQ_free(req_p);
        EVP_PKEY_free(key_p);
        fprintf(stderr, "Failed to make get X509_REQ_get_subject_name\n");
        return -1;
    }

    /* Build the DN */
    for (i = 0; i < dn_entries; i++) {
        if (!X509_NAME_add_entry_by_txt(name_p, dn_fields[i], MBSTRING_ASC,
                dn_values[i], -1, -1, 0)) {
            X509_REQ_free(req_p);
            EVP_PKEY_free(key_p);
            fprintf(stderr, "Failed to make the X509_NAME\n");
            return -1;
        }
    }

    if (!X509_REQ_sign(req_p, key_p, EVP_sha1())) {
        X509_REQ_free(req_p);
        EVP_PKEY_free(key_p);
        fprintf(stderr, "X509_REQ_sign() failed\n");
        return -1;
    }

    /* save the private key to file (PKCS#1) */
    priv_p = NULL;
    priv_len = i2d_RSAPrivateKey(rsa_p, &priv_p);
    fwrite(priv_p, priv_len, 1, priv_f);
    OPENSSL_free(priv_p);

    EVP_PKEY_free(key_p);   /* nolonger need the EVP structure */

    /* save the CSR to file (PKCS#10) */
    i2d_X509_REQ_fp(req_f, req_p);
    X509_REQ_free(req_p);

    return 0;
}

int main(int argc, char *argv[])
{
    char    *dn_fields[] = { "O", "CN" };
    char    *dn_values[] = { "My Application", "tomcelic@selleck.com" };
    FILE    *req_f, *priv_f;

    req_f = fopen("selleck.csr", "w");
    priv_f = fopen("selleck.key", "w");

    if (build_and_save_csr(2, dn_fields, dn_values, req_f, priv_f) != 0) {
        fprintf(stderr, "Oh bother...\n");
        fclose(req_f);
        fclose(priv_f);
        exit(1);
    }

    fclose(req_f);
    fclose(priv_f);
    return 0;
}

我认为这行可以换成一个创建自签名证书而不是签名请求的行吗?

/* save the CSR to file (PKCS#10) */
i2d_X509_REQ_fp(req_f, req_p);

这对我来说都是全新的,所以我很感激任何建议!

1 个答案:

答案 0 :(得分:2)

  

我认为这行可以换成一个创建自签名证书而不是签名请求的行吗?

不,我很抱歉没那么容易。

X509_REQ不是创建自签名证书的正确结构。它仅用于CSR(证书签名请求)管理,因此主要结构和功能(带有_REQ后缀)对您的pourpose无效。

但是,自签名证书创建的过程非常接近这个(在X509_REQ_sign调用中你可以注意到它自己签署的CSR。)。

Here您可以找到整个过程的完整而详尽的答案,并here一个自签名创作的示例。

作为解释i2d_X509_REQ_fp,它用于将X509 CSR保存为PKCS#10格式Info