⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 context.cpp

📁 基于SD卡的软实现CSP程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	Same as CP* (See MSDN).  Context parameter missing
	as the context is the current object (this ptr).

	Note we simply pass this through to our RSA base provider.

Params:
	ALG_ID Algid: See MSDN
	HCRYPTHASH hBaseData: See MSDN
	DWORD dwFlags: See MSDN
	HCRYPTKEY* phKey: See MSDN

Returns:
	BOOL : See MSDN
*/
BOOL CContext::DeriveKey(ALG_ID Algid, HCRYPTHASH hBaseData, DWORD dwFlags, HCRYPTKEY* phKey)
{
	return CryptDeriveKey(m_rsaProv, Algid, hBaseData, dwFlags, phKey);
}


/*
CContext::DestroyKey
Purpose: 
	Same as CP* (See MSDN).  Context parameter missing
	as the context is the current object (this ptr).

	Note we simply pass this through to our RSA base provider.

Params:
	HCRYPTKEY hKey: See MSDN

Returns:
	BOOL : See MSDN
*/
BOOL CContext::DestroyKey(HCRYPTKEY hKey)
{
	return CryptDestroyKey(hKey);
}


/*
CContext::DuplicateKey
Purpose: 
	Same as CP* (See MSDN).  Context parameter missing
	as the context is the current object (this ptr).

Params:
	HCRYPTKEY hKey: See MSDN
	DWORD* pdwReserved: See MSDN
	DWORD dwFlags: See MSDN
	HCRYPTKEY* phKey: See MSDN

Returns:
	BOOL : See MSDN
*/
BOOL CContext::DuplicateKey(HCRYPTKEY hKey, DWORD* pdwReserved, DWORD dwFlags, HCRYPTKEY* phKey)
{
	//The hKey passed in is the one we returned before which is a
	//valid one from our RSA provider...pass it along.
	return CryptDuplicateKey(hKey, pdwReserved, dwFlags, phKey);
}


