CryptImportKey NTE_BAD_KEY error.

From: Neo Sapien (csinger_at_algo.ca)
Date: 05/06/04


Date: Thu, 6 May 2004 13:00:31 -0700

Hi Everyone,

I am having my first crack at using the Crypto API and am having problems
exporting and importing DH keys. What I'm doing is generate a DH key set,
exporting the public and private keys to a pair of blobs, writing them to a
disk file then reading them back in and trying to import them. The import
of the private key is just fine but when I try to import the public key I
get a NTE_BAD_KEY error thrown. Can anyone help me out with this.

Essentially all I'm doing is calling the OnGenerateEncrypKey() and then the
OnImportKey(). When I call the OnImportKey function I select from the
dialog the public key file that was created in the OnGenerateEncrypKey()
call. The eventual goal is to get the public key stored on disk so that I
can distribute it with my software and then use it to decode information
that I have created using the private key. I would like to also have the
private key backed up onto a disk for safety sake. Any help on what I might
be missing here would be a great help.

My code is as follows:

////////////////////////////////////////////////////////////////////////////
/
// CECCRLicenseToolDlg message handlers

BOOL CECCRLicenseToolDlg::OnInitDialog()
{
 CDialog::OnInitDialog();

 // Add "About..." menu item to system menu.

 // IDM_ABOUTBOX must be in the system command range.
 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 ASSERT(IDM_ABOUTBOX < 0xF000);

 CMenu* pSysMenu = GetSystemMenu(FALSE);
 if (pSysMenu != NULL)
 {
  CString strAboutMenu;
  strAboutMenu.LoadString(IDS_ABOUTBOX);
  if (!strAboutMenu.IsEmpty())
  {
   pSysMenu->AppendMenu(MF_SEPARATOR);
   pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  }
 }

 // Set the icon for this dialog. The framework does this automatically
 // when the application's main window is not a dialog
 SetIcon(m_hIcon, TRUE); // Set big icon
 SetIcon(m_hIcon, FALSE); // Set small icon

 // TODO: Add extra initialization here

 m_hCryptProv = NULL;
 m_hExportPubKey = NULL;
 m_hExportPrivKey= NULL;
 m_hSessionKey = NULL;

 // Add the types of License to the combobox.
 CComboBox *pCombo = (CComboBox*)GetDlgItem(IDC_COMBO1);
    pCombo->AddString("SEAT");
 pCombo->AddString("TIME");

 // Set the key display to have EOL automatically inserted.
 CEdit *display = (CEdit *) GetDlgItem(IDC_EDIT6);
 display->FmtLines(true);

 Init();

 return TRUE; // return TRUE unless you set the focus to a control
}
//**************************************************************************
***********************************************
//**************************************************************************
***********************************************
BOOL CECCRLicenseToolDlg::CanExit()
{
 // If the proxy object is still around, then the automation
 // controller is still holding on to this application. Leave
 // the dialog around, but hide its UI.
 if (m_pAutoProxy != NULL)
 {
  ShowWindow(SW_HIDE);
  return FALSE;
 }

 if(m_hCryptProv != NULL)
  CryptReleaseContext(m_hCryptProv, 0);

 return TRUE;
}
//**************************************************************************
***********************************************
// Create a public and private key pair then store them to a file.
void CECCRLicenseToolDlg::OnGenerateEncrypKey()
{
 CString csStr;
 HCRYPTKEY hKey;

 // Now get the key pair for asymetic encryption (AT_KEYEXCHANGE)
 if(!(CryptGenKey(m_hCryptProv,AT_KEYEXCHANGE,CRYPT_EXPORTABLE,&hKey))){
  CryptError("Error trying to create the exchange pair.");
  return;
 }

 ExportAsymKeys(hKey);
}

//**************************************************************************
***********************************************
// Gets the cryptography interface and loads the key pair for this user.
// This Asymetric key set will be used to create the Autherization Code.
bool CECCRLicenseToolDlg::Init()
{
 if(m_hCryptProv != NULL)
  CryptReleaseContext(m_hCryptProv, 0);

 // Get the Diffie-Hellman service provider.
    if(!(CryptAcquireContext(&m_hCryptProv, "ECCR", MS_DEF_DSS_DH_PROV,
PROV_DSS_DH, 0)))
 {
  CryptError("Attempting to create a new key set. ");
  if(!CryptAcquireContext(&m_hCryptProv, "ECCR", MS_DEF_DSS_DH_PROV,
PROV_DSS_DH, CRYPT_NEWKEYSET))
  {
   CryptError("Error getting new keys in the context.");
   return false;
    } }

    return true;
}
//**************************************************************************
***********************************************
// Exports the current keys held by the current crypto provider.
bool CECCRLicenseToolDlg::ExportAsymKeys(HCRYPTKEY hKey)
{
 unsigned long ulPathIndex, ulIndex;
 BYTE *psBuffer;
 DWORD dwKeySize;
 CString csPath,OutputString;

 ASSERT(m_hCryptProv != NULL);

 // Get the destination directory.
 CString strPath("");
 CFileDialog cFile(TRUE, NULL, NULL,
OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST|OFN_LONGNAMES); //
OFN_FILEMUSTEXIST - use to get an existing Key.

 if(cFile.DoModal() == IDOK){
  strPath = cFile.GetPathName();
 }

 // Isolate the path from the file name!
 ulIndex = 0;
 while((ulIndex = strPath.Find('\\',ulIndex)+1) != -1)
 {
  if(strPath.Find('\\',ulIndex) == -1){
   ulPathIndex = ulIndex;
   break;
 } }

 csPath = strPath.Left(ulPathIndex);

 if(!CryptExportKey(hKey,NULL,PUBLICKEYBLOB,0,NULL, &dwKeySize)){
  CryptError("Error getting the length of the Public key.");
  return false;
 }

 psBuffer = new BYTE[dwKeySize];
 if(!CryptExportKey(hKey,NULL,PUBLICKEYBLOB,0,psBuffer, &dwKeySize)){
  CryptError("Error getting the Public key.");
  return false;
 }

 // now store the key to a file.
 CFile publicKey(csPath+"publickey.key",
CFile::modeWrite|CFile::modeCreate);
 publicKey.Write(static_cast<void*> (psBuffer),dwKeySize);
 publicKey.Close();

 // Display the key on screen.
 OutputString += "Public Key:\r\n";
 char *pszPublicKey = new char[2*(dwKeySize+(dwKeySize%30))+1];
 *pszPublicKey = '\0';
 int i=0;

 for(int n=0; n<dwKeySize; n++){
  sprintf(&pszPublicKey[i], "%02x", psBuffer[n]);
  i += 2;
  if((n+1)%30 == 0){
   pszPublicKey[i] = '\r';
   pszPublicKey[i+1]= '\n';
   i += 2;
 } }
 OutputString += pszPublicKey;
 OutputString += "\r\n\r\nPrivate Key:\r\n";

 delete pszPublicKey;
 delete [] psBuffer;

 if(!CryptExportKey(hKey,NULL,PRIVATEKEYBLOB,0,NULL, &dwKeySize)){
  CryptError("Error getting the length of the Private key.");
  return false;
 }

 psBuffer = new BYTE[dwKeySize];
 if(!CryptExportKey(hKey,NULL,PRIVATEKEYBLOB,0,psBuffer, &dwKeySize)){
  CryptError("Error exporting the Private key.");
  return false;
 }
 // now store the key to a file.
 CFile privateKey(csPath+"privatekey.key",
CFile::modeWrite|CFile::modeCreate);
 privateKey.Write(static_cast<void*> (psBuffer),dwKeySize);
 privateKey.Close();
//************************************
 // Display the key on screen.

 pszPublicKey = new char[2*(dwKeySize+(dwKeySize%30))+1];
 *pszPublicKey = '\0';
 i=0;
 for(n=0; n<dwKeySize; n++)
 {
  sprintf(&pszPublicKey[i], "%02x", psBuffer[n]);
  i += 2;
  if((n+1)%30 == 0){
   pszPublicKey[i] = '\r';
   pszPublicKey[i+1]= '\n';
   i += 2;
  }
 }
 OutputString += pszPublicKey;

 delete pszPublicKey;
 delete [] psBuffer;

 SetDlgItemText(IDC_EDIT6,OutputString);
 return true;
}
//**************************************************************************
***********************************************
// Loads a key from the designated file into memory and inputs it to the
current
// crypto provider. If the interface is not initialized it will be using
this key.
bool CECCRLicenseToolDlg::ImportKeys()
{
 // Get the destination directory.
 BYTE *psBuffer;
 DWORD ulKeySize = 0;
 CString strPath("");
 CFileDialog cFile(TRUE, NULL, NULL, OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST);
// OFN_FILEMUSTEXIST - use to get an existing Key.

 // Import the public key from file.
 MessageBox("Select public key source file.");
 if(cFile.DoModal() == IDOK){
  strPath = cFile.GetPathName();
 }

 // now store the key to a file.
 CFile publicKey(strPath, CFile::modeRead);
 ulKeySize = publicKey.GetLength();
 psBuffer = new BYTE[ulKeySize];
 publicKey.ReadHuge(static_cast<void*> (psBuffer),ulKeySize);

 // Because this is not a public private key pair we don't need to worry
about the CRYPT_EXPORTABLE flag!
 if(!CryptImportKey(m_hCryptProv, psBuffer, ulKeySize, NULL, 0,
&m_hExportPubKey)){
  CryptError("Error importing the Public key.");
  delete [] psBuffer;
  return false;
 }
 delete [] psBuffer;

 // Import the private key from file.
 MessageBox("Select private key source file.");
 if(cFile.DoModal() == IDOK){
  strPath = cFile.GetPathName();
 }

 // now store the key to a file.
 CFile privateKey(strPath, CFile::modeRead);
 ulKeySize = privateKey.GetLength();
 psBuffer = new BYTE[ulKeySize];
 publicKey.ReadHuge(static_cast<void*> (psBuffer),ulKeySize);

 if(!CryptImportKey(m_hCryptProv, psBuffer, ulKeySize, NULL,
CRYPT_EXPORTABLE, &m_hExportPubKey)){
  CryptError("Error importing the private key.");
  delete [] psBuffer;
  return false;
 }

 delete [] psBuffer;
 publicKey.Close();
 privateKey.Close();

 return true;
}
//**************************************************************************
***********************************************
void CECCRLicenseToolDlg::OnImport()
{
 ImportKeys();
}
//**************************************************************************
***********************************************
void CECCRLicenseToolDlg::CryptError(CString csMsg)
{
  char sTemp[256];
  DWORD e;

  csMsg += "\n\nERROR: ";
  e = GetLastError();
  switch(e) {
  case NTE_BAD_KEY:
  csMsg += "NTE_BAD_KEY - ";
  break;
  case ERROR_INVALID_HANDLE:
  csMsg += "ERROR_INVALID_HANDLE - ";
  break;
  case ERROR_INVALID_PARAMETER:
  csMsg += "ERROR_INVALID_PARAMETER - ";
  break;
  case ERROR_MORE_DATA:
  csMsg += "ERROR_MORE_DATA - ";
  break;
  case NTE_BAD_FLAGS:
  csMsg += "NTE_BAD_FLAGS - ";
  break;
  case NTE_BAD_KEY_STATE:
  csMsg += "NTE_BAD_KEY_STATE - ";
  break;
  case NTE_BAD_PUBLIC_KEY:
  csMsg += "NTE_BAD_PUBLIC_KEY - ";
     break;
  case NTE_BAD_TYPE:
  csMsg += "NTE_BAD_TYPE - ";
  break;
  case NTE_BAD_UID:
  csMsg += "NTE_BAD_UID - ";
  break;
  case NTE_NO_KEY:
  csMsg += "NTE_NO_KEY - ";
  break;
  default:
  csMsg += "Unknown error - ";
  }
  sprintf(sTemp,"0x%x\n",e);
  csMsg += sTemp;
  MessageBox(csMsg,"Crypto Error",MB_ICONERROR);
}

