Hi,

 

I'm working on a simple C-program to parse an X.509 certificate in PEM
format, retrieve the public key and hash it so I can add this to a data
package being sent to different remote sites and, at those sites,
compare the hash to the subjectKeyIdentifier of the end-entity
certificate and thus establish the first link in a chain of
certificates.  The program is up and running but I can't get the hash to
match the subjectKeyIdentifier because the hash is running on the public
key included in the certificate plus some extra bytes at the beginning
of the key.  The public key algorithm is id-ecPublicKey and from digging
around on the internet a little bit I found that the extra bytes in
front of the public key are identifying this fact.  Here is an excerpt
from the certificate I am using to test:

 

        Subject Public Key Info:

            Public Key Algorithm: id-ecPublicKey

            EC Public Key:

                pub:

                    04:00:71:b0:b1:69:5c:a2:db:26:fa:ef:96:d7:83:

                    a3:1c:a6:44:4b:1b:5f:e7:a7:6f:dd:08:53:32:1e:

                    b3:fc:73:87:a2:e3:90:fa:04:77:da:18:4f:58:49:

                    fa:cd:78:1f:e6:3f:c4:70:a9:5a:7e:20:28:99:2a:

                    30:60:e9:e3:d4:07:f5:00:c8:1a:f0:f8:a4:33:74:

                    ed:61:65:f3:d2:8c:39:37:af:95:02:d0:f2:70:08:

                    b9:07:b8:de:21:31:03:d9:81:23:42:f3:84:80:5b:

                    9c:a9:eb:0d:f6:05:ce:cc:ee:69:54:f7:4e:4f:3d:

                    e6:60:ac:b9:a1:cb:55:5f:39:22:f3:6d:23

                ASN1 OID: secp521r1

 

And the output of the public key after I put it in DER format and print
it in hex with the underlined part being the extra "header":

 

Signer Public Key:
30:81:9b:30:10:06:07:2a:86:48:ce:3d:02:01:06:05:2b:81:04:00:23:03:81:86:
00:04:00:71:b0:b1:...matching public key...:55:5f:39:22:f3:6d:23

 

It is my first time using OpenSSL so there may be some piece of code I
missed where I need to indicate the type of key it is so that I don't
get these extra bytes.  One way or the other, here is my code:

 

int main(int argc, char *argv[])

{

    FILE * fp = NULL;

    X509 * x509 = NULL;

    EVP_PKEY * pubkey = NULL;

    const EVP_MD * md;

    EVP_MD_CTX ctx;

 

    unsigned char *certfile, *alg, *pubkey_der, *pubkey_der_next, *hash;

    unsigned int len;

    unsigned int * olen;

    int i;

 

    if (argc < 2)

    {

        printf("Usage: get_sid <cert_name.pem> [msg_digest]\n");

        return -1;

    }

 

    certfile = strdup(argv[1]);

    if (argc > 2)

    {

        alg = strdup(argv[2]);

    }

    else

    {

        alg = strdup("sha1");

    }

 

    printf("Reading end entity certificate\n");

 

    //Open end entity certificate for x509 reading

    fp = fopen (certfile, "r");

    free(certfile);

    if (fp == NULL)

    {

        return -1;

    }

 

    x509 = PEM_read_X509(fp, NULL, NULL, NULL);

    fclose(fp);

    if (x509 == NULL)

        return -1;

 

    printf("Obtaining public key from x509 cert\n");

 

    //Obtain public key from x509

    pubkey = X509_get_pubkey(x509);

    X509_free(x509);

 

    if(pubkey == NULL)

    {

        return -1;

    }

 

    printf("Public key successfully obtained\n");

 

    //Hash public key to obtain sid

    OpenSSL_add_all_digests();

    if (!(md = EVP_get_digestbyname(alg)))

    {

        free(alg);

        return -1;

    }

    free(alg);

 

    if (!(hash = malloc(EVP_MAX_MD_SIZE)))

    {

        return -1;

    }

 

    //Convert pubkey into DER format for hash calculation

    pubkey_der = pubkey_der_next = (unsigned char *)malloc(200);

    len = i2d_PUBKEY(pubkey, &pubkey_der_next);

 

    printf("Signer Public Key: ");

    for (i = 0; i < len - 1; ++i)

        printf("%02x:", pubkey_der[i]);

    printf("%02x\n", pubkey_der[i]);

 

    EVP_DigestInit(&ctx, md);

    EVP_DigestUpdate(&ctx, pubkey_der, len);

    EVP_DigestFinal(&ctx, hash, olen);

 

    printf("SID: ");

    for (i = 0; i < *olen - 1; ++i)

        printf("%02x:", hash[i]);

 

    printf("%02x\n", hash[i]);

    free(hash);

 

    return 0;

}

 

Any suggestions to remove the extra bytes from the key (without doing a
hardcode to do the DigestUpdate starting at element x) would be great.
Any other suggestions would be appreciated as well since the library is
huge and it being my first time, there may be some cleaner ways to
execute this program.

 

John Larson

JIPM Systems Engineer, ViaSat Inc.

Reply via email to