📄 context.cpp
字号:
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 + -