Condividi tramite


Importazione della chiave pubblica dei driver

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice usi MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation invece di DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

La chiave pubblica RSA del driver è contenuta nei tag modulo ed esponente del nodo foglia del certificato. Entrambi i valori sono codificati in base64 e devono essere decodificati. Se si usa CryptoAPI di Microsoft, è necessario importare la chiave in un provider di servizi di crittografia (CSP), ovvero il modulo che implementa gli algoritmi di crittografia.

Per convertire i moduli e gli esponenti dalla codifica base64 alle matrici binarie, usare la funzione CryptStringToBinary , come illustrato nel codice seguente. Chiamare la funzione una volta per ottenere le dimensioni della matrice di byte. Allocare quindi il buffer e chiamare di nuovo la funzione.

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.)

La matrice con codifica base64 è in ordine big-endian, mentre CryptoAPI prevede il numero in ordine little-endian, quindi è necessario scambiare l'ordine dei byte della matrice restituita da CryptStringToBinary. Il modulo è di 256 byte, ma la matrice di byte decodificata può essere inferiore a 256 byte. In tal caso, sarà necessario allocare una nuova matrice di 256 byte, copiare i dati nella nuova matrice e riempire la parte anteriore della matrice con zeri. L'esponente è un valore DWORD (4 byte).

Dopo aver ottenuto i valori modulo ed esponente, è possibile importare la chiave nel provider di servizi di crittografia predefinito (CSP), come illustrato nel codice seguente:

// 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) 

È ora possibile usare CryptoAPI per crittografare i comandi e le richieste di stato con la chiave pubblica del driver.

Uso del protocollo COPP (Certified Output Protection Protocol)