Mbedtls how to generate a Certificate Request (CSR)

mbedtls how to generate a Certificate Request (CSR)
The link of suggestion how to use mbedtls x509/cert_req to generate a Certificate Request:
https://tls.mbed.org/kb/how-to/generate-a-certificate-request-csr

The source code base the newest mbedtls:
mbedtls/programs/x509/cert_req.c

This tutorial describes how to generate your own certificate request for use in an online SSL certificate request.
Mbed TLS includes the core and applications for generating keys and certificate requests without relying on other
libraries and applications, offering users a command-line alternative to OpenSSL for generating their keys and certificate requests.
This article assumes you have compiled and installed the Mbed TLS library and example programs on your system.
Certificate Request for use with SSL vendors
Whenever you request a certificate from one of the SSL vendors, you are asked to enter a CSR. CSR is short for Certificate Signing Request and is often in the PEM format.
To generate a certificate request, you need a private-public key pair. The public key is put in the certificate request
in addition to some identifying information (such as website domain, address, and country).
By submitting your request, you ask the SSL vendor to sign that request with their CA key and generate a full certificate from it.
The CA will determine the validity of the certificate they generate based on how much you paid them.
Generating a RSA key file
The first step for generating a certificate request, is to generate a private-public key pair for the certificate.
For generating key files, Mbed TLS includes the gen_key application in programs/pkey.
This key generation application accepts the following arguments:
usage: gen_key param=<>…

acceptable parameters:
type=rsa default: rsa
rsa_keysize=%d default: 4096
filename=%s default: keyfile.key
format=pem|der default: pem
The following command generates a 2048 bit RSA key file, as explained here:
programs/pkey/gen_key type=rsa rsa_keysize=2048 filename=example.com.key
Generating certificate request
For generating and writing certificate files, Mbed TLS includes the cert_req application in programs/x509.
Before generating the certificate request you need to determine the different values that need to go in it.
Key to use in the certificate
First and foremost a certificate binds a public-private key pair to an identity. To indicate which key to use in the certificate request you use the filename argument, like so filename=example.com.key.
Subject name
Each certificate request needs a subject name (the identity that is being signed). Each CA vendor has different requirements for which items are required in a certificate request.
If you want to request a certificate for the example.com domain name from the organization Example Ltd in the country UK, you should use subject_name=CN=example.com,O=Example\ Ltd,C=UK on the command-line.
Note: If you want to use a space in one of the names you have to either nullify it (issuer_name=CN=my\ server) or contain the entire argument in quotation marks (“issuer_name=CN=my server”).
Note: Commas inside names need to be nullified with a backslash as well. You need to protect the backslash from your shell, for example, issuer_name=CN=my\,server or issuer_name=‘CN=my,server’.
The available items you can put in a subject_name (that you support) are:
C = Country
CN = Common Name
L = Locality
O = Organization
OU = Organizational Unit
R = e-mail address
ST = State
serialNumber
postalAddress
postalCode
Command to generate a certificate request
So the full command for generating a certificate request for example.com.key with the name CN=example.com,O=Example Ltd,C=UK would be:
programs/x509/cert_req filename=example.com.key
subject_name=CN=example.com,O=Example\ Ltd,C=UK
output_file=example.com.req
The file example.com.req now contains your PEM-encoded certificate request. It will look something like:
-----BEGIN CERTIFICATE REQUEST-----
MIICgTCCAWkCAQAwPDEVMBMGA1UEAxMMcG9sYXJzc2wub3JnMRYwFAYDVQQKEw1P
ZmZzcGFyayBCLlYuMQswCQYDVQQGEwJOTDCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAJ8NFeCvO7F1DJhkZEUZpt8x9x7BBxW9odeORDcNFSifNyh1ywRi
HMMWbR6JwQDiCqBMLZ9kOktv3VXpTSAD15vwYGPQHnD9Cs3kHc7DDaj27KerSFgH
oYE4/MxAadeXGIYMjmFqCbJ6Y+3CDxWn5V9TkFkXOJHZb3EKjOEPq5Zjrvdr1vPC
/C1+GUFAkIIo2y044uZTH3oFcSXx0xCK5yjZEfa+x1PzYaugAInVcj+43VLTOJWP
4RaHgUnNwE/D1HgX8DKKRvDE2uJY6sU+EXd2J9GhijqarvCcVNfYWzX+bsicjl4k
K4u7TVWN95c4KtJ+spq+YPP+PkUyTqvrkgECAwEAAaAAMA0GCSqGSIb3DQEBBQUA
A4IBAQAOmMR3z53yz7haJbpl2GNTwDBs8UKzGexJ+OBC+Jww2NEbXeN0HSQdQhMD
R7GJVO7CslWELcwn9TDCZjNDTSL95YNputzA0yhfu3/9HTeWGwR1X3oH+FjVCPD2
JkUn1A/l4FnCgxraC2YoaKxnpGj3qe2dq4y9j/rB5yrOjyqfvHhSmm83ktWHqsa/
TuOXC/24Dsc4iHapiWo+F5WO2jWOj+HE22y7i9O/dcth6Gv37tUFhqB8X++TfNkj
62O45O/iBEGNebBD/r90a+Z+FOa5k3FgJ34hTqts3UhD8UPgQ0q8x8aSbGOjykrD
+F2IMb01ggOxT9qOBlRLHRhVDkqV
-----END CERTIFICATE REQUEST-----
You can copy and paste the PEM content into the website for the certificate vendor.

