대량 암호화 및 MAC 키마스터 키 파생되지만 사용되는 프로토콜 및 암호 도구 모음에 따라 다른 원본을 포함할 수 있습니다.
대량 암호화 및 MAC 키를 파생시키는 프로세스는 클라이언트와 서버 모두에서 동일합니다.
- 프로토콜 엔진은 마스터 키에 CryptSetKeyParam 한 번 이상 호출하여 CSP에 키를 빌드하는 데 필요한 정보를 제공합니다.
- CryptoAPI 키는 다른 키에서 직접 파생될 수 없으므로 CryptCreateHash사용하여 마스터 키에서 해시 개체를 만듭니다. 이 해시 새 키를 만드는 데 사용됩니다.
- 두 개의 대량 암호화 키와 두 개의 MAC 키는 CryptDeriveKey대한 네 가지 호출을 사용하여 "마스터 해시" 개체에서 만들어집니다.
메모
SSL 다시 연결 수행 시 프로토콜 엔진은 동일한 마스터 키를 사용하여 위의 절차를 여러 번 수행할 수 있습니다. 이렇게 하면 클라이언트와 서버가 각각 다른 대량 암호화 및 MAC 키를 사용하여 추가 RSA 또는 Diffie-Hellman 작업 없이 여러 동시 연결을 가질 수 있습니다.
모든 CSP는 스레드 안전한 방법을 사용해야 합니다. 수십 개의 스레드 수는 드문 일이 아닙니다.
다음은 프로토콜 엔진에 대한 일반적인 소스 코드입니다.
//--------------------------------------------------------------------
// Define and initialize local variables.
BOOL fClient = <TRUE if this is code for the client?>;
CRYPT_DATA_BLOB Data;
HCRYPTHASH hMasterHash;
//--------------------------------------------------------------------
// Finish creating the master_secret.
switch(<protocol being used>)
{
case <PCT 1.0>:
//------------------------------------------------------------
// Specify clear key value.
Data.pbData = pClearKey;
Data.cbData = cbClearKey;
CryptSetKeyParam(
hMasterKey,
KP_CLEAR_KEY,
(PBYTE)&Data,
0);
//------------------------------------------------------------
// Specify the CH_CHALLENGE_DATA.
Data.pbData = pChallenge;
Data.cbData = cbChallenge;
CryptSetKeyParam(
hMasterKey,
KP_CLIENT_RANDOM,
(PBYTE)&Data,
0);
//------------------------------------------------------------
// Specify the SH_CONNECTION_ID_DATA.
Data.pbData = pConnectionID;
Data.cbData = cbConnectionID;
CryptSetKeyParam(
hMasterKey,
KP_SERVER_RANDOM,
(PBYTE)&Data,
0);
//------------------------------------------------------------
// Specify the SH_CERTIFICATE_DATA.
Data.pbData = pbServerCertificate;
Data.cbData = cbServerCertificate;
CryptSetKeyParam(
hMasterKey,
KP_CERTIFICATE,
(PBYTE)&Data,
0);
break;
case <SSL 2.0>:
//------------------------------------------------------------
// Specify clear key value.
Data.pbData = pClearKey;
Data.cbData = cbClearKey;
CryptSetKeyParam(
hMasterKey,
KP_CLEAR_KEY,
(PBYTE)&Data,
0);
//------------------------------------------------------------
// Specify the CH_CHALLENGE_DATA.
Data.pbData = pChallenge;
Data.cbData = cbChallenge;
CryptSetKeyParam(
hMasterKey,
KP_CLIENT_RANDOM,
(BYTE*)&Data,
0);
//------------------------------------------------------------
// Specify the SH_CONNECTION_ID_DATA.
Data.pbData = pConnectionID;
Data.cbData = cbConnectionID;
CryptSetKeyParam(
hMasterKey,
KP_SERVER_RANDOM,
(BYTE*)&Data,
0);
break;
case <SSL 3.0>:
case <TLS 1.0>:
//------------------------------------------------------------
// Specify client_random.
Data.pbData = pClientRandom;
Data.cbData = cbClientRandom;
CryptSetKeyParam(
hMasterKey,
KP_CLIENT_RANDOM,
(PBYTE)&Data,
0);
//------------------------------------------------------------
// Specify server_random.
Data.pbData = pServerRandom;
Data.cbData = cbServerRandom;
CryptSetKeyParam(
hMasterKey,
KP_SERVER_RANDOM,
(PBYTE)&Data,
0);
}
//------------------------------------------------------------
// Create the master hash object from the master key.
CryptCreateHash(
hProv,
CALG_SCHANNEL_MASTER_HASH,
hMasterKey,
0,
&hMasterHash);
//------------------------------------------------------------
// Derive read key from the master hash object.
CryptDeriveKey(hProv,
CALG_SCHANNEL_ENC_KEY,
hMasterHash,
fClient ? CRYPT_SERVER : 0,
&hReadKey);
//------------------------------------------------------------
// Derive write key from the master hash object.
CryptDeriveKey(
hProv,
CALG_SCHANNEL_ENC_KEY,
hMasterHash,
fClient ? 0 : CRYPT_SERVER,
&hWriteKey);
if(<protocol being used> != <SSL 2.0>) // for SSL 2.0, the master
// key is also the MAC.
{
//------------------------------------------------------------
// Derive read MAC from the master hash object.
CryptDeriveKey(
hProv,
CALG_SCHANNEL_MAC_KEY,
hMasterHash,
fClient ? CRYPT_SERVER : 0,
&hReadMAC);
//------------------------------------------------------------
// Derive write MAC from the master hash object.
CryptDeriveKey(
hProv,
CALG_SCHANNEL_MAC_KEY,
hMasterHash,
fClient ? 0 : CRYPT_SERVER,
&hWriteMAC);
}
CryptDestroyHash(hMasterHash);