RE: NTE_BAD_DATA
- From: lelteto <lelteto@xxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Wed, 25 Apr 2007 08:00:00 -0700
You should first understand how public / private keys are used for encryption
/ decryption. They are NOT used DIRECTLY to encrypt / decrypt data; instead,
you should generate a RANDOM SESSION KEY and select a SYMMETRIC ENCRYPTION
ALGO (eg. AES)
- encrypt your data with the session key
- encrypt the session key with the recipient's public key
on the receiving side:
- decrypt the encrypted session key with the private key and recover the
session key
- decrypt the data with the session key
What your code does is trying to encrypt data directly with the public key
and decrypt it with the private key. It's not only bad (and not supported by
CAPI) but would be awfully slow for large data.
So here what you should change:
1. use CryptGenKey to generate a session key
2. use CryptExportKey to encrypt (wrap) the session key with the public key
3. save the size + KEYBLOB as the first data of your output file.
4. encrypt the input data file with the session key
on the receiving side:
1. read the blob from the beginning of the file
2. use CryptImportKey (with the private key) to import the session key
3. decrypt the rest of the data file using the imported session key
Read up a bit more on encryption and cryptography. One highly recommended
book is Bruce Scheier's Applied Cryptography. From that you hopefully will
understand how crypto works and will start to use it in the correct way.
Laszlo Elteto
SafeNet, Inc.
"sunil" wrote:
Hi ,.
I am trying to my hard against developing a simple encryption and
decryption module using the self signed certificate. I am getting the
error of NTE_BAD_DATA in the decryption module.
Please help to debug my problem
My encryption and decryption module are as follows. I am not using the
password in the following code.
DECRYPTION CODE
------------------------------------------------------------------------------------------------------------------------
#define KEYLENGTH 0x00800000
#define ENCRYPT_ALGORITHM CALG_RC4
#define ENCRYPT_BLOCK_SIZE 8
#define CERT_SUBJECT_NAME "abc"
LPCTSTR UserName=(LPCTSTR)"bond007";
int _tmain(int argc, _TCHAR* argv[])
{
if(argc < 3)
{
_tprintf(TEXT("Usage: <example.exe> <source file> ")
TEXT("<destination file> | <password>\n"));
_tprintf(TEXT("<password> is optional.\n"));
_tprintf(TEXT("Press any key to exit."));
_gettch();
return 1;
}
LPTSTR pszSource = argv[1];
LPTSTR pszDestination = argv[2];
if(MyDecryptFile(pszSource, pszDestination))
{
_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 MyDecryptFile called by main.
bool MyDecryptFile(LPTSTR pszSourceFile, LPTSTR pszDestinationFile)
{
//---------------------------------------------------------------
// Declare and initialize local variables.
bool fReturn = false;
HANDLE hSourceFile = INVALID_HANDLE_VALUE;
HANDLE hDestinationFile = INVALID_HANDLE_VALUE;
HCRYPTKEY hKey = NULL;
HCRYPTPROV hCryptProv = NULL;
DWORD dwCount;
PBYTE pbBuffer = NULL;
DWORD dwBlockLen;
DWORD dwBufferLen;
//---------------------------------------------------------------
// 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 encrypted file, %s, is open. \n"),
pszSourceFile);
}
else
{
MyHandleError(TEXT("Error opening source plaintext file!\n"),
GetLastError());
goto Exit_MyDecryptFile;
}
//---------------------------------------------------------------
// 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_MyDecryptFile;
}
HCERTSTORE hSystemStore; // The system store handle.
PCCERT_CONTEXT pDesiredCert = NULL; // Set to NULL for the first
// call to
// CertFindCertificateInStore.
CERT_NAME_BLOB SubjNameBlob;
DWORD cbNameEncoded;
BYTE* pbNameEncoded;
CRYPT_BIT_BLOB pubkey;
//-------------------------------------------------------------------
// Declare and initialize variables
// Declare and initialize a CERT_RDN_ATTR array.
// In this code, only one array element is used.
CERT_RDN_ATTR rgNameAttr[] = {
"2.5.4.3", // pszObjId
CERT_RDN_PRINTABLE_STRING, // dwValueType
strlen(CERT_SUBJECT_NAME), // value.cbData
(BYTE*)CERT_SUBJECT_NAME}; // value.pbData
//-------------------------------------------------------------------
// Declare and initialize a CERT_RDN array.
// In this code, only one array element is used.
CERT_RDN rgRDN[] = {
1, // rgRDN[0].cRDNAttr
&rgNameAttr[0]}; // rgRDN[0].rgRDNAttr
//-------------------------------------------------------------------
// Declare and initialize a CERT_NAME_INFO structure.
CERT_NAME_INFO Name = {
1, // Name.cRDN
rgRDN}; // Name.rgRDN
//-------------------------------------------------------------------
// Begin processing.
if(CryptEncodeObject(
X509_ASN_ENCODING, // Encoding type
X509_NAME, // Structure type
&Name, // Address of CERT_NAME_INFO structure
NULL, // pbEncoded
&cbNameEncoded)) // pbEncoded size
{
printf("The first call to CryptEncodeObject succeeded. \n");
}
else
{
printf("The first call to CryptEncodeObject failed. \n");
}
//-------------------------------------------------------------------
// Allocate memory for the encoded name.
if(!(pbNameEncoded = (BYTE*)malloc(cbNameEncoded)))
printf("pbNamencoded malloc operation failed.\n");
//-------------------------------------------------------------------
// Call CryptEncodeObject to do the actual encoding of the name.
if(CryptEncodeObject(
X509_ASN_ENCODING, // Encoding type
X509_NAME, // Structure type
&Name, // Address of CERT_NAME_INFO structure
pbNameEncoded, // pbEncoded
&cbNameEncoded)) // pbEncoded size
{
printf("The object is encoded. \n");
}
else
{
free(pbNameEncoded);
printf("Second call to CryptEncodeObject failed.\n");
}
//-------------------------------------------------------------------
// Set the subject member of CertReqInfo to point to
// a CERT_NAME_INFO structure that
// has been initialized with the data from cbNameEncoded
// and pbNameEncoded.
SubjNameBlob.cbData = cbNameEncoded;
SubjNameBlob.pbData = pbNameEncoded;
//-------------------------------------------------------------------
// Open the certificate store to be searched.
if(hSystemStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
X509_ASN_ENCODING, // Encoding type
NULL, // Accept the default HCRYPTPROV.
CERT_SYSTEM_STORE_CURRENT_USER,
// Set the system store location in the
registry.
L"MY")) // system stores including Trust, CA, or
Root.
{
printf("Opened the MY system store. \n");
}
else
{
printf( "Could not open the MY system store.\n");
exit(1);
}
//-------------------------------------------------------------------
// Get a certificate that has lpszCertSubject as its
// subject.
if(pDesiredCert=CertFindCertificateInStore(
hSystemStore,
X509_ASN_ENCODING, // Use X509_ASN_ENCODING.
0, // No dwFlags needed.
CERT_FIND_SUBJECT_NAME, // Find a certificate with a
// subject that matches the string
// in the next parameter.
&SubjNameBlob, // The Unicode string to be found
// in a certificate's subject.
NULL)) // NULL for the first call to the
// function. In all subsequent
// calls, it is the last pointer
// returned by the function.
{
printf("The desired certificate was found. \n");
}
else
{
printf("Could not find the desired certificate.\n");
}
DWORD dwKeySpec;
BOOL fCallerFreeProv;
if(CryptAcquireCertificatePrivateKey(
pDesiredCert,
CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
NULL,
&hCryptProv,
&dwKeySpec,
&fCallerFreeProv
))
{
if(CryptGetUserKey(
hCryptProv,
AT_KEYEXCHANGE,
&hKey))
{
_tprintf(TEXT("got the key handle"));
}
else
{
MyHandleError(TEXT("Error during CryptGetUserKey\n"),
GetLastError());
goto Exit_MyDecryptFile;
}
}
else
{
MyHandleError(TEXT("Error during CryptAcquireCertificatePrivateKey
\n"), GetLastError());
goto Exit_MyDecryptFile;
}
//---------------------------------------------------------------
// The decryption key is now available, either having been
// imported from a BLOB read in from the source file or having
// been created by using the password. This point in the program
// is not reached if the decryption key is not available.
//---------------------------------------------------------------
// Determine the number of bytes to decrypt at a time.
// This must be a multiple of ENCRYPT_BLOCK_SIZE.
dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
dwBufferLen = dwBlockLen;
//---------------------------------------------------------------
// Allocate memory for the file read buffer.
if(!(pbBuffer = (PBYTE)malloc(dwBufferLen)))
{
MyHandleError(TEXT("Out of memory!\n"), E_OUTOFMEMORY);
goto Exit_MyDecryptFile;
}
//---------------------------------------------------------------
// Decrypt the source file, and write to the destination file.
bool fEOF = false;
do
{
//-----------------------------------------------------------
// Read up to dwBlockLen bytes from the source file.
if(!ReadFile(
hSourceFile,
pbBuffer,
dwBlockLen,
&dwCount,
NULL))
{
MyHandleError(
TEXT("Error reading from source file!\n"),
GetLastError());
goto Exit_MyDecryptFile;
}
if(dwCount < dwBlockLen)
{
fEOF = TRUE;
}
//-----------------------------------------------------------
// Decrypt the block of data.
if(!CryptDecrypt(
- Follow-Ups:
- RE: NTE_BAD_DATA
- From: Pranay
- RE: NTE_BAD_DATA
- References:
- NTE_BAD_DATA
- From: sunil
- NTE_BAD_DATA
- Prev by Date: developping a credential provider : password expired
- Next by Date: SmartCard Verify
- Previous by thread: NTE_BAD_DATA
- Next by thread: RE: NTE_BAD_DATA
- Index(es):
Relevant Pages
|
|