none
How to import a certificate and pkcs#12 file into a Cryptographic Provider? RRS feed

  • Question

  • Hi all

    I want to Import a certificate & pfx (pkcs#12) file into a cryptographic hardware token.

    I'm programming with Visual C++ 2008 and using CryptoAPI in windows 7.

    There is two API's called "CryptImportKey" and "CryptExportKey" to import and export public or private or session keys into a CSP (Cryptographic Service Provider) but there is not any API to import a cert & pfx into a CSP!

    Here is part of my code to import pfx file to a cert store in memory, but I don't know how should I transfer this cert store into the CSP (indeed, into the token with it's CSP)?

    int main()
    {
    
    CRYPT_DATA_BLOB data;
    
    // load key-pair from disk to memory.
    FILE *fIn;
    errno_t err;
    
    if( (err  = fopen_s(&fIn, "C:\\my.pfx", "rb")) !=0 )
          MyHandleError("File my.pfx Not Found!!\n");
       else
          printf( "The file 'my.pfx' was opened\n" );
    
    if(fseek(fIn, 0, SEEK_END)) 
    {
    	fclose(fIn);
    	MyHandleError("Error in fseek1!!\n");
    }
    
    if((data.cbData = ftell(fIn)) == -1) 
    {
    	fclose(fIn);
    	MyHandleError("Error in ftell!!\n");
    }
    
    if(fseek(fIn, 0, SEEK_SET)) 
    {
    	fclose(fIn);
    	MyHandleError("Error in fseek2!!\n");
    }
    
    if(!(data.pbData = (BYTE*)malloc(data.cbData)))
        MyHandleError("The data.pbData malloc operation failed. \n");
    
    int nread = fread(data.pbData, 1, data.cbData, fIn);
    if (nread == 0) 
    	MyHandleError("Error in fread!!\n");
    
    if (nread == data.cbData)
        printf("The pfx file is read successfully.\n");
    
    fclose(fIn);
    
    // Convert key-pair data to the in-memory certificate store
    WCHAR pszPassword[] = TEXT("bahareh");
    HCERTSTORE hCertStore = PFXImportCertStore(&data, pszPassword, 0);
    SecureZeroMemory(pszPassword, sizeof(pszPassword));
    
    
    if (!hCertStore)
    {
      printf("Password is empty1.\n");
      hCertStore = PFXImportCertStore(&data, L"", 0);
      
    }
    
    if (!hCertStore)
    {
      printf("Password is empty2.\n");
      hCertStore = PFXImportCertStore(&data, NULL, 0);
    }
    
    ...

    Could you help me about this?

    TIA

    • Moved by Helen Zhao Monday, June 4, 2012 5:39 AM (From:Visual C++ General)
    Friday, June 1, 2012 2:39 PM

All replies

  • Hi creative22,

    According to your description, I'd like to move this thread to "Application Security for Windows Desktop Forum" for better support.

    Thanks for your understanding and active participation in the MSDN Forum.

    Best regards,


    Helen Zhao [MSFT]
    MSDN Community Support | Feedback to us

    Monday, June 4, 2012 5:39 AM
  • Hi Creative22,

    You should pass in the PKCS12_NO_PERSIST_KEY flag to PFXImportCertStore so that the keys are not written to disk. Then iterate through the cert store calling CryptAcquireCertificatePrivateKey on each cert context to get a handle to the key [if one exists on the cert]. Then call CryptExportKey on the key handle.

    Then you will need to call CryptImportKey on your csp handle to import the key into your csp.

    Andrew

    Monday, June 4, 2012 5:18 PM
  • Hi Creative22,

    You should pass in the PKCS12_NO_PERSIST_KEY flag to PFXImportCertStore so that the keys are not written to disk. Then iterate through the cert store calling CryptAcquireCertificatePrivateKey on each cert context to get a handle to the key [if one exists on the cert]. Then call CryptExportKey on the key handle.

    Then you will need to call CryptImportKey on your csp handle to import the key into your csp.

    Andrew

    Thank you very much dear Andrew!

    Your Reply was so helpful.

    I did your advice and added some piece of code into my program as following:

    #include <stdio.h>
    #include <windows.h>
    #include <wincrypt.h>
    void MyHandleError(char *s);
    #pragma comment (lib, "crypt32")
    
    int main()
    {
    CRYPT_DATA_BLOB data;
    
    // load key-pair from disk to memory.
    FILE *fIn;
    errno_t err;
    
    if( (err  = fopen_s(&fIn, "C:\\my.pfx", "rb")) !=0 )
          MyHandleError("File my.pfx Not Found!!\n");
       else
          printf( "The file 'my.pfx' was opened\n" );
    
    if(fseek(fIn, 0, SEEK_END)) 
    {
    	fclose(fIn);
    	MyHandleError("Error in fseek1!!\n");
    }
    
    if((data.cbData = ftell(fIn)) == -1) 
    {
    	fclose(fIn);
    	MyHandleError("Error in ftell!!\n");
    }
    
    if(fseek(fIn, 0, SEEK_SET)) 
    {
    	fclose(fIn);
    	MyHandleError("Error in fseek2!!\n");
    }
    
    // Allocate memory for the encoded name.
    if(!(data.pbData = (BYTE*)malloc(data.cbData)))
        MyHandleError("The data.pbData malloc operation failed. \n");
    
    int nread = fread(data.pbData, 1, data.cbData, fIn);
    if (nread == 0) 
    	MyHandleError("Error in fread!!\n");
    
    if (nread == data.cbData)
        printf("The pfx file is read successfully.\n");
    
    fclose(fIn);
    
    // Convert key-pair data to the in-memory certificate store 
    WCHAR pszPassword[] = TEXT("bahareh");
    HCERTSTORE hCertStore = PFXImportCertStore(&data, pszPassword, PKCS12_NO_PERSIST_KEY);
    SecureZeroMemory(pszPassword, sizeof(pszPassword));
    
    if (!hCertStore)
    {
      printf("Password is empty1.\n");
      hCertStore = PFXImportCertStore(&data, L"", 0);
    }
    
    if (!hCertStore)
    {
      printf("Password is empty2.\n");
      hCertStore = PFXImportCertStore(&data, NULL, 0);
    }
    
    
    //----------------------------------------------
    //=======<<< New Piece of Code >>>=============-
    //----------------------------------------------
    
    
    // Find the certificate in P12 file   
    PCCERT_CONTEXT hContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL);
    if (!hContext)
      MyHandleError("The CertFindCertificateInStore failed. \n");
    
    BOOL bFreeHandle;
    HCRYPTPROV hProv;
    DWORD dwKeySpec;
    
    // acquire private key to this certificate    
    if(CryptAcquireCertificatePrivateKey(hContext, 0, NULL, &hProv, &dwKeySpec, &bFreeHandle))
    {
        printf("The CryptAcquireCertificatePrivateKey succeeded. \n");
    }
    else
    {
        MyHandleError("The CryptAcquireCertificatePrivateKey failed. \n");
    }
    
    // Export the key pair.
    BYTE *pbKeyBlob;
    DWORD dwBlobLen;
    
    // Export the public key.
    HCRYPTKEY hAltKey;
    hAltKey = (HCRYPTKEY)hProv;
    
    if(CryptExportKey(hAltKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwBlobLen)) 
    {
         printf("Size of the BLOB for the private key determined. \n");
    }
    else
    {
         MyHandleError("Error computing BLOB length.");
    }
    
    // Allocate memory for the pbKeyBlob.
    if(pbKeyBlob = (BYTE*)malloc(dwBlobLen)) 
    {
        printf("Memory has been allocated for the BLOB. \n");
    }
    else
    {
        MyHandleError("Out of memory. \n");
    }
    
    // Do the actual exporting into the key BLOB.
    if(CryptExportKey(hAltKey, NULL, PRIVATEKEYBLOB, 0, pbKeyBlob, &dwBlobLen))
    {
         printf("Contents have been written to the BLOB. \n");
    }
    else
    {
        MyHandleError("Error during CryptExportKey.");
    }
    
    // Acquire context to the token's CSP
    HCRYPTPROV hCryptProv;
            
    if(CryptAcquireContext(&hCryptProv, L"My Sample", L"EnterSafe ePass3003 CSP v1.0", PROV_RSA_FULL, 0))
    {
       printf("A crypto context with key container has been acquired.\n");
    }
    else
    { 
        if(GetLastError() == NTE_BAD_KEYSET)
        {
            if(CryptAcquireContext(&hCryptProv, L"My Sample", L"EnterSafe ePass3003 CSP v1.0", PROV_RSA_FULL, CRYPT_NEWKEYSET)) 
            {
                printf("A new key container has been created.\n");
            }
            else
            {
                MyHandleError("Could not create a new key container.\n");
            }
        }
        else
        {
                MyHandleError("CryptAcquireContext failed.\n");
        }
    }
    
    // Import the key into the CSP. 
    HCRYPTKEY hKey;
    if(CryptImportKey(hCryptProv, pbKeyBlob, dwBlobLen, 0, 0, &hKey))
    {
         printf("The key has been imported.\n");
    }
    else
    {
         MyHandleError("Private key import failed.");
    }
    
    //Release all the resources...
    
    // Release the certificate context. 
    if(hContext)
    {
       if(!CertFreeCertificateContext(hContext))
       {
          MyHandleError("Error during CertFreeCertificateContext!\n");
       }
    }
    
    // Release the certificate store. 
    if(hCertStore)
    {
       if(!CertCloseStore(hCertStore,0))
       {
          MyHandleError("Error during CertCloseStore!\n");
       }
    }
    
    // Free memory 
    if(pbKeyBlob)
       free(pbKeyBlob);
    
    if(data.pbData)
       free(data.pbData);
    
    // Release the Export key handle. 
    if(hKey)
    {
       if(!(CryptDestroyKey(hKey)))
       {
          MyHandleError("Error during CryptDestroyKey!\n");
       }
        hKey = 0;
    }
    
    // Release the provider handle.
    if(hCryptProv) 
       CryptReleaseContext(hCryptProv, 0);
    
    // Release the hProv handle.
    if (bFreeHandle)
        if(hProv)
    	{
    		printf("bFreeHandle & hProv is true.\n");
    		if(!(CryptReleaseContext(hProv, 0)))
    		{
    			MyHandleError("Error during CryptReleaseContext.");
    		}
    	} 
    	printf("Everything is OK!\n");
    
     return 0;
    
    }//end of main
    
    void MyHandleError(char *s)
    {
        fprintf(stderr,"An error occurred in running the program. \n");
        fprintf(stderr,"%s\n",s);
        fprintf(stderr, "Error number %x.\n", GetLastError());
        fprintf(stderr, "Program terminating. \n");
        exit(1);
    }

    Now, problem is in first call to CryptExportKey function?!

    First, I called it with "hProv" handle returned by CryptAcquireCertificatePrivateKey. but the program returned with the error ERROR_INVALID_PARAMETER caused by CryptExportKey.

    Then I did a casting to a HCRYPTKEY type (I'm not sure about this work!) and passed in to CryptExportKey.

    HCRYPTKEY hAltKey;
    hAltKey = (HCRYPTKEY)hProv;
    
    if(CryptExportKey(hAltKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwBlobLen)) 

    But the error ERROR_INVALID_PARAMETER is returning from the program yet!

    I've also tried PLAINTEXTKEYBLOB flag instead of PRIVATEKEYBLOB, but I've not seen any change!

    Should I use a key pair as second argument in this function to encrypt the retrieved private key from cert store certainly?

    I don't want to use any other key in this process.

    I just want to import pfx file (certificate & corresponding private key) into the token (in a key container within the token for example). 

    Could you guild me again about this?

    And what about importing & exporting only different Certificates into & from token?

    I know that should use CryptSetKeyParam & CryptGetKeyParam with KP_CERTIFICATE flag, but I also have problem with them!

    Is there a sample code for using them to import & export certificate into a hardware token (with CSP)?

    What steps would be required for this procedure?

    Any help will be greatly appreciated;

    Good Luck

    Creative22 

    Saturday, June 9, 2012 11:50 AM
  • Before calling CryptExportKey, be sure to call CryptGetUserKey [http://msdn.microsoft.com/en-us/library/ms938123.aspx].

    That is the appropriate way to get an HCRYPTKEY from an HCRYPTPROV. You should not cast one to the other.

    Andrew

    Monday, June 11, 2012 1:48 AM
  • Before calling CryptExportKey, be sure to call CryptGetUserKey [http://msdn.microsoft.com/en-us/library/ms938123.aspx].

    That is the appropriate way to get an HCRYPTKEY from an HCRYPTPROV. You should not cast one to the other.

    Andrew

    Hi Andrew and thank you!

    I've added the required code as below:

    if(CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hKey))
    {
        printf("An exchange key is available.\n");
    }
    else
    {
        printf("No exchange key is available.\n");
    } 
    
    if(CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwBlobLen)) 
    {
    	printf("Size of the BLOB for the private key determined: %d \n", dwBlobLen);
    }
    else
    {
         MyHandleError("Error computing BLOB length.");
    }

    Now, I get NTE_BAD_TYPE  error for CryptExportKey!

    MSDN documentation about this error is:

    "The dwBlobType parameter (PRIVATEKEYBLOB) specifies an unknown BLOB type."

    What's the problem?

    Also, when I use PUBLICKEYBLOB flag instead, the code runs but doesn't import the public key of pfx into the token!

    So that I don't see anything in the new key container on the token.

    Could you help me again?!

    sincerely.

    Monday, June 11, 2012 6:44 PM
  • I copied your code and CryptExportKey [both calls] succeeded. using PRIVATEKEYBLOB as the blob type. I think it is time you look at your CSP. What CSP was your PFX created with? Do: certutil -asn c:\my.pfx

    It will dump out the asn and you should see the csp name in the clear.

    Andrew

    Tuesday, June 12, 2012 2:57 AM
  • I copied your code and CryptExportKey [both calls] succeeded. using PRIVATEKEYBLOB as the blob type. I think it is time you look at your CSP. What CSP was your PFX created with? Do: certutil -asn c:\my.pfx

    It will dump out the asn and you should see the csp name in the clear.

    Andrew

    I've generated my.pfx file with openssl and it's asn dump is here:

    0000: 30 82 07 16                               ; SEQUENCE (716 Bytes)
    0004:    02 01                                  ; INTEGER (1 Bytes)
    0006:    |  03
    0007:    30 82 06 dc                            ; SEQUENCE (6dc Bytes)
    000b:    |  06 09                               ; OBJECT_ID (9 Bytes)
    000d:    |  |  2a 86 48 86 f7 0d 01 07  01
             |  |     ; 1.2.840.113549.1.7.1 PKCS 7 Data
    0016:    |  a0 82 06 cd                         ; OPTIONAL[0] (6cd Bytes)
    001a:    |     04 82 06 c9                      ; OCTET_STRING (6c9 Bytes)
    001e:    |        30 82 06 c5                   ; SEQUENCE (6c5 Bytes)
    0022:    |           30 82 03 97                ; SEQUENCE (397 Bytes)
    0026:    |           |  06 09                   ; OBJECT_ID (9 Bytes)
    0028:    |           |  |  2a 86 48 86 f7 0d 01 07  06
             |           |  |     ; 1.2.840.113549.1.7.6 PKCS 7 Encrypted
    0031:    |           |  a0 82 03 88             ; OPTIONAL[0] (388 Bytes)
    0035:    |           |     30 82 03 84          ; SEQUENCE (384 Bytes)
    0039:    |           |        02 01             ; INTEGER (1 Bytes)
    003b:    |           |        |  00
    003c:    |           |        30 82 03 7d       ; SEQUENCE (37d Bytes)
    0040:    |           |           06 09          ; OBJECT_ID (9 Bytes)
    0042:    |           |           |  2a 86 48 86 f7 0d 01 07  01
             |           |           |     ; 1.2.840.113549.1.7.1 PKCS 7 Data
    004b:    |           |           30 1c          ; SEQUENCE (1c Bytes)
    004d:    |           |           |  06 0a       ; OBJECT_ID (a Bytes)
    004f:    |           |           |  |  2a 86 48 86 f7 0d 01 0c  01 06
             |           |           |  |     ; 1.2.840.113549.1.12.1.6
    0059:    |           |           |  30 0e       ; SEQUENCE (e Bytes)
    005b:    |           |           |     04 08    ; OCTET_STRING (8 Bytes)
    005d:    |           |           |     |  fb df dd d2 a1 f6 29 03                           ; ......).
    0065:    |           |           |     02 02    ; INTEGER (2 Bytes)
    0067:    |           |           |        08 00
    0069:    |           |           80 82 03 50    ; CONTEXT_SPECIFIC[0] (350 Bytes)
    006d:    |           |              d7 25 d6 03 63 59 35 40  d2 30 07 06 63 9b 15 f6  ; .%..cY5@.0..c...
    007d:    |           |              4d 65 d7 38 5e 80 1a 06  fa f0 39 56 bf 21 8b f2  ; Me.8^.....9V.!..
    008d:    |           |              7c ef 06 c7 91 d7 0f c8  6c 39 b4 b9 01 b0 40 25  ; |.......l9....@%
    009d:    |           |              f8 55 31 89 08 75 23 fa  f9 08 c7 e6 48 2c 76 99  ; .U1..u#.....H,v.
    00ad:    |           |              31 87 6f 68 eb ee 29 f5  34 5b c1 d4 8d e1 3d 5d  ; 1.oh..).4[....=]
    00bd:    |           |              d4 95 0e a4 f5 53 23 85  15 6e 6a a1 ed 83 40 06  ; .....S#..nj...@.
    00cd:    |           |              2c 6d b8 24 37 b7 7b 93  cc ee fc 78 86 2c a4 9b  ; ,m.$7.{....x.,..
    00dd:    |           |              64 e1 0a 4b 99 5c e7 78  dc a4 9f be 4a 54 86 84  ; d..K.\.x....JT..
    00ed:    |           |              34 13 3f f1 fe 5c ae 59  4a 51 c2 00 66 69 0e 4e  ; 4.?..\.YJQ..fi.N
    00fd:    |           |              88 b9 98 71 9b cd 49 44  f5 d8 c1 5a b0 08 e5 06  ; ...q..ID...Z....
    010d:    |           |              fc 9d 83 41 0c 9a ba 74  e7 9c eb 29 f3 bc ec 0a  ; ...A...t...)....
    011d:    |           |              62 49 19 f9 d9 6b 13 9d  6e 43 0d 28 f6 50 41 86  ; bI...k..nC.(.PA.
    012d:    |           |              15 0e a9 b0 6b b8 5f 04  b6 12 e4 56 70 80 75 10  ; ....k._....Vp.u.
    013d:    |           |              2a 89 7c 2b 5a d8 57 c5  b0 29 92 93 28 d1 dd 16  ; *.|+Z.W..)..(...
    014d:    |           |              6a e3 f0 c6 73 4e c7 14  9c 46 69 f4 f1 f9 1d 1e  ; j...sN...Fi.....
    015d:    |           |              f9 9a ba a9 2e 6d 25 0f  5d e2 33 27 86 fd a4 c5  ; .....m%.].3'....
    016d:    |           |              c1 8d f5 f7 b7 0d 4f 0f  8e 15 b6 26 de 4e 66 6a  ; ......O....&.Nfj
    017d:    |           |              82 ed 6d b9 d0 13 9a 48  f7 cd a1 6a d4 96 8d 92  ; ..m....H...j....
    018d:    |           |              04 fe 24 36 e5 ae ac 3b  e3 6b 2d 0f fe 50 a2 f4  ; ..$6...;.k-..P..
    019d:    |           |              36 d4 14 8d 44 c4 33 4a  5f 12 7e 10 43 37 a5 f5  ; 6...D.3J_.~.C7..
    01ad:    |           |              4d 20 3d fd 3c e3 84 01  0a 2c 3b 8c f0 90 24 3b  ; M =.<....,;...$;
    01bd:    |           |              5c 91 39 62 c8 a3 1c d8  9f c1 6e 1f 7a 2c 3a d9  ; \.9b......n.z,:.
    01cd:    |           |              3b 8b 07 ce e5 03 40 59  66 11 f5 14 eb 3b 1a 3c  ; ;.....@Yf....;.<
    01dd:    |           |              fe 31 d1 94 34 6b 1d 8e  69 c6 13 16 ae 0c 2b 61  ; .1..4k..i.....+a
    01ed:    |           |              e8 42 42 20 83 fb 77 a9  11 af 82 d5 3d 5a 2b 7f  ; .BB ..w.....=Z+.
    01fd:    |           |              a3 bd c0 dd fe 5c e3 4d  93 8f d4 73 f7 32 9b eb  ; .....\.M...s.2..
    020d:    |           |              3f d7 1a df e6 8f 31 e2  80 08 e4 39 0f b1 d2 c8  ; ?.....1....9....
    021d:    |           |              4d 6e 10 2c 6a 4e dc dc  82 b6 6b 39 97 e2 8f 2c  ; Mn.,jN....k9...,
    022d:    |           |              df 31 f5 42 42 09 b0 21  71 72 eb 96 e0 15 28 de  ; .1.BB..!qr....(.
    023d:    |           |              47 b0 8e 1e 8c c3 89 fd  cb 5c 73 16 73 8e ef 32  ; G........\s.s..2
    024d:    |           |              b6 f1 ff 34 46 6a 28 51  11 43 46 1a 81 c8 d0 c0  ; ...4Fj(Q.CF.....
    025d:    |           |              8c d4 56 f0 0b 0c ed dc  0b 40 3a 73 fc 2c 15 31  ; ..V......@:s.,.1
    026d:    |           |              b3 f0 9a 91 aa 28 fa 3b  34 23 88 48 36 c5 13 cf  ; .....(.;4#.H6...
    027d:    |           |              cc 22 2c a6 fb a2 91 4a  f1 ce 2d e1 41 d1 0f 4c  ; .",....J..-.A..L
    028d:    |           |              1a 5a a3 93 27 e3 24 67  02 2a 62 c8 5a 1c b7 ab  ; .Z..'.$g.*b.Z...
    029d:    |           |              7c 31 2a 4d b8 64 3a 53  99 93 0f f0 25 b8 92 2e  ; |1*M.d:S....%...
    02ad:    |           |              19 14 9a 02 0b 09 df 5a  f8 3e c7 14 86 46 ee 6c  ; .......Z.>...F.l
    02bd:    |           |              7b 8d 65 ac 8f 8a e8 2c  36 2f ec 2d 3d 08 b6 38  ; {.e....,6/.-=..8
    02cd:    |           |              40 07 20 69 53 62 4e 93  b1 12 97 fb f1 74 08 38  ; @. iSbN......t.8
    02dd:    |           |              35 29 37 27 90 ba 6f b9  2e 4a 77 69 2e 32 96 15  ; 5)7'..o..Jwi.2..
    02ed:    |           |              74 96 55 e6 a5 32 aa 07  3b 31 f7 93 bf 3e d5 ce  ; t.U..2..;1...>..
    02fd:    |           |              d7 da 5c d0 87 3b 80 85  c7 89 06 78 34 2e 9f 21  ; ..\..;.....x4..!
    030d:    |           |              7d 2c 03 e4 12 10 9b 19  c0 29 53 4a 57 d9 c6 36  ; },.......)SJW..6
    031d:    |           |              e0 df cb 27 d7 b4 cc e4  d8 99 5b 0e d6 35 d9 72  ; ...'......[..5.r
    032d:    |           |              01 e3 da cf d4 fd 17 60  1b bb d0 4c 82 5f ba 71  ; .......`...L._.q
    033d:    |           |              ca c7 37 ec 3f 12 15 ff  7c 3e 45 8b 75 07 f8 66  ; ..7.?...|>E.u..f
    034d:    |           |              33 5f 41 0c 49 c7 b1 9c  e8 19 a6 f6 3f b3 6b 95  ; 3_A.I.......?.k.
    035d:    |           |              33 7b ca d6 17 31 1f 7d  98 e7 72 d2 08 64 df f9  ; 3{...1.}..r..d..
    036d:    |           |              0e cc 16 2a ab 17 ea 6d  db e1 74 a2 a0 7c 15 af  ; ...*...m..t..|..
    037d:    |           |              0c 48 2d 32 55 c6 e4 9f  1d 68 f9 df 3e f4 6e c2  ; .H-2U....h..>.n.
    038d:    |           |              1f 81 f7 62 20 1b 73 b5  01 29 16 64 44 47 28 d0  ; ...b .s..).dDG(.
    039d:    |           |              31 d7 1c 5b 8d 95 29 0e  dc 65 71 ad a6 d6 da 2f  ; 1..[..)..eq..../
    03ad:    |           |              fb 93 68 6b d0 e4 0d 92  0d e9 de 78 06 bd aa 52  ; ..hk.......x...R
    03bd:    |           30 82 03 26                ; SEQUENCE (326 Bytes)
    03c1:    |              06 09                   ; OBJECT_ID (9 Bytes)
    03c3:    |              |  2a 86 48 86 f7 0d 01 07  01
             |              |     ; 1.2.840.113549.1.7.1 PKCS 7 Data
    03cc:    |              a0 82 03 17             ; OPTIONAL[0] (317 Bytes)
    03d0:    |                 04 82 03 13          ; OCTET_STRING (313 Bytes)
    03d4:    |                    30 82 03 0f       ; SEQUENCE (30f Bytes)
    03d8:    |                       30 82 03 0b    ; SEQUENCE (30b Bytes)
    03dc:    |                          06 0b       ; OBJECT_ID (b Bytes)
    03de:    |                          |  2a 86 48 86 f7 0d 01 0c  0a 01 02
             |                          |     ; 1.2.840.113549.1.12.10.1.2
    03e9:    |                          a0 82 02 a6 ; OPTIONAL[0] (2a6 Bytes)
    03ed:    |                          |  30 82 02 a2      ; SEQUENCE (2a2 Bytes)
    03f1:    |                          |     30 1c ; SEQUENCE (1c Bytes)
    03f3:    |                          |     |  06 0a      ; OBJECT_ID (a Bytes)
    03f5:    |                          |     |  |  2a 86 48 86 f7 0d 01 0c  01 03
             |                          |     |  |     ; 1.2.840.113549.1.12.1.3
    03ff:    |                          |     |  30 0e      ; SEQUENCE (e Bytes)
    0401:    |                          |     |     04 08   ; OCTET_STRING (8 Bytes)
    0403:    |                          |     |     |  e3 b8 45 58 93 95 55 86                           ; ..EX..U.
    040b:    |                          |     |     02 02   ; INTEGER (2 Bytes)
    040d:    |                          |     |        08 00
    040f:    |                          |     04 82 02 80   ; OCTET_STRING (280 Bytes)
    0413:    |                          |        b4 60 16 45 58 c1 6a 8f  b9 35 8e a7 03 e2 6c 18  ; .`.EX.j..5....l.
    0423:    |                          |        e7 c7 be 9f 8a 8b 88 94  08 f5 d4 87 e0 e9 f2 ef  ; ................
    0433:    |                          |        dd 97 74 3b 2f e7 15 40  b0 1b 1e 29 39 db 3a 5b  ; ..t;/..@...)9.:[
    0443:    |                          |        e3 09 4b 67 72 25 1b 18  38 f1 b3 24 68 2a c6 9a  ; ..Kgr%..8..$h*..
    0453:    |                          |        b8 f1 4a 11 8d 86 b0 2f  1a 82 96 58 3b 15 33 c0  ; ..J..../...X;.3.
    0463:    |                          |        ee 45 19 9c 52 6b d4 9f  62 5a 7b 97 38 19 4f f3  ; .E..Rk..bZ{.8.O.
    0473:    |                          |        59 68 02 86 3f bd 6b ca  10 25 1f 46 66 16 9f 4c  ; Yh..?.k..%.Ff..L
    0483:    |                          |        97 c6 87 0c 03 16 92 fc  af 3b 63 19 74 16 4d 81  ; .........;c.t.M.
    0493:    |                          |        53 d4 d7 8d 76 4a e2 79  38 8e 02 75 49 c6 d9 b8  ; S...vJ.y8..uI...
    04a3:    |                          |        5f d3 7c 7d 9d 86 dd 34  34 ce 88 06 be b7 ea be  ; _.|}...44.......
    04b3:    |                          |        7f 63 7b 42 04 71 29 ea  d2 47 b0 b6 eb 24 c9 80  ; .c{B.q)..G...$..
    04c3:    |                          |        1b 9e fb 35 08 4f b9 79  69 b1 29 0f bf 8f 6c f7  ; ...5.O.yi.)...l.
    04d3:    |                          |        47 a4 aa 2e b3 1a aa 9f  74 a2 72 e8 ed f9 3e 17  ; G.......t.r...>.
    04e3:    |                          |        26 8d c2 b3 8c a7 42 5d  48 95 25 4e 19 f8 fc 07  ; &.....B]H.%N....
    04f3:    |                          |        e2 ba e9 84 f5 57 b4 b9  ff 29 31 67 f5 49 10 97  ; .....W...)1g.I..
    0503:    |                          |        20 66 ab 02 5e 00 9c cf  a0 15 2e 2b 81 17 16 42  ;  f..^......+...B
    0513:    |                          |        3f ee f9 5c e3 02 de 70  94 80 fe a5 6d b7 b5 79  ; ?..\...p....m..y
    0523:    |                          |        3e 54 e1 0e 13 26 d0 cd  b2 3d 59 6f 8d d9 a8 63  ; >T...&...=Yo...c
    0533:    |                          |        b7 8b bd e3 9b 92 e9 b4  c6 a9 81 18 11 8e 49 d9  ; ..............I.
    0543:    |                          |        de 6b 99 22 27 1b 73 f2  33 a8 c6 b2 c1 3c 14 c8  ; .k."'.s.3....<..
    0553:    |                          |        f3 35 5f 6d f3 99 65 8e  dc 30 f9 fc 37 6e a1 c3  ; .5_m..e..0..7n..
    0563:    |                          |        c0 53 42 71 84 28 74 c3  0d cb c1 d8 97 36 bb 7d  ; .SBq.(t......6.}
    0573:    |                          |        0f a6 1f a3 32 4b 51 01  f3 08 9a 2f 4f 62 c9 9e  ; ....2KQ..../Ob..
    0583:    |                          |        6a 06 39 8b c7 ba 1b 2e  3f 43 c6 30 3a 56 79 26  ; j.9.....?C.0:Vy&
    0593:    |                          |        ff e0 a0 2c 47 ff fd be  dc 92 c9 52 51 1c b5 73  ; ...,G......RQ..s
    05a3:    |                          |        db ca 6c 69 a4 cf e7 e6  0a 11 8c c7 d1 74 e4 1d  ; ..li.........t..
    05b3:    |                          |        67 65 11 16 cd bc 4a d1  79 0e b0 9c 21 da 26 79  ; ge....J.y...!.&y
    05c3:    |                          |        e5 0d 59 de ab f0 66 1a  bb 0b c6 43 7b 08 ee 66  ; ..Y...f....C{..f
    05d3:    |                          |        0d 65 4e 82 cc bd 42 08  be fe 8c 84 59 db 2c 5b  ; .eN...B.....Y.,[
    05e3:    |                          |        01 8b 60 76 d4 3f 74 a7  04 b8 0b 07 76 21 db 92  ; ..`v.?t.....v!..
    05f3:    |                          |        0d a5 b9 f1 01 7e ff ac  d8 f2 55 35 e7 f3 cc 90  ; .....~....U5....
    0603:    |                          |        51 89 61 03 90 4a 12 19  24 4f e2 4d 1f 22 bd 66  ; Q.a..J..$O.M.".f
    0613:    |                          |        91 a0 35 51 af a2 25 e8  70 61 3b 9f dc 18 b8 7e  ; ..5Q..%.pa;....~
    0623:    |                          |        b4 b1 b7 3f c6 4e af da  b2 30 bc a1 4b 02 bd 7c  ; ...?.N...0..K..|
    0633:    |                          |        db 8a 09 74 f8 37 62 87  8a 79 8b 3e 3d 97 29 d5  ; ...t.7b..y.>=.).
    0643:    |                          |        6f ea 2c 14 e6 c8 93 5c  45 5f 43 0f a4 a3 f3 5b  ; o.,....\E_C....[
    0653:    |                          |        67 5d 99 29 66 6c 7f 20  9e 27 77 e6 4b 05 ba 15  ; g].)fl. .'w.K...
    0663:    |                          |        87 0c 0d 1b 48 34 29 d8  56 95 07 07 ec 14 8c d8  ; ....H4).V.......
    0673:    |                          |        31 1c 9b 68 c6 1a 92 86  1a e7 a6 a6 c8 2c 83 d9  ; 1..h.........,..
    0683:    |                          |        39 a8 cb 10 b1 dc 59 91  cb 37 ec 79 e0 48 ee e3  ; 9.....Y..7.y.H..
    0693:    |                          31 52       ; SET (52 Bytes)
    0695:    |                             30 23    ; SEQUENCE (23 Bytes)
    0697:    |                             |  06 09 ; OBJECT_ID (9 Bytes)
    0699:    |                             |  |  2a 86 48 86 f7 0d 01 09  15
             |                             |  |     ; 1.2.840.113549.1.9.21
    06a2:    |                             |  31 16 ; SET (16 Bytes)
    06a4:    |                             |     04 14      ; OCTET_STRING (14 Bytes)
    06a6:    |                             |        44 0e bb 37 11 fe 76 c2  32 ad fa 14 49 00 ec 6b  ; D..7..v.2...I..k
    06b6:    |                             |        8a 80 e2 b1                                       ; ....
    06ba:    |                             30 2b    ; SEQUENCE (2b Bytes)
    06bc:    |                                06 09 ; OBJECT_ID (9 Bytes)
    06be:    |                                |  2a 86 48 86 f7 0d 01 09  14
             |                                |     ; 1.2.840.113549.1.9.20
    06c7:    |                                31 1e ; SET (1e Bytes)
    06c9:    |                                   1e 1c      ; UNICODE_STRING (1c Bytes)
    06cb:    |                                      00 4d 00 79 00 20 00 43  00 65 00 72 00 74 00 69  ; .M.y. .C.e.r.t.i
    06db:    |                                      00 66 00 69 00 63 00 61  00 74 00 65              ; .f.i.c.a.t.e
             |                                         ; "My Certificate"
    06e7:    30 31                                  ; SEQUENCE (31 Bytes)
    06e9:       30 21                               ; SEQUENCE (21 Bytes)
    06eb:       |  30 09                            ; SEQUENCE (9 Bytes)
    06ed:       |  |  06 05                         ; OBJECT_ID (5 Bytes)
    06ef:       |  |  |  2b 0e 03 02 1a
                |  |  |     ; 1.3.14.3.2.26 sha1 (sha1NoSign)
    06f4:       |  |  05 00                         ; NULL (0 Bytes)
    06f6:       |  04 14                            ; OCTET_STRING (14 Bytes)
    06f8:       |     fa 35 bf 6d 92 b9 6f 47  bc e1 b6 28 c8 42 9e 5e  ; .5.m..oG...(.B.^
    0708:       |     e0 be fa 42                                       ; ...B
    070c:       04 08                               ; OCTET_STRING (8 Bytes)
    070e:       |  12 20 01 8c f0 7e b5 41                           ; . ...~.A
    0716:       02 02                               ; INTEGER (2 Bytes)
    0718:          08 00
    CertUtil: -asn command completed successfully.
    

    The certificate Friendly Name is "My Certificate".

    If I import this pkcs12 file into the windows Certificate Store, a key container with "My Certificate" name is created for it to hold the pfx private key in the following directory :

    C:\Users\Administrator\AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-21-2085089358-1753042714-1925376585-500\

    that usually is related to the system default CSP (Microsoft Strong Cryptographic Provider).

    But I don't see any CSP name in this asn1 dump!

    Also, when I test the code with a pfx file issued by Microsoft CA, the program stops with error "CRYPT_E_NO_KEY_PROPERTY" returned by CryptAcquireCertificatePrivateKey!

    With openssl created my.pfx, I see the error NTE_BAD_TYPE from CryptExportKey function YET!

    What's your opinion please?!

    Thanks a lot.

    Tuesday, June 12, 2012 11:16 AM
  • openssl does not put in a csp name in the pfx. That's ok. The Microsoft Strong CSP will be used.

    What is the password for the pfx? I will try to decode it.

    Microsoft CA does not issue pfx files so I don't understand how you are getting the CRYPT_E_NO_KEY_PROPERTY. Most likely you have a cert with no corresponding key.


    Andrew

    Wednesday, June 13, 2012 1:56 AM
  • openssl does not put in a csp name in the pfx. That's ok. The Microsoft Strong CSP will be used.

    What is the password for the pfx? I will try to decode it.

    Microsoft CA does not issue pfx files so I don't understand how you are getting the CRYPT_E_NO_KEY_PROPERTY. Most likely you have a cert with no corresponding key.


    Andrew

    Hi 

    Could I have your email to send pfx files Or is it possible to upload some files on this MSDN thread?

    I'd like to send you two openssl created pfx files as below:

    1) my.pfx

    2) mypfx3.p12

    And one Microsoft CA retrieved pkcs12 file:

     mypfx5.pfx

    And one EJBCA generated pkcs12 file: 

     superadmin.p12

    BTW, my.pfx password is within the code: "bahareh".

    I've tried mypfx5.pfx (retrieved by Microsoft CA) and superadmin.p12 and got the error CRYPT_E_NO_KEY_PROPERTY with the both files!

    Best Regards.

     

    Wednesday, June 13, 2012 8:32 AM
  • Two problems:

    On the call to PfxImportCertStore, you should also make sure you pass in CRYPT_EXPORTABLE.
    On the call to CryptAcquireCertificatePrivateKey, you should pass in CRYPT_ACQUIRE_CACHE_FLAG.

    The purpose of these flags is well documented on msdn. CRYPT_EXPORTABLE is needed so that we can export the key from the csp. CRYPT_ACQUIRE_CACHE_FLAG is needed because the key was imported into memory so no KEY_PROV_INFO property exists on the certificate context.

    With these 2 changes I was able to export the key from the pfx that you provided [my.pfx]. This should also get around the problem you had with the CRYPT_E_NO_KEY_PROPERTY error.

    Andrew

    • Proposed as answer by Andrew Bernat Thursday, June 14, 2012 5:38 PM
    Thursday, June 14, 2012 5:35 PM
  • Two problems:

    On the call to PfxImportCertStore, you should also make sure you pass in CRYPT_EXPORTABLE.
    On the call to CryptAcquireCertificatePrivateKey, you should pass in CRYPT_ACQUIRE_CACHE_FLAG.

    The purpose of these flags is well documented on msdn. CRYPT_EXPORTABLE is needed so that we can export the key from the csp. CRYPT_ACQUIRE_CACHE_FLAG is needed because the key was imported into memory so no KEY_PROV_INFO property exists on the certificate context.

    With these 2 changes I was able to export the key from the pfx that you provided [my.pfx]. This should also get around the problem you had with the CRYPT_E_NO_KEY_PROPERTY error.

    Andrew

    Thanks!

    The program with my.pfx runs and the public & private keys are imported into "My2" key container as following:

    But when I import my.pfx with the above token utility in another key container (My Sample), the public & private keys with the certificate are imported as the following:

    Is it possible to import all of pub/priv key and cert into the token?

    If so, with which flags?

    BTW, I've tried the following cases:

    1) my.pfx and mypfx3.p12 (both, openssl generated)

    The program is OK and only pub & priv keys without corresponding certificate are imported;

    2) mypfx4.p12 (openssl generated that has two certificates (a CA certificate and it's own certificate))

    The program returns with CRYPT_E_NO_KEY_PROPERTY error related to CryptAcquireCertificatePrivateKey.

    3) mypfx5.pfx (Microsoft CA generated that has one certificate)

    The program returns with CRYPT_E_NO_KEY_PROPERTY error related to CryptAcquireCertificatePrivateKey.

    4) mypfx6,pfx (Microsoft CA generated that has two certificates (a CA certificate and it's own certificate))

    The program returns with CRYPT_E_NO_KEY_PROPERTY error related to CryptAcquireCertificatePrivateKey.

    5) superadmin.p12 (EJBCA generated that has two certificates (a CA certificate and it's own certificate))

    The program returns with CRYPT_E_NO_KEY_PROPERTY error related to CryptAcquireCertificatePrivateKey.


    The changed parts are:

    HCERTSTORE hCertStore = PFXImportCertStore(&data, pszPassword, PKCS12_NO_PERSIST_KEY | CRYPT_EXPORTABLE);
    
    CryptAcquireCertificatePrivateKey(hContext, CRYPT_ACQUIRE_CACHE_FLAG, NULL, &hProv, &dwKeySpec, &bFreeHandle)

    What's wrong with the code?

    Thanks again for your all helps...

    Saturday, June 16, 2012 3:18 PM
  • I'm not 100% sure but I think you need to call CryptSetKeyParam with KP_CERTIFICATE and the cert you want associated with your key. This will put the certificate together with your key. At least that's how I think most smartcard based CSPs behave.

    To answer your specific questions:

    1) Use KP_CERTIFICATE property as a I described above.

    2) Since your pfx has 2 certificates then you need to find the certificate that has a private key associated with it. My guess is that the CertFindCertificateInStore is picking up the CA cert which really doesn't have a private key. Instead, you should enumerate through the cert store using CertEnumerateCertificatesInStore and on each cert context call CertGetCertificateContextProperty with CERT_KEY_CONTEXT_PROP_ID as the property id. If the call fails then there is no private key for that certificate in the pfx. And you should move onto the next cert.

    3) Run: certutil -dump mypfx5.pfx
    This comand will tell you if you actually have a private key for the cert in the pfx. If you do then send me the ASN encoding of the pfx with the password and I will have a look.

    4) Same problem as 2.

    5) Same problem as 2.

    Andrew

    • Proposed as answer by Andrew Bernat Sunday, June 17, 2012 1:39 AM
    Sunday, June 17, 2012 1:39 AM
  • Hi,

    I have previously published a sample code that shows how to correctly parse the content of a PFX file using CrypoAPI. It contains the same ideas proposed by Andrew and you can modify it in order to add the key and certificate import. Here is the link : http://www.idrix.fr/Root/Samples/pfx_parse.cpp

    Just a last remark : I advice you to use a unique container name for each new imported key instead of hard coding it. For example, you can create GUID based container name using UuidCreate and UuidToString.

    I hope this will help.
    --
    Mounir IDRASSI
    IDRIX
    http://www.idrix.fr



    Mounir IDRASSI - IDRIX - http://www.idrix.fr

    Tuesday, June 19, 2012 11:41 PM