#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif

#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_printf          printf
#define mbedtls_exit            exit
#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
#endif /* MBEDTLS_PLATFORM_C */

#if !defined(MBEDTLS_X509_CSR_WRITE_C) || !defined(MBEDTLS_FS_IO) ||  \
    !defined(MBEDTLS_PK_PARSE_C) || !defined(MBEDTLS_SHA256_C) || \
    !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \
    !defined(MBEDTLS_PEM_WRITE_C)
int main( void )
{
    mbedtls_printf( "MBEDTLS_X509_CSR_WRITE_C and/or MBEDTLS_FS_IO and/or "
            "MBEDTLS_PK_PARSE_C and/or MBEDTLS_SHA256_C and/or "
            "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C "
            "not defined.\n");
    return( 0 );
}
#else

#include "mbedtls/x509_csr.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DFL_FILENAME            "keyfile.key"
#define DFL_PASSWORD            NULL
#define DFL_DEBUG_LEVEL         0
#define DFL_OUTPUT_FILENAME     "cert.req"
#define DFL_SUBJECT_NAME        "CN=Cert,O=mbed TLS,C=UK"
#define DFL_KEY_USAGE           0
#define DFL_FORCE_KEY_USAGE     0
#define DFL_NS_CERT_TYPE        0
#define DFL_FORCE_NS_CERT_TYPE  0
#define DFL_MD_ALG              MBEDTLS_MD_SHA256

#define USAGE \
    "\n usage: cert_req param=<>...\n"                  \
    "\n acceptable parameters:\n"                       \
    "    filename=%%s         default: keyfile.key\n"   \
    "    password=%%s         default: NULL\n"          \
    "    debug_level=%%d      default: 0 (disabled)\n"  \
    "    output_file=%%s      default: cert.req\n"      \
    "    subject_name=%%s     default: CN=Cert,O=mbed TLS,C=UK\n"   \
    "    key_usage=%%s        default: (empty)\n"       \
    "                        Comma-separated-list of values:\n"     \
    "                          digital_signature\n"     \
    "                          non_repudiation\n"       \
    "                          key_encipherment\n"      \
    "                          data_encipherment\n"     \
    "                          key_agreement\n"         \
    "                          key_cert_sign\n"  \
    "                          crl_sign\n"              \
    "    force_key_usage=0/1  default: off\n"           \
    "                          Add KeyUsage even if it is empty\n"  \
    "    ns_cert_type=%%s     default: (empty)\n"       \
    "                        Comma-separated-list of values:\n"     \
    "                          ssl_client\n"            \
    "                          ssl_server\n"            \
    "                          email\n"                 \
    "                          object_signing\n"        \
    "                          ssl_ca\n"                \
    "                          email_ca\n"              \
    "                          object_signing_ca\n"     \
    "    force_ns_cert_type=0/1 default: off\n"         \
    "                          Add NsCertType even if it is empty\n"    \
    "    md=%%s               default: SHA256\n"       \
    "                          possible values:\n"     \
    "                          MD2, MD4, MD5, SHA1\n"  \
    "                          SHA224, SHA256\n"       \
    "                          SHA384, SHA512\n"       \
    "\n"


