CryptImportKey NTE_BAD_KEY error.

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

  • Next message: Patty: "hacking"
    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.");
        }
    }


  • Next message: Patty: "hacking"

    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.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)