/*
CContext::ImportKey
Purpose: 
	Same as CP* (See MSDN).  Context parameter missing
	as the context is the current object (this ptr).

Params:
	CONST BYTE* pbData: See MSDN
	DWORD dwDataLen: See MSDN
	HCRYPTKEY hPubKey: See MSDN
	DWORD dwFlags: See MSDN
	HCRYPTKEY* phKey: See MSDN

Returns:
	BOOL : See MSDN
*/
BOOL CContext::ImportKey(BYTE* pbData, DWORD dwDataLen, HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY* phKey)
{
	//Simple check on the pointer passed in.
	if(!pbData)
	{
		SetLastError(NTE_FAIL);
		return FALSE;
	}

	//If it's a PUBLICKEYBLOB import it into the base provider.
	LPSESSIONKEYHEADER pskh = (LPSESSIONKEYHEADER)pbData;
	if(PUBLICKEYBLOB == pskh->blobHeader.bType || !hPubKey)
	{
		PUBLICKEYSTRUC* pks = (PUBLICKEYSTRUC*)pbData;
		DWORD pubBlobSize = 148;
		if((pks->aiKeyAlg == CALG_RSA_KEYX || pks->aiKeyAlg == CALG_RSA_SIGN) && dwDataLen > pubBlobSize)
		{
			BYTE* publicKeyBlob = new BYTE[pubBlobSize];
			memcpy(publicKeyBlob,pbData,pubBlobSize);
			RSAPUBKEY* rp = (RSAPUBKEY*)(publicKeyBlob + sizeof(PUBLICKEYSTRUC));
			rp->magic = 0x31415352;
			m_crd.StoreKey(m_pCurrentContainer,pks->aiKeyAlg,pbData,dwDataLen,publicKeyBlob,pubBlobSize);
			ALG_ID aid;
			if(pks->aiKeyAlg == CALG_RSA_SIGN)
				aid = AT_SIGNATURE;
			else
				aid = AT_KEYEXCHANGE;
			m_pCurrentContainer->SetCachedCert(aid,publicKeyBlob,pubBlobSize);
		}
		return CryptImportKey(m_rsaProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
	}

	//We need our private key for this operation, so we need a container.
	if(!m_pCurrentContainer ||
		(m_dwFlags & CRYPT_VERIFYCONTEXT) == CRYPT_VERIFYCONTEXT)
	{
		SetLastError(NTE_PERM);
		return FALSE;
	}

	//If it's not a SIMPLEBLOB we don't know what to do with it.
	if(SIMPLEBLOB != pskh->blobHeader.bType)
	{
		SetLastError(NTE_BAD_TYPE);
		return FALSE;
	}

	//It's a simple blob.
	assert(SIMPLEBLOB == pskh->blobHeader.bType);

	//We only know how to deal with RSA keys.
	if(CALG_RSA_KEYX != pskh->algid)
	{
		SetLastError(NTE_BAD_TYPE);
		return FALSE;
	}

	BOOL bRet = FALSE;

	//Wrapped blob size.
	DWORD wEncryptedDataLength = (DWORD)(dwDataLen - sizeof(SESSIONKEYHEADER));
	BYTE* pKeySource = pbData + sizeof(SESSIONKEYHEADER);
	BYTE* pbyDecryptedData = new BYTE[wEncryptedDataLength];
	DWORD wDecryptedDataLength = wEncryptedDataLength;

	ALG_ID algid;
	DWORD dwAlgIDLen = sizeof(ALG_ID);

	if(!pbyDecryptedData)
	{
		SetLastError(NTE_FAIL);
		goto cleanup;
	}

	if(!CryptGetKeyParam(hPubKey, KP_ALGID, (BYTE*)&algid,&dwAlgIDLen ,0))
		goto cleanup;

	assert(m_pCurrentContainer);
	if(!m_pCurrentContainer->Decrypt(algid, pKeySource, wEncryptedDataLength, pbyDecryptedData, &wDecryptedDataLength))
		goto cleanup;

	/*DWORD dwLen = sizeof(SESSIONKEYIMPORTBLOB);
	BYTE* bCopy = pbData + dwLen;
	HCRYPTKEY internalKey;
	CryptGetUserKey(m_rsaProv,AT_KEYEXCHANGE,&internalKey);
	CryptEncrypt(internalKey,0,TRUE,0,pbyDecryptedData,wDecryptedDataLength,0x80);
	CryptImportKey(m_rsaProv,pbData,dwDataLen,internalKey,dwFlags,phKey);*/

	SESSIONKEYIMPORTBLOB SessionKeyImportBlob;
	SessionKeyImportBlob.keyHeader.blobHeader.bType = SIMPLEBLOB;
	SessionKeyImportBlob.keyHeader.blobHeader.bVersion = CUR_BLOB_VERSION;
	SessionKeyImportBlob.keyHeader.blobHeader.reserved = 0x00;
	SessionKeyImportBlob.keyHeader.blobHeader.aiKeyAlg = pskh->blobHeader.aiKeyAlg;
	SessionKeyImportBlob.keyHeader.algid = CALG_RSA_KEYX;

	memset(&SessionKeyImportBlob.encryptedKey[0], 0xFF, sizeof(SessionKeyImportBlob.encryptedKey));
	
	memcpy(&SessionKeyImportBlob.encryptedKey[0], pbyDecryptedData, wDecryptedDataLength);
	SessionKeyImportBlob.encryptedKey[wDecryptedDataLength] = 0;
	SessionKeyImportBlob.encryptedKey[sizeof(SessionKeyImportBlob.encryptedKey) - 2] = 0x02;
	SessionKeyImportBlob.encryptedKey[sizeof(SessionKeyImportBlob.encryptedKey) - 1] = 0x00;
	
	
	if(!CryptImportKey(m_rsaProv, (BYTE*)&SessionKeyImportBlob, sizeof(SESSIONKEYIMPORTBLOB), 0, dwFlags, phKey))
	{
		printf("Import Key error with code %d.\n",GetLastError());
		goto cleanup;
	}

	bRet = TRUE;

cleanup:
	if(pbyDecryptedData)
		delete [] pbyDecryptedData;

	return bRet;
}


/*
CContext::ExportKey
Purpose: 
	Same as CP* (See MSDN).  Context parameter missing
	as the context is the current object (this ptr).

	Note we simply pass this through to our RSA base provider.

Params:
	HCRYPTKEY hKey: See MSDN
	HCRYPTKEY hPubKey: See MSDN
	DWORD dwBlobType: See MSDN
	DWORD dwFlags: See MSDN
	BYTE* pbData: See MSDN
	DWORD* pdwDataLen: See MSDN

Returns:
	BOOL : See MSDN
*/
BOOL CContext::ExportKey(HCRYPTKEY hKey, HCRYPTKEY hPubKey, DWORD dwBlobType, DWORD dwFlags, BYTE* pbData, DWORD* pdwDataLen)
{
	return CryptExportKey(hKey, hPubKey, dwBlobType, dwFlags, pbData, pdwDataLen);
}


/*
CContext::GenKey
Purpose: 
	Same as CP* (See MSDN).  Context parameter missing
	as the context is the current object (this ptr).

Params:
	ALG_ID algid: See MSDN
	DWORD dwFlags: See MSDN
	HCRYPTKEY* phKey: See MSDN

Returns:
	BOOL : See MSDN
*/
BOOL CContext::GenKey(ALG_ID algid, DWORD dwFlags, HCRYPTKEY* phKey)
{
	*phKey = NULL;

	//Get the key strength from the flags
	DWORD dwKeySize=HIWORD(dwFlags);

	//If no key size, use maximum key size available.
	if(0 == dwKeySize) m_rsaProv.GetMaxKeySize(dwKeySize);

	//If we don't know about that kind of key, pass it along
	//to our base provider
	if(AT_SIGNATURE != algid && AT_KEYEXCHANGE != algid)
	{
		return CryptGenKey(m_rsaProv, algid, dwFlags, phKey);
	}

	//Verify Contexts cannot generate keys.
	if(!m_pCurrentContainer || 
		(m_dwFlags & CRYPT_VERIFYCONTEXT) == CRYPT_VERIFYCONTEXT)
	{
		SetLastError(NTE_PERM);
		return FALSE;
	}
	BOOL bResult = FALSE;

	HCRYPTKEY hGenKey = NULL;
	DWORD dwGenKeyFlags = HIWORD(dwKeySize)|CRYPT_EXPORTABLE;
	DWORD dwPrivateBlobSize = 0;
	BYTE* pbyPrivateKey = NULL;
	BYTE* pbyPublicKey = NULL;
	DWORD dwPublicBlobSize = 0;

	//Generate the key
	if(!CryptGenKey(m_rsaProv, algid, dwGenKeyFlags, &hGenKey))
		goto cleanup;

	//Export the private key
	CryptExportKey(hGenKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPrivateBlobSize);

	pbyPrivateKey = new BYTE[dwPrivateBlobSize];
	if(!pbyPrivateKey) goto cleanup;

	if(!CryptExportKey(hGenKey, NULL, PRIVATEKEYBLOB, 0, pbyPrivateKey, &dwPrivateBlobSize))
		goto cleanup;

	//Export the public key
	CryptExportKey(hGenKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwPublicBlobSize);

	pbyPublicKey = new BYTE[dwPublicBlobSize];
	if(!pbyPublicKey) goto cleanup;

	if(!CryptExportKey(hGenKey, NULL, PUBLICKEYBLOB, 0, pbyPublicKey, &dwPublicBlobSize))
		goto cleanup;

	//Write keys to smart card
	if(!m_crd.StoreKey(m_pCurrentContainer, algid, pbyPrivateKey, 
				dwPrivateBlobSize, pbyPublicKey, dwPublicBlobSize))
		goto cleanup;

	// Cache the public key here.
	m_pCurrentContainer->SetCachedCert(algid,pbyPublicKey,dwPublicBlobSize);


	//Re-import just the public key 
	//(we only want the private key on the card and no where else).
	if(!CryptImportKey(m_rsaProv, pbyPublicKey, dwPublicBlobSize, NULL, 
				CRYPT_EXPORTABLE,phKey))
	{
		goto cleanup;
	}

	//Success!
	bResult = TRUE;

cleanup:

	if(hGenKey)
	{
		CryptDestroyKey(hGenKey);

	}

	if(pbyPrivateKey) 
	{
		//Clear the private key out of memory.
		RtlSecureZeroMemory(pbyPrivateKey, dwPrivateBlobSize);
		delete [] pbyPrivateKey;
		EraseKeyFromContainer(algid);
	}

	if(pbyPublicKey) delete [] pbyPublicKey;

	if(!bResult) SetLastError(NTE_FAIL);

	return bResult;
}


/*
CContext::GetKeyParam
Purpose: 
	Same as CP* (See MSDN).  Context parameter missing
	as the context is the current object (this ptr).

	Note we simply pass this through to our RSA base provider.

Params:
	HCRYPTKEY hKey: See MSDN
	DWORD dwParam: See MSDN
	BYTE* pbData: See MSDN
	DWORD* pdwDataLen: See MSDN
	DWORD dwFlags: See MSDN

Returns:
	BOOL : See MSDN
*/
BOOL CContext::GetKeyParam(HCRYPTKEY hKey, DWORD dwParam, BYTE* pbData, DWORD* pdwDataLen, DWORD dwFlags)
{
	//If we're after the certificate...
	if(KP_CERTIFICATE == dwParam)
	{
		ALG_ID algid;
		DWORD dwAlgIDLen = sizeof(algid);
		if(!m_pCurrentContainer)
			return FALSE;
		if(!CryptGetKeyParam(hKey, KP_ALGID, (BYTE*)&algid, &dwAlgIDLen,0))
			return FALSE;
		if(dwAlgIDLen != sizeof(algid))
			return FALSE;
		if(!m_pCurrentContainer->GetCertificate(algid, pbData, pdwDataLen))
			return FALSE;
		return TRUE;
	}
	return CryptGetKeyParam(hKey, dwParam, pbData, pdwDataLen, dwFlags);
}


/*
CContext::SetKeyParam
Purpose: 
	Same as CP* (See MSDN).  Context parameter missing
	as the context is the current object (this ptr).

Params:
	HCRYPTKEY hKey: See MSDN
	DWORD dwParam: See MSDN
	BYTE*pbData: See MSDN
	DWORD dwFlags: See MSDN

Returns:
	BOOL : See MSDN
*/
BOOL CContext::SetKeyParam(HCRYPTKEY hKey, DWORD dwParam, BYTE*pbData, DWORD dwFlags)
{
	switch(dwParam)
	{
	case KP_CERTIFICATE:
		{
			//Get the length of the certificate
			DWORD dwCertLength;
			ALG_ID algid;
			DWORD dwAlgIDLen = sizeof(algid);
			if(!GetAsnLength(pbData, dwCertLength))
				return FALSE;
			if(!m_pCurrentContainer)
				return FALSE;
			if(!CryptGetKeyParam(hKey, KP_ALGID, (BYTE*)&algid, &dwAlgIDLen,0))
				return FALSE;
			if(dwAlgIDLen != sizeof(algid))
				return FALSE;
			if(!m_pCurrentContainer->SetCertificate(algid, pbData, dwCertLength))
				return FALSE;
			return TRUE;
		}

	//We don't do anything with the ADMIN_PIN...
	case KP_ADMIN_PIN:
		SetLastError(NTE_BAD_KEY);
		return FALSE;

	//ASCII string to remain consistent with desktop CSP even though
	//0 is a valid PIN byte.
	case KP_KEYEXCHANGE_PIN:
	case KP_SIGNATURE_PIN:
		m_crd.SetUserPin(pbData, strlen((char*)pbData));
		return TRUE;
	}

	//Pass it off to our base provider if we don't know what to do.
	return CryptSetKeyParam(hKey, dwParam, pbData, dwFlags);
}


/*
CContext::GetUserKey
Purpose: 
	Same as CP* (See MSDN).  Context parameter missing
	as the context is the current object (this ptr).

Params:
	DWORD dwKeySpec: See MSDN
	HCRYPTKEY* phUserKey: See MSDN

Returns:
	BOOL : See MSDN
*/
BOOL CContext::GetUserKey(DWORD dwKeySpec, HCRYPTKEY* phUserKey)
{
	if (!m_pCurrentContainer)
	{
		SetLastError(NTE_NO_KEY);
		return FALSE;
	}

	if(AT_SIGNATURE != dwKeySpec 
		&& AT_KEYEXCHANGE != dwKeySpec)
	{
		SetLastError(NTE_BAD_KEY);
		return FALSE;
	}

	return m_pCurrentContainer->GetPublicKey(m_rsaProv, dwKeySpec, phUserKey);
}

/*
CContext::GenRandom
Purpose: 
	Same as CP* (See MSDN).  Context parameter missing
	as the context is the current object (this ptr).

	Note we simply pass this through to our RSA base provider.

Params:
	DWORD dwLen: See MSDN
	BYTE* pbBuffer: See MSDN

Returns:
	BOOL : See MSDN
*/
BOOL CContext::GenRandom(DWORD dwLen, BYTE* pbBuffer)
{
	return CryptGenRandom(m_rsaProv, dwLen, pbBuffer);
}


/*
CContext::GetAsnLength
Purpose:
	Returns the length of an ASN blob

Params:
	BYTE* pbyASNData: The ASN blob
	DWORD& dwLength: Set to the length of the blob at the end of the function

Returns:
	true if it succeeds, false otherwise
*/
bool CContext::GetAsnLength(BYTE* pbyASNData, DWORD& dwLength)
{
	// First byte should be 0x30.
	if (*pbyASNData != 0x30)
	{
		assert(0); // Make sure this is a correctly encoded object.
		return false;
	}

	//Find the length field
	dwLength=2; // Skip the Header, and the length feild.
	++pbyASNData;

	// Next byte should have the length, or tell us how many 
	// bytes will be in the length.
	if((*pbyASNData & ASN1_LONG_LENGTH) == ASN1_LONG_LENGTH)
	{
		//Get the number of bytes in the length
		DWORD dwSubFieldLength = (*pbyASNData++ & ASN1_LONG_LENGTH_BYTES);
		if(dwSubFieldLength > 4) return false;

		dwLength += dwSubFieldLength;

		//Get the number of bytes following the bytes in the length
		DWORD dwSubLength = 0;
		for(BYTE byIndex = 0; byIndex < dwSubFieldLength; ++byIndex)
		{
			dwSubLength <<= 8;
			DWORD dwCurrentValue = pbyASNData[byIndex];
			ASSERT(!(dwCurrentValue & dwSubLength)); // Make sure we're not overwritting existing data
			dwSubLength |= dwCurrentValue;
		}

		//Will we CF (overflow the DWORD?)
		if(0xFFFFFFFF - dwSubLength < dwLength)
			return false;

		dwLength += dwSubLength;
	}
	else
	{
		dwLength += *pbyASNData; 
	}
	return true;
}

// Problem :  We create a key in the rsa provider, and don't have a 
// way to delete it . Solution - Import a key over it.
// Thus EraseKeyFromContainer - Will import a key into the container
// overwriting the existing generated key.
BOOL CContext::EraseKeyFromContainer( ALG_ID algid) 
{
	// The PrivateKey starts with a blobheader.
	BLOBHEADER *bh =  (BLOBHEADER*)m_pbPrivKey;
	HCRYPTKEY hTmpKey=0;
	ASSERT( CALG_RSA_KEYX == bh->aiKeyAlg  ||  CALG_RSA_KEYX == bh->aiKeyAlg );

	//  We need to change the algId depending on keyexchange or signature.
	if (AT_SIGNATURE == algid)
	{
		bh->aiKeyAlg  = CALG_RSA_SIGN; 
	}
	else if (AT_KEYEXCHANGE == algid)
	{
		bh->aiKeyAlg  = CALG_RSA_KEYX; 
	}
	else
	{
		ASSERT( (AT_SIGNATURE  == algid) || (AT_KEYEXCHANGE == algid));
	}

	// Import a new Key to overwrite that generated privateKey.
	if(!CryptImportKey(m_rsaProv, m_pbPrivKey, m_dwPrivKeySize,0,
	CRYPT_EXPORTABLE,&hTmpKey))
	{
		assert(0);
	}
	// Destroy the key handle.
	if (hTmpKey) CryptDestroyKey(hTmpKey);
	return true;
}
// The Private key used when erasing the generating the key.
DWORD CContext::m_dwPrivKeySize =236;
BYTE CContext::m_pbPrivKey[236] = 
{ // 15 * 15 + 11
0x07,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x32,0x80,0x01,0x00,
0x00,0x01,0x00,0x01,0x00,0xb3,0x16,0x00,0xbc,0x94,0x6a,0x91,0xf5,0x72,0xdc,
0xba,0xc6,0xa5,0xea,0xdb,0xc7,0x69,0x13,0xbd,0x55,0x38,0x25,0x6f,0xa7,0x06,
0x96,0xf2,0x50,0xf8,0x3e,0x5c,0x6c,0x32,0x64,0x6c,0xc7,0xa1,0x3b,0xbb,0xb0,
0x52,0x4b,0x11,0x81,0x63,0x7b,0x4a,0xa9,0x59,0x05,0xd9,0x2f,0xcc,0xd7,0x1b,
0xcf,0xb8,0x84,0xd5,0xc3,0xe9,0xa7,0x83,0x7f,0x01,0x26,0x35,0x3a,0x54,0x48,
0x47,0xdb,0xeb,0xde,0xad,0x00,0x2e,0xfd,0x13,0x04,0x0f,0x8a,0xb8,0x9d,0x58,
0x32,0xe1,0xf2,0x25,0xb6,0xdc,0x10,0x9b,0x2d,0xa4,0xc5,0xd1,0xb7,0xc7,0xac,
0x86,0xda,0x13,0x0b,0x19,0x39,0x25,0x34,0xc8,0x6d,0xda,0xb0,0x76,0xe0,0xe2,
0x8a,0x83,0xdc,0x0e,0x23,0xdf,0x81,0xc6,0xec,0xbf,0x7d,0x32,0xca,0x55,0x76,
0x88,0x78,0xe6,0x77,0x58,0x9a,0x2b,0x8c,0x09,0x37,0x63,0xe3,0xd0,0xb1,0x18,
0x16,0xca,0xf5,0xf4,0x75,0xfa,0xe7,0xd8,0x1e,0xad,0x7f,0x81,0x43,0xe3,0xe8,
0x3f,0xff,0x85,0x46,0x46,0xb4,0xd4,0x91,0xf1,0x1b,0x3c,0x2c,0xc8,0x3a,0x11,
0xa9,0x62,0x77,0x07,0x40,0xef,0xd6,0x5e,0xb2,0x17,0xa2,0x4f,0xc4,0x5d,0x16,
0x19,0xdf,0x7f,0x61,0x17,0x7b,0x50,0xc2,0x49,0xbd,0xa7,0x92,0x34,0xbc,0x29,
0x95,0x00,0x22,0x2e,0x25,0x79,0xcd,0xc2,0xe,0xb5,0x07
}; 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -