Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you verify a public key was issued by your private CA?

Tags:

c++

openssl

I have created a CA cert, and used it to issue a public key. At a date in the future, I need to verify that the certificate loaded was issued by my CA.

How do I do that with the OpenSSL API (c++)?

like image 488
John Avatar asked Aug 05 '10 05:08

John


People also ask

Where is the public key on a certificate?

Public key is embedded in the SSL certificate and Private key is stored on the server and kept secret. When a site visitor fills out a form with personal information and submits it to the server, the information gets encrypted with the public key to protect if from eavesdropping.

How do I find the private key of a certificate?

In the Certificate windows that appears, you should see a note with a key symbol underneath the Valid from field that says, "You have a private key that corresponds to this certificate." If you do not see this, then your private key is not attached to this certificate, indicating a certificate installation issue.


2 Answers

I've reduced verify.c (in openssl/apps/) to the minimum functions required. Assumptions: cert and CA cert are both PEM format files. There are no CRLS or trusted list checks required.

Call verify() with the path to your cert and CA PEM files.

static int verify(const char* certfile, const char* CAfile);
static X509 *load_cert(const char *file);
static int check(X509_STORE *ctx, const char *file);

int verify(const char* certfile, const char* CAfile)
{
    int ret=0;
    X509_STORE *cert_ctx=NULL;
    X509_LOOKUP *lookup=NULL;

    cert_ctx=X509_STORE_new();
    if (cert_ctx == NULL) goto end;

    OpenSSL_add_all_algorithms();

    lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_file());
    if (lookup == NULL)
        goto end;

    if(!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM))
        goto end;

    lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_hash_dir());
    if (lookup == NULL)
        goto end;

    X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);

    ret = check(cert_ctx, certfile);
end:
    if (cert_ctx != NULL) X509_STORE_free(cert_ctx);

    return ret;
}

static X509 *load_cert(const char *file)
{
    X509 *x=NULL;
    BIO *cert;

    if ((cert=BIO_new(BIO_s_file())) == NULL)
        goto end;

    if (BIO_read_filename(cert,file) <= 0)
        goto end;

    x=PEM_read_bio_X509_AUX(cert,NULL, NULL, NULL);
end:
    if (cert != NULL) BIO_free(cert);
    return(x);
}

static int check(X509_STORE *ctx, const char *file)
{
    X509 *x=NULL;
    int i=0,ret=0;
    X509_STORE_CTX *csc;

    x = load_cert(file);
    if (x == NULL)
        goto end;

    csc = X509_STORE_CTX_new();
    if (csc == NULL)
        goto end;
    X509_STORE_set_flags(ctx, 0);
    if(!X509_STORE_CTX_init(csc,ctx,x,0))
        goto end;
    i=X509_verify_cert(csc);
    X509_STORE_CTX_free(csc);

    ret=0;
end:
    ret = (i > 0);
    if (x != NULL)
        X509_free(x);

    return(ret);
}
like image 166
John Avatar answered Oct 12 '22 05:10

John


The openssl verify -CAfile <CA_cert_filename> <unknown_cert_filename> command will do what you want -- it's miserable to try to find the API that will do what you want, so I'd suggest finding the source code for the openssl verify routine.

(If you have choice of implementations, gnutls looks promising:

   #include <gnutls/x509.h>

   int gnutls_x509_crt_verify(gnutls_x509_crt_t cert, const  gnutls_x509_crt_t
   * CA_list, int CA_list_length, unsigned int flags, unsigned int * verify);

But OpenSSL is installed everywhere..)

like image 45
sarnold Avatar answered Oct 12 '22 03:10

sarnold