/*
 * global options
 */
struct options
{
    const char *filename;       /* filename of the key file             */
    const char *password;       /* password for the key file            */
    int debug_level;            /* level of debugging                   */
    const char *output_file;    /* where to store the constructed key file  */
    const char *subject_name;   /* subject name for certificate request */
    unsigned char key_usage;    /* key usage flags                      */
    int force_key_usage;        /* Force adding the KeyUsage extension  */
    unsigned char ns_cert_type; /* NS cert type                         */
    int force_ns_cert_type;     /* Force adding NsCertType extension    */
    mbedtls_md_type_t md_alg;   /* Hash algorithm used for signature.   */
} opt;

int write_certificate_request( mbedtls_x509write_csr *req, const char *output_file,
                               int (*f_rng)(void *, unsigned char *, size_t),
                               void *p_rng )
{
    int ret;
    FILE *f;
    unsigned char output_buf[4096];
    size_t len = 0;

    memset( output_buf, 0, 4096 );
    /*If you don't want to save the csr to file, you can just save them into output_buf and take this buf out. The output_buf is he context of the CSR */
    if( ( ret = mbedtls_x509write_csr_pem( req, output_buf, 4096, f_rng, p_rng ) ) < 0 )
    {
        len = strlen( (char *) output_buf );
        mbedtls_printf("#whw_dbg#func:%s line:%d\noutput_buf:%s\nlen:%d\n", __func__, __LINE__, output_buf, len);
        return( ret );
    }

    len = strlen( (char *) output_buf );

    mbedtls_printf("#whw_dbg#func:%s line:%d\noutput_buf:%s\nlen:%d\n", __func__, __LINE__, output_buf, len);
    if( ( f = fopen( output_file, "w" ) ) == NULL )
        return( -1 );

    if( fwrite( output_buf, 1, len, f ) != len )
    {
        fclose( f );
        return( -1 );
    }

    fclose( f );

    return( 0 );
}

