导入驱动程序公钥
[与此页面关联的功能 DirectShow 是旧版功能。 它已被 MediaPlayer、 IMFMediaEngine 和 Media Foundation 中的音频/视频捕获所取代。 这些功能已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能在 Media Foundation 中使用 MediaPlayer、 IMFMediaEngine 和 音频/视频捕获 ,而不是 DirectShow。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]
驱动程序的 RSA 公钥包含在证书的叶节点的模数和指数标记中。 这两个值都是 base64 编码的,必须解码。 如果使用 Microsoft 的 CryptoAPI,则必须将密钥导入加密服务提供程序 (CSP) ,这是实现加密算法的模块。
若要将模数和指数从 base64 编码转换为二进制数组,请使用 CryptStringToBinary 函数,如以下代码所示。 调用函数一次以获取字节数组的大小。 然后分配缓冲区并再次调用函数。
DWORD cbLen = 0, dwSkip = 0, dwFlags = 0;
::CryptStringToBinary(
pszModulus, // String that contains the Base64-encoded modulus.
cchModulus, // Length of the string, not including the trailing NULL.
CRYPT_STRING_BASE64, // Base64 encoding.
NULL, // Do not convert yet. Just calculate the length.
&cbLen, // Receives the length of the buffer that is required.
&dwSkip, // Receives the number of skipped characters.
&dwFlags // Receives flags.
);
// Allocate a new buffer.
BYTE *pbBuffer = new BYTE [cbLen];
::CryptStringToBinary(pszModulus, cchModulus, CRYPT_STRING_BASE64,
pbBuffer, &cbLen, &dwSkip, &dwFlags);
// (Repeat these steps for the exponent.)
base64 编码的数组采用大端顺序,而 CryptoAPI 预期数字以小端顺序排列,因此需要交换从 CryptStringToBinary 返回的数组的字节顺序。 模数为 256 个字节,但解码的字节数组可能小于 256 个字节。 如果是这样,则需要分配一个 256 字节的新数组,将数据复制到新数组中,并使用零填充数组的前面。 指数是 DWORD (4 字节) 值。
获得模数和指数值后,可以将密钥导入默认加密服务提供程序 (CSP) ,如以下代码所示:
// Assume the following values exist:
BYTE *pModulus; // Byte array that contains the modulus.
DWORD cbModulus; // Size of the modulus in bytes.
DWORD dwExponent; // Exponent.
// Create a new key container to hold the key.
::CryptAcquireContext(
&hCSP, // Receives a handle to the CSP.
NULL, // Use the default key container.
NULL, // Use the default CSP.
PROV_RSA_AES, // Use the AES provider (public-key algorithm).
CRYPT_SILENT | CRYPT_NEWKEYSET
);
// Move the key into the key container.
// The data format is: PUBLICKEYSTRUC + RSAPUBKEY + key
DWORD cbKeyBlob = cbModulus + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY)
BYTE *pBlob = new BYTE[cbKeyBlob];
// Fill in the data.
PUBLICKEYSTRUC *pPublicKey = (PUBLICKEYSTRUC*)pBlob;
pPublicKey->bType = PUBLICKEYBLOB;
pPublicKey->bVersion = CUR_BLOB_VERSION; // Always use this value.
pPublicKey->reserved = 0; // Must be zero.
pPublicKey->aiKeyAlg = CALG_RSA_KEYX; // RSA public-key key exchange.
// The next block of data is the RSAPUBKEY structure.
RSAPUBKEY *pRsaPubKey = (RSAPUBKEY*)(pBlob + sizeof(PUBLICKEYSTRUC));
pRsaPubKey->magic = RSA1; // Public key.
pRsaPubKey->bitlen = cbModulus * 8; // Number of bits in the modulus.
pRsaPubKey->pubexp = dwExponent; // Exponent.
// Copy the modulus into the blob. Put the modulus directly after the
// RSAPUBKEY structure in the blob.
BYTE *pKey = (BYTE*)(pRsaPubkey + sizeof(RSAPUBKEY));
CopyMemory(pKey, pModulus, cbModulus);
// Now import the key.
HCRYPTKEY hRSAKey; // Receives a handle to the key.
CryptImportKey(hCSP, pBlob, cbKeyBlob, 0, 0, &hRSAKey)
现在,可以使用 CryptoAPI 使用驱动程序的公钥来加密命令和状态请求。
相关主题