Построение СКЗИ "КриптоПро CSP 5.0" следует идеологии Microsoft CryptoAPI и использует криптографические объекты трех типов:
Использование CryptoAPI в MSDN
Объекты идентифицируются дескриптором, работа с объектами определяется интерфейсом СКЗИ "КриптоПро CSP 5.0".
Общая схема организации работы с криптографическими объектами – создание контекста, создание ассоциированных с ним криптографических объектов. Перенос дескрипторов из одного контекста в другой не допускается. Объекты могут уничтожаться самостоятельно. При уничтожении контекста все ассоциированные с ним объекты уничтожаются автоматически.
Возможность переноса объектов между контекстами обеспечивается с помощью данных, получаемых функцией экспорта ключей, а также с помощью значения хэш-функции, получаемого и устанавливаемого в объект хэширования функциями CPGetHashParam() и CPSetHashParam().
Многопоточная обработка с использованием СКЗИ "КриптоПро CSP 5.0" может быть организована двумя способами:
Первый подход универсален и может использоваться без дополнительных ограничений на синхронизацию объектов.
Второй связан с необходимостью синхронизации объектов криптопровайдера. Если поток вызывает функцию с объектом, блокированным другим потоком, функция возвращает ошибку с кодом ERROR_BUSY (0xaa).
В следующей таблице определены методы блокировки объектов в криптопровайдере "КриптоПро CSP 5.0".
Имя функции | hProv | hKey | hExpKey | hHash | Примечание |
---|---|---|---|---|---|
CPCAcquireContext(), CPAcquireContext() | LOCK_WRITE | -- | -- | -- | |
CPCCreateHash(), CPCreateHash() | LOCK_READ | LOCK_READ | -- | -- | |
CPCDecrypt(), CPDecrypt() | LOCK_READ | LOCK_READ LOCK_WRITE | -- | LOCK_READ LOCK_WRITE | (dwFlags&CP_CRYPT_NOKEYWLOCK) ? CRWLOCK_READ : CRWLOCK_WRITE |
CPCDeriveKey(), CPDeriveKey() | LOCK_READ | -- | -- | LOCK_WRITE | |
CPCDestroyHash(), CPDestroyHash() | LOCK_READ | -- | -- | LOCK_WRITE | |
CPCDestroyKey(), CPDestroyKey() | LOCK_READ | LOCK_WRITE | -- | -- | |
CPCDuplicateHash(), CPDuplicateHash() | LOCK_READ | -- | -- | LOCK_READ | |
CPCDuplicateKey(), CPDuplicateKey() | LOCK_READ | LOCK_READ | -- | -- | |
CPCEncrypt(), CPEncrypt() | LOCK_READ | LOCK_READ LOCK_WRITE | -- | LOCK_READ LOCK_WRITE | (dwFlags&CP_CRYPT_NOKEYWLOCK) ? CRWLOCK_READ : CRWLOCK_WRITE |
CPCExportKey(), CPExportKey() | LOCK_READ | LOCK_READ | LOCK_READ LOCK_WRITE | -- | (dwBlobType == SIMPLEBLOB) && (dwFlags&CP_CRYPT_NOKEYWLOCK) ? CRWLOCK_READ : CRWLOCK_WRITE |
CPCGenKey(), CPGenKey() | LOCK_READ | -- | -- | -- | |
CPCGenRandom(), CPGenRandom() | LOCK_READ | -- | -- | -- | |
CPCGetHashParam(), CPGetHashParam() | LOCK_READ | -- | -- | LOCK_WRITE | |
CPCGetKeyParam(), CPGetKeyParam() | LOCK_READ | LOCK_WRITE | -- | -- | |
CPCGetProvParam(), CPGetProvParam() | LOCK_READ LOCK_WRITE | -- | -- | -- | IsReadOnlyProvParam (dwParam) ? LOCK_READ : LOCK_WRITE |
CPCGetUserKey(), CPGetUserKey() | LOCK_READ | -- | -- | -- | |
CPCHashData(), CPHashData() | LOCK_READ | -- | -- | LOCK_WRITE | |
CPCHashSessionKey(), CPHashSessionKey() | LOCK_READ | LOCK_WRITE | -- | LOCK_WRITE | |
CPCImportKey(), CPImportKey() | LOCK_READ LOCK_WRITE | LOCK_READ LOCK_WRITE | -- | -- | hProv: bUKChange ? LOCK_WRITE : LOCK_READ, где bUKChange = IsPRIVATEKEYBLOB(pbData, dwDataLen); hKey: ((pbData[0] == SIMPLEBLOB) || (pbData[0] == PUBLICKEYBLOB) || ((pbData[0] == DIVERSKEYBLOB) && (CALG_PRO_DIVERS == (*(DWORD*)(pbData + sizeof(BLOBHEADER))))))) ? CRWLOCK_READ : CRWLOCK_WRITE |
CPCReleaseContext(), CPReleaseContext() | LOCK_WRITE | -- | -- | -- | |
CPCSetHashParam(), CPSetHashParam() | LOCK_READ | -- | -- | LOCK_WRITE | |
CPCSetKeyParam(), CPSetKeyParam() | LOCK_READ LOCK_WRITE | LOCK_WRITE | -- | -- | bUKChange ? LOCK_WRITE : LOCK_READ, где bUKChange = IsPrivateKeyParam(dwParam, pbData); |
CPCSetProvParam(), CPSetProvParam() | LOCK_WRITE | -- | -- | -- | |
CPCSignHash(), CPSignHash() | LOCK_READ | -- | -- | LOCK_WRITE | |
CPCVerifySignature(), CPVerifySignature() | LOCK_READ | LOCK_WRITE LOCK_READ | -- | LOCK_WRITE | (dwFlags&CP_CRYPT_NOKEYWLOCK) ? CRWLOCK_READ : CRWLOCK_WRITE |
Объекты ключей и хэширования, как видно из таблицы, в основном блокируются на запись, что связано с динамических характером обработки этих объектов.
Схема блокирования объектов СКЗИ "КриптоПро CSP 5.0" обеспечивает их безопасное использование при конкурентном выполнении операций в различных потоках. Вместе с тем, такое выполнение операций может приводить к неопределённому результату не вследствие ограничений СКЗИ или приложений, а по сути исполняемых операций. Например, результаты вызова функций CPEncrypt() зависят от предыдущих вызовов. Поэтому при многопоточной обработке пользователю следует самостоятельно обеспечивать потоковую безопасность (thread safe) и синхронизацию потоков тем способом, который он сочтёт нужным.