RE: CryptExportKey() NTE_BAD_KEY (80090003) error
- From: lelteto <lelteto@xxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Wed, 11 Apr 2007 08:50:03 -0700
What I see in your Encryption code is that you TWICE export the public key
(same code) but you don't export the session key (which should be exported
using the TARGET's public key). I think you have some fundamental problems
here:
At the encrypt beginning you try to get a user's AT_KEYEXCHANGE key PAIR.
Question: is this the TARGET user or the SENDER? If the sender, than the
whole logic is bad, as you need to get the TARGET's public key - and it's
normally NOT from a container's AT_KEYEXCHANGE, because that container
contains both the public and private key - and the latter should not be
available at the sender side. You should get the target's public key from a
CERTIFICATE (or simply a public key blob - if you trust that blob because of
some out-of-band delivery).
In your code if you don't find the user's AT_KEYEXCHANGE key pair, you
generate a new one. This is bad - unless the sender and the target is always
the SAME user - and even then it will work only if you are decrypting the
file for the SAME computer. (Otherwise you would need to copy the PRIVATE key
blob to the receiving computer, where the private key is used to decrypt the
wrapped session key).
Next, after you generate the random session key you should export the
SESSION KEY - wrapped with the TARGET's public key.
And on the receiving side you need the public key's PRIVATE part (to decrypt
the wrapped session key).
I would recommend you to read some generic crypto book (eg. Bruce Schneier's
Applied Cryptography) to learn how public key systems work: which side is
using private key for what (signing: sender, decrypting: receiver) and who is
using the public key (signature verification: receiver, encrypting: sender).
Laszlo Elteto
SafeNet, Inc.
"Debbrat" wrote:
I tried using PUBLICBLOB with hExpKey set as 0, but it still decrypts on one.
system only and gives the same error NTE_BAD_KEY. I am pasting the
encryption code as well as decryption code. Kindly overlook my previous post
as i pasted decryption code in both encryption and decryption codes.
Encryption:
// enctofile.cpp : Defines the entry point for the console application.
#include "stdafx.h"
// Encrypting_a_File.cpp : Defines the entry point for the console
// application.
#include <tchar.h>
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#include <malloc.h>
#include <winerror.h>
// Link with the Advapi32.lib file.
#pragma comment (lib, "advapi32")
#define KEYLENGTH 0x00800000
#define ENCRYPT_ALGORITHM CALG_RC4
#define ENCRYPT_BLOCK_SIZE 8
LPCWSTR UserName = (LPCWSTR)"bond007";
bool MyEncryptFile(
LPTSTR szSource,
LPTSTR szDestination,
LPTSTR szPassword);
void MyHandleError(
LPTSTR psz,
int nErrorNumber);
int _tmain(int argc, _TCHAR* argv[])
{
LPTSTR pszSource = L"C:\\SourceFile.txt";
LPTSTR pszDestination = L"C:\\DestFile.txt";
LPTSTR pszPassword = NULL;
// Call EncryptFile to do the actual encryption.
if(MyEncryptFile(pszSource, pszDestination, pszPassword))
{
_tprintf(
TEXT("Encryption of the file %s was successful. \n"),
pszSource);
_tprintf(
TEXT("The encrypted data is in file %s.\n"),
pszDestination);
}
else
{
MyHandleError(
TEXT("Error encrypting file!\n"),
GetLastError());
}
return 0;
}
// Code for the function MyEncryptFile called by main.
// Parameters passed are:
// pszSource, the name of the input, a plaintext file.
// pszDestination, the name of the output, an encrypted file to be
// created.
// pszPassword, either NULL if a password is not to be used or the
// string that is the password.
bool MyEncryptFile(
LPTSTR pszSourceFile,
LPTSTR pszDestinationFile,
LPTSTR pszPassword)
{
// Declare and initialize local variables.
bool fReturn = false;
HANDLE hSourceFile = INVALID_HANDLE_VALUE;
HANDLE hDestinationFile = INVALID_HANDLE_VALUE;
HANDLE hpublic = INVALID_HANDLE_VALUE;
HANDLE hprivate = INVALID_HANDLE_VALUE;
LPTSTR pszpublic=_TEXT("c:\\public.txt");
LPTSTR pszprivate=_TEXT("c:\\private.txt");
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
HCRYPTKEY hXchgKey = NULL;
HCRYPTKEY hSignatureKey = NULL;
HCRYPTHASH hHash = NULL;
PBYTE pbKeyBlob = NULL;
PBYTE pbKeyBlobpublic = NULL;
PBYTE pbKeyBlobprivate = NULL;
PBYTE pbKeyBlobatexchange = NULL;
PBYTE pbKeyBlobsignature = NULL;
DWORD dwKeyBlobLen;
PBYTE pbBuffer = NULL;
DWORD dwBlockLen;
DWORD dwBufferLen;
DWORD dwCount;
// Open the source file.
hSourceFile = CreateFile(
pszSourceFile,
FILE_READ_DATA,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(INVALID_HANDLE_VALUE != hSourceFile)
{
_tprintf(
TEXT("The source plaintext file, %s, is open. \n"),
pszSourceFile);
}
else
{
MyHandleError(
TEXT("Error opening source plaintext file!\n"),
GetLastError());
goto Exit_MyEncryptFile;
}
// Open the public file.
hpublic = CreateFile(
pszpublic,
FILE_WRITE_DATA,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(INVALID_HANDLE_VALUE != hpublic)
{
_tprintf(
TEXT("The destination file, %s, is open. \n"),
pszDestinationFile);
}
else
{
MyHandleError(
TEXT("Error opening destination file!\n"),
GetLastError());
goto Exit_MyEncryptFile;
}
// Open the destination file.
hDestinationFile = CreateFile(
pszDestinationFile,
FILE_WRITE_DATA,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(INVALID_HANDLE_VALUE != hDestinationFile)
{
_tprintf(
TEXT("The destination file, %s, is open. \n"),
pszDestinationFile);
}
else
{
MyHandleError(
TEXT("Error opening destination file!\n"),
GetLastError());
goto Exit_MyEncryptFile;
}
// Get the handle to the default provider.
if(!CryptAcquireContext(
&hCryptProv,
UserName,
MS_ENHANCED_PROV,
PROV_RSA_FULL,
0))
{
if(CryptAcquireContext(
&hCryptProv,
UserName,
MS_ENHANCED_PROV,
PROV_RSA_FULL,
CRYPT_NEWKEYSET ))
{
_tprintf(
TEXT("A cryptographic provider has been acquired. \n"));
}
else
{
MyHandleError(
TEXT("Error during CryptAcquireContext!\n"),
GetLastError());
goto Exit_MyEncryptFile;
}
}
CHAR szUserName[100]; // buffer to hold the name
// of the key container
DWORD dwUserNameLen = 100; // length of the buffer
if(CryptGetProvParam(
hCryptProv, // handle to the CSP
PP_CONTAINER, // get the key container name
(BYTE *)szUserName, // pointer to the key container name
&dwUserNameLen, // length of name, preset to 100
0))
{
printf("A crypto context has been acquired and \n");
printf("The name on the key container is %s\n\n",(char*)szUserName);
}
// Create the session key.
// No password was passed.
// Encrypt the file with a random session key, and write the
// key to a file.
// Create a random session key.
if(CryptGenKey(
hCryptProv,
ENCRYPT_ALGORITHM,
KEYLENGTH | CRYPT_EXPORTABLE,
&hKey))
{
_tprintf(TEXT("A session key has been created. \n"));
}
else
{
MyHandleError(
TEXT("Error during CryptGenKey. \n"),
GetLastError());
goto Exit_MyEncryptFile;
}
// Get the handle to the exchange public key.
if(CryptGetUserKey(
hCryptProv,
AT_KEYEXCHANGE,
&hXchgKey))
{
_tprintf(
TEXT("The user public key has been retrieved. \n"));
}
else
{
if(NTE_NO_KEY == GetLastError())
{
// No exchange key exists. Try to create one.
if(!CryptGenKey(
hCryptProv,
AT_KEYEXCHANGE,
CRYPT_EXPORTABLE,
&hXchgKey))
{
MyHandleError(TEXT("Could not create a user public
key.\n"),GetLastError());
goto Exit_MyEncryptFile;
}
}
else
{
MyHandleError(
TEXT("User public key is not available and may ")
TEXT("not exist.\n"),
GetLastError());
goto Exit_MyEncryptFile;
}
}
//exporting the exchange public key
if(CryptExportKey(
hXchgKey,
0,
PUBLICKEYBLOB,
0,
NULL,
&dwKeyBlobLen))
{
_tprintf(
TEXT("The key BLOB is %d bytes long. \n"),
dwKeyBlobLen);
}
else
{
MyHandleError(
TEXT("Error computing BLOB length! \n"),
GetLastError());
goto Exit_MyEncryptFile;
}
if(pbKeyBlobpublic = (BYTE *)malloc(dwKeyBlobLen))
{
_tprintf(
TEXT("Memory is allocated for the key BLOB. \n"));
- Follow-Ups:
- RE: CryptExportKey() NTE_BAD_KEY (80090003) error
- From: Debbrat
- RE: CryptExportKey() NTE_BAD_KEY (80090003) error
- References:
- RE: CryptExportKey() NTE_BAD_KEY (80090003) error
- From: Debbrat
- RE: CryptExportKey() NTE_BAD_KEY (80090003) error
- Prev by Date: Re: Questions about s/mime, CryptEncryptMessage & CryptMsgOpenToEncode
- Next by Date: Re: Smart card GINA replacement log off issue
- Previous by thread: RE: CryptExportKey() NTE_BAD_KEY (80090003) error
- Next by thread: RE: CryptExportKey() NTE_BAD_KEY (80090003) error
- Index(es):
Relevant Pages
|