//**************************************************************************
***********************************************
void CECCRLicenseToolDlg::OnDeleteAllKeys()
{
 CString str;
 HCRYPTKEY hKey;
 DWORD dwRC;

 // Get the Diffie-Hellman service provider.
    if(!(CryptAcquireContext(&m_hCryptProv, "ECCR", MS_DEF_DSS_DH_PROV,
PROV_DSS_DH, CRYPT_DELETEKEYSET)))
  CryptError("Error deleting the key container."); // Display error and
exit.
 else{
  // Reinitialize the context with a new key set.
  if(!CryptAcquireContext(&m_hCryptProv, "ECCR", MS_DEF_DSS_DH_PROV,
PROV_DSS_DH, CRYPT_NEWKEYSET))
   CryptError("Error recreating the container after deletion.");
  MessageBox("The keys have been deleted.");
    }
}



Relevant Pages

  • CryptImportKey NTE_BAD_KEY error.
    ... of the private key is just fine but when I try to import the public key I ... // This Asymetric key set will be used to create the Autherization Code. ... delete psBuffer; ...
    (microsoft.public.platformsdk.security)
  • RE: PGP scripting...
    ... cryptosystems, ... In these systems divulging your private key compromises the public ... Here is a quick over view of the public key encryption routines (the ...
    (SecProg)
  • Re: Private & Public Key storage location
    ... with that you complete the 'certificate' to have both public and private key ... To view the complete cert, you access the cert mmc, ... its end & send only the public key to the CA along with the other websites ... The CA never know the private key of the website. ...
    (microsoft.public.inetserver.iis.security)
  • Re: Private & Public Key storage location
    ... client use the public key to ... corresponds to this certiticate' when you view the cert. ... it will has the private key as well. ... installed for your website, it will be sent to all the clients who connect ...
    (microsoft.public.inetserver.iis.security)
  • Re: How do people write keygens?
    ... it should be well versed on things like public key cryptology - they ... the code with a binary editor, it would seem hard to exploit that. ... Suppose your scheme is that the input is hashed with SHA1, ... however known the list doesn't give you any help about deriving the key set. ...
    (comp.security.misc)