CryptAcquireContext() 사용 및 문제 해결
이 문서에서는 CryptAcquireContext를 호출할 때 특정 플래그를 사용하는 시기와 이러한 플래그를 사용하는 이유에 대한 정보를 제공합니다.
적용 대상: Windows Server 2012 R2
원본 KB 번호: 238187
요약
함수에 대한 호출에는 다양한 플래그가 CryptAcquireContext
포함될 수 있습니다. 이러한 플래그를 사용해야 하는 경우를 알아야 합니다. 이 문서에서는 호출 CryptAcquireContext
할 때 특정 플래그를 사용하는 시기와 이러한 플래그를 사용하는 이유에 대한 정보를 제공합니다.
추가 정보
프라이빗 키 작업이 수행되지 않음
지속형 프라이빗 키를 사용하지 않는 경우 CryptAcquireContext가 호출될 때 CRYPT_VERIFYCONTEXT(0xF0000000) 플래그를 사용할 수 있습니다. CryptoAPI에 CryptReleaseContext가 호출될 때 릴리스될 키 컨테이너를 메모리에 만들도록 지시합니다. 이 플래그를 사용하는 경우 pszContainer 매개 변수는 NULL이어야 합니다. CRYPT_VERIFYCONTEXT 플래그는 다음 시나리오에서 사용할 수 있습니다.
해시를 만들고 있습니다.
대칭 키를 생성하여 데이터를 암호화하거나 해독합니다.
해시에서 대칭 키를 파생하여 데이터를 암호화하거나 암호 해독합니다.
서명을 확인하고 있습니다. CryptImportKey 또는 CryptImportPublicKeyInfo를 사용하여 PUBLICKEYBLOB 또는 인증서에서 공개 키를 가져올 수 있습니다.
대칭 키를 내보낼 계획이지만 암호화 컨텍스트의 수명 내에 가져오지는 않습니다.
참고
마지막 두 시나리오에 대한 공개 키만 가져오려는 경우 CRYPT_VERIFYCONTEXT 플래그를 사용하여 컨텍스트를 가져올 수 있습니다.
프라이빗 키 작업을 수행하고 있지만 키 컨테이너에 저장된 지속형 프라이빗 키를 사용하지 않습니다.
프라이빗 키 작업이 수행됩니다.
프라이빗 키 작업을 수행하려는 경우 고려해야 할 많은 문제가 있습니다.
컨텍스트를 획득하는 가장 좋은 방법은 컨테이너를 여는 것입니다. 이 시도가 "NTE_BAD_KEYSET"와 함께 실패하는 경우 CRYPT_NEWKEYSET 플래그를 사용하여 컨테이너를 만듭니다.
참고
애플리케이션은 프라이빗 키를 저장하기 위해 컨테이너 이름에 NULL 을 전달하여 기본 키 컨테이너를 사용하면 안 됩니다. 여러 애플리케이션이 동일한 컨테이너를 사용하는 경우 한 애플리케이션은 다른 애플리케이션에서 사용할 수 있어야 하는 키를 변경하거나 삭제할 수 있습니다. 애플리케이션이 고유한 이름의 키 컨테이너를 사용하는 경우 적절한 기능에 필요한 키를 조작하는 다른 애플리케이션의 위험이 줄어듭니다.
// Acquire Context of container that is unique to each user.
if (!CryptAcquireContext(&hProv,
"Container",
NULL,
PROV_RSA_FULL,
0))
{
if (GetLastError() == NTE_BAD_KEYSET)
{
if (!CryptAcquireContext(&hProv,
"Container",
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
// Error ...
}
}
}
// Or, acquire Context of container that is shared across the machine.
if (!CryptAcquireContext(&hProv,
"Container",
NULL,
PROV_RSA_FULL,
CRYPT_MACHINE_KEYSET))
{
if (GetLastError() == NTE_BAD_KEYSET)
{
if (!CryptAcquireContext(&hProv,
"Container",
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET)
{
// Error ...
}
}
}
CRYPT_MACHINE_KEYSET 플래그 사용
사용자별로 프라이빗 키 작업을 수행하지 않고 전역 프라이빗 키 작업이 필요한 경우 CRYPT_MACHINE_KEYSET 사용해야 합니다. 이 메서드는 컴퓨터별로 프라이빗/퍼블릭 키 쌍을 만듭니다. CRYPT_MACHINE_KEYSET 사용해야 하는 몇 가지 특정 시나리오는 다음과 같습니다.
- 서비스를 작성하고 있습니다.
- 구성 요소가 ASP(활성 서버 페이지) 페이지에서 실행되고 있습니다.
- 구성 요소는 MTS(Microsoft Transaction Server) 구성 요소입니다. 이러한 예제에서는 애플리케이션이 실행되는 보안 컨텍스트가 사용자 프로필에 액세스할 수 없기 때문에 CRYPT_MACHINE_KEYSET 사용됩니다. 예를 들어 MTS 클라이언트는 사용자를 가장할 수 있지만 사용자가 로그온하지 않았기 때문에 사용자의 프로필을 사용할 수 없습니다. ASP 페이지에서 실행되는 구성 요소도 마찬가지입니다.
컨테이너에 대한 액세스 제공
기본적으로 키 컨테이너를 만들 때 로컬 시스템과 작성자는 컨테이너에 액세스할 수 있는 유일한 사용자입니다. 관리자가 키 컨테이너를 만드는 경우는 예외입니다. 로컬 시스템과 다른 모든 관리자는 키 컨테이너에 액세스할 수 있습니다. 다른 보안 컨텍스트는 컨테이너를 열 수 없습니다.
코드가 둘 이상의 보안 컨텍스트에서 실행되는 경우 적절한 사용자에게 컨테이너에 대한 액세스 권한을 부여해야 합니다.
컨테이너에 대한 보안을 설정하려면 컨테이너를 만든 후 PP_KEYSET_SEC_DESCR 플래그를 사용하여 CryptSetProvParam 함수를 호출합니다. 이 메서드를 사용하면 컨테이너에서 보안 설명자를 설정할 수 있습니다.
다음 코드에서는 CryptSetProvParam을 호출하는 방법을 보여 줍니다. 이 작업은 키 컨테이너를 만든 직후에 수행됩니다.
// Acquire Context
if (!CryptAcquireContext(&hProv,
"Container",
NULL,
PROV_RSA_FULL,
0))
{
if (GetLastError() == NTE_BAD_KEYSET)
{
if (!CryptAcquireContext(&hProv,
"Container",
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
// Error ...
}
// Create Security Descriptor (pSD)...
// Set the Security Descriptor on the container
if (!CryptSetProvParam(hProv,
PP_KEYSET_SEC_DESCR,
pSD,
DACL_SECURITY_INFORMATION))
{
// Error ...
}
}
}
CryptAcquireContext 오류
다음은 가장 일반적인 오류 코드와 오류의 가능한 이유입니다.
- NTE_BAD_KEYSET(0x80090016)
- 키 컨테이너가 없습니다.
- 키 컨테이너에 액세스할 수 없습니다.
- 보호된 스토리지 서비스가 실행되고 있지 않습니다.
- NTE_EXISTS(0x8009000F)
- 키 컨테이너가 이미 있지만 만들려고 합니다. NTE_BAD_KEYSET 키를 열려는 이전 시도가 실패한 경우 키 컨테이너에 대한 액세스가 거부되었음을 의미합니다.
- NTE_KEYSET_NOT_DEF(0x80090019)
- CSP(암호화 서비스 공급자)가 올바르게 설정되지 않을 수 있습니다. CSP DLL(Rsabase.dll 또는 Rsaenh.dll)에서 Regsvr32.exe 사용하면 사용 중인 공급자에 따라 문제가 해결될 수 있습니다.
피드백
https://aka.ms/ContentUserFeedback
출시 예정: 2024년 내내 콘텐츠에 대한 피드백 메커니즘으로 GitHub 문제를 단계적으로 폐지하고 이를 새로운 피드백 시스템으로 바꿀 예정입니다. 자세한 내용은 다음을 참조하세요.다음에 대한 사용자 의견 제출 및 보기