Search code examples
c++cryptographycryptoapipkcs#11

Get CryptoAPI public key via PKCS#11


In my C++ program I created a public/private key pair using CryptoAPI.

CryptGenKey(eTokenProv,ENCRYPT_ALGORITHM,CRYPT_EXPORTABLE,&k1)

Keys are stored in a eToken. Is it possible to get the public key using PKCS#11? The private key previously created is found after a search using the following search-template:

    CK_ATTRIBUTE private_search[] = {
       {CKA_PRIVATE, CK_TRUE, sizeof(CK_BBOOL)}
    };

If I set CKA_PRIVATE to CK_FALSE, I can't get the public key. I also tried with other attributes. Is there a way to do it?

EDIT

As owlstead suggests, I tried to create a public key starting from the modulus and public exponent of a key created in a previous session (in CAPI or, just for this test, in PKCS11). I got the modulus and public exponent from a private key in these buffers:

CK_BYTE  modulus[128]; //if 1024bit
CK_BYTE  publicExponent[4]; //4 Byte, according to public key blob

But when I try to create a new public with key with the following instructions:

CK_ATTRIBUTE publicKeyTemplate[] = {
    {CKA_TOKEN, &yes, sizeof(true)},
    {CKA_WRAP, &yes, sizeof(true)},
    {CKA_ENCRYPT, &yes, sizeof(true)},
    {CKA_MODULUS_BITS, &modulusBits, sizeof(modulusBits)},
    {CKA_MODULUS, &modulus, sizeof(modulus)},
    {CKA_PUBLIC_EXPONENT, &publicExponent, sizeof(publicExponent)}

CK_MECHANISM mechanism = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
rv = (*functions->C_GenerateKeyPair) (session, &mechanism, publicKeyTemplate, 6, privateKeyTemplate, 6, &hPublicKey, &hPrivateKey); 

I get the error "Invalid template". The probles is the modulus, because, without it, I can create a key pair. I use the function C_GenerateKeyPair, but I'm only interested in the public key. I omitted the private template. What is the wrong here?


Solution

  • CKA_PRIVATE does not indicate a private key at all.

    When the CKA_PRIVATE attribute is TRUE, a user may not access the object until the user has been authenticated to the token

    Instead you should look for an attribute such as CKA_CLASS with a value CKO_PUBLIC_KEY or CKO_PRIVATE_KEY, possibly using other attributes to filter your results further.

    If you cannot find any CKO_PUBLIC_KEY then I presume it was either not generated in the token (key was imported, check if CKA_LOCAL is set). Alternatively, it may have only been created as a session object. Finally it may have been removed.

    Note that RSA private keys commonly do contain the public exponent, so you can still construct a public key from just the private key object (using the modulus and public exponent, of course).