int main( int argc, char *argv[] )
{
    int ret = 1;
    int exit_code = MBEDTLS_EXIT_FAILURE;
    mbedtls_pk_context key;
    char buf[1024];
    int i;
    char *p, *q, *r;
    mbedtls_x509write_csr req;
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    const char *pers = "csr example app";

    /*
     * Set to sane values
     */
    mbedtls_x509write_csr_init( &req );
    mbedtls_pk_init( &key );
    mbedtls_ctr_drbg_init( &ctr_drbg );
    memset( buf, 0, sizeof( buf ) );

    if( argc == 0 )
    {
    usage:
        mbedtls_printf( USAGE );
        goto exit;
    }

    opt.filename            = DFL_FILENAME;
    opt.password            = DFL_PASSWORD;
    opt.debug_level         = DFL_DEBUG_LEVEL;
    opt.output_file         = DFL_OUTPUT_FILENAME;
    opt.subject_name        = DFL_SUBJECT_NAME;
    opt.key_usage           = DFL_KEY_USAGE;
    opt.force_key_usage     = DFL_FORCE_KEY_USAGE;
    opt.ns_cert_type        = DFL_NS_CERT_TYPE;
    opt.force_ns_cert_type  = DFL_FORCE_NS_CERT_TYPE;
    opt.md_alg              = DFL_MD_ALG;


    for( i = 1; i < argc; i++ )
    {

        p = argv[i];
        if( ( q = strchr( p, '=' ) ) == NULL )
            goto usage;
        *q++ = '\0';

        if( strcmp( p, "filename" ) == 0 )
            opt.filename = q;
        else if( strcmp( p, "password" ) == 0 )
            opt.password = q;
        else if( strcmp( p, "output_file" ) == 0 )
            opt.output_file = q;
        else if( strcmp( p, "debug_level" ) == 0 )
        {
            opt.debug_level = atoi( q );
            if( opt.debug_level < 0 || opt.debug_level > 65535 )
                goto usage;
        }
        else if( strcmp( p, "subject_name" ) == 0 )
        {
            mbedtls_printf("\n#whw_dbg#func:%s line:%d \np:%s \nq:%s\n", __func__, __LINE__, p, q);
            opt.subject_name = q;
        }
        else if( strcmp( p, "md" ) == 0 )
        {
            if( strcmp( q, "SHA256" ) == 0 )
            {
                opt.md_alg = MBEDTLS_MD_SHA256;
            }
            else if( strcmp( q, "SHA224" ) == 0 )
            {
                opt.md_alg = MBEDTLS_MD_SHA224;
            }
            else
#if defined(MBEDTLS_MD5_C)
            if( strcmp( q, "MD5" ) == 0 )
            {
                opt.md_alg = MBEDTLS_MD_MD5;
            }
            else
#endif /* MBEDTLS_MD5_C */
#if defined(MBEDTLS_MD4_C)
            if( strcmp( q, "MD4" ) == 0 )
            {
                opt.md_alg = MBEDTLS_MD_MD4;
            }
            else
#endif /* MBEDTLS_MD5_C */
#if defined(MBEDTLS_MD2_C)
            if( strcmp( q, "MD2" ) == 0 )
            {
                opt.md_alg = MBEDTLS_MD_MD2;
            }
            else
#endif /* MBEDTLS_MD2_C */
#if defined(MBEDTLS_SHA1_C)
            if( strcmp( q, "SHA1" ) == 0 )
            {
                opt.md_alg = MBEDTLS_MD_SHA1;
            }
            else
#endif /* MBEDTLS_SHA1_C */
#if defined(MBEDTLS_SHA512_C)
            if( strcmp( q, "SHA384" ) == 0 )
            {
                opt.md_alg = MBEDTLS_MD_SHA384;
            }
            else
            if( strcmp( q, "SHA512" ) == 0 )
            {
                opt.md_alg = MBEDTLS_MD_SHA512;
            }
            else
#endif /* MBEDTLS_SHA512_C */
            {
                goto usage;
            }
        }
        else if( strcmp( p, "key_usage" ) == 0 )
        {
            while( q != NULL )
            {
                if( ( r = strchr( q, ',' ) ) != NULL )
                    *r++ = '\0';

                if( strcmp( q, "digital_signature" ) == 0 )
                    opt.key_usage |= MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
                else if( strcmp( q, "non_repudiation" ) == 0 )
                    opt.key_usage |= MBEDTLS_X509_KU_NON_REPUDIATION;
                else if( strcmp( q, "key_encipherment" ) == 0 )
                    opt.key_usage |= MBEDTLS_X509_KU_KEY_ENCIPHERMENT;
                else if( strcmp( q, "data_encipherment" ) == 0 )
                    opt.key_usage |= MBEDTLS_X509_KU_DATA_ENCIPHERMENT;
                else if( strcmp( q, "key_agreement" ) == 0 )
                    opt.key_usage |= MBEDTLS_X509_KU_KEY_AGREEMENT;
                else if( strcmp( q, "key_cert_sign" ) == 0 )
                    opt.key_usage |= MBEDTLS_X509_KU_KEY_CERT_SIGN;
                else if( strcmp( q, "crl_sign" ) == 0 )
                    opt.key_usage |= MBEDTLS_X509_KU_CRL_SIGN;
                else
                    goto usage;

                q = r;
            }
        }
        else if( strcmp( p, "force_key_usage" ) == 0 )
        {
            switch( atoi( q ) )
            {
                case 0: opt.force_key_usage = 0; break;
                case 1: opt.force_key_usage = 1; break;
                default: goto usage;
            }
        }
        else if( strcmp( p, "ns_cert_type" ) == 0 )
        {
            while( q != NULL )
            {
                if( ( r = strchr( q, ',' ) ) != NULL )
                    *r++ = '\0';

                if( strcmp( q, "ssl_client" ) == 0 )
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT;
                else if( strcmp( q, "ssl_server" ) == 0 )
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER;
                else if( strcmp( q, "email" ) == 0 )
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL;
                else if( strcmp( q, "object_signing" ) == 0 )
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING;
                else if( strcmp( q, "ssl_ca" ) == 0 )
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CA;
                else if( strcmp( q, "email_ca" ) == 0 )
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA;
                else if( strcmp( q, "object_signing_ca" ) == 0 )
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA;
                else
                    goto usage;

                q = r;
            }
        }
        else if( strcmp( p, "force_ns_cert_type" ) == 0 )
        {
            switch( atoi( q ) )
            {
                case 0: opt.force_ns_cert_type = 0; break;
                case 1: opt.force_ns_cert_type = 1; break;
                default: goto usage;
            }
        }
        else
            goto usage;
    }

    mbedtls_printf("#whw_whw_dbg#func:%s line:%d opt.md_alg:%d\n", __func__, __LINE__, opt.md_alg);
    mbedtls_x509write_csr_set_md_alg( &req, opt.md_alg );

    if( opt.key_usage || opt.force_key_usage == 1 )
        mbedtls_x509write_csr_set_key_usage( &req, opt.key_usage );

    if( opt.ns_cert_type || opt.force_ns_cert_type == 1 )
        mbedtls_x509write_csr_set_ns_cert_type( &req, opt.ns_cert_type );

    /*
     * 0. Seed the PRNG
     */
    mbedtls_printf( "  . Seeding the random number generator..." );
    fflush( stdout );

    mbedtls_entropy_init( &entropy );
    if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
    {
        mbedtls_printf( " failed\n  !  mbedtls_ctr_drbg_seed returned %d", ret );
        goto exit;
    }

    mbedtls_printf( " ok\n" );

    /*
     * 1.0. Check the subject name for validity
     */
    mbedtls_printf( "  . Checking subject name..." );
    fflush( stdout );

    if( ( ret = mbedtls_x509write_csr_set_subject_name( &req, opt.subject_name ) ) != 0 )
    {
        mbedtls_printf( " failed\n  !  mbedtls_x509write_csr_set_subject_name returned %d", ret );
        goto exit;
    }

    mbedtls_printf( " ok\n" );

    /*
     * 1.1. Load the key
     */
    mbedtls_printf( "  . Loading the private key ..." );
    fflush( stdout );

    ret = mbedtls_pk_parse_keyfile( &key, opt.filename, opt.password );

    if( ret != 0 )
    {
        mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile returned %d", ret );
        goto exit;
    }

    mbedtls_x509write_csr_set_key( &req, &key );

    mbedtls_printf( " ok\n" );

    /*
     * 1.2. Writing the request
     */
    mbedtls_printf( "  . Writing the certificate request ..." );
    fflush( stdout );

    if( ( ret = write_certificate_request( &req, opt.output_file,
                                           mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
    {
        mbedtls_printf( " failed\n  !  write_certifcate_request %d", ret );
        goto exit;
    }

    mbedtls_printf( " ok\n" );

    exit_code = MBEDTLS_EXIT_SUCCESS;

exit:

    if( exit_code != MBEDTLS_EXIT_SUCCESS )
    {
#ifdef MBEDTLS_ERROR_C
        mbedtls_strerror( ret, buf, sizeof( buf ) );
        mbedtls_printf( " - %s\n", buf );
#else
        mbedtls_printf("\n");
#endif
    }

    mbedtls_x509write_csr_free( &req );
    mbedtls_pk_free( &key );
    mbedtls_ctr_drbg_free( &ctr_drbg );
    mbedtls_entropy_free( &entropy );

#if defined(_WIN32)
    mbedtls_printf( "  + Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( exit_code );
}
#endif /* MBEDTLS_X509_CSR_WRITE_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
          MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_PEM_WRITE_C */
发布了223 篇原创文章 · 获赞 160 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/u014100559/article/details/104190140