다음을 통해 공유


CryptAcquireContextW 함수(wincrypt.h)

중요 이 API는 더 이상 사용되지 않습니다. 신규 및 기존 소프트웨어는 Cryptography Next Generation API 사용을 시작해야 합니다. Microsoft는 향후 릴리스에서 이 API를 제거할 수 있습니다.
 
CryptAcquireContext 함수는 특정 CSP(암호화 서비스 공급자) 내의 특정 키 컨테이너에 대한 핸들을 획득하는 데 사용됩니다. 이 반환된 핸들은 선택한 CSP를 사용하는 CryptoAPI 함수 호출에 사용됩니다.

이 함수는 먼저 dwProvTypepszProvider 매개 변수에 설명된 특성을 가진 CSP를 찾으려고 시도합니다. CSP가 발견되면 함수는 pszContainer 매개 변수로 지정된 이름과 일치하는 CSP 내에서 키 컨테이너를 찾으려고 시도합니다. 인증서의 공개 키와 연결된 프라이빗 키컨텍스트 및 키 컨테이너를 가져오려면 CryptAcquireCertificatePrivateKey를 사용합니다.

dwFlags의 적절한 설정을 사용하면 이 함수는 키 컨테이너를 만들고 삭제할 수도 있으며 프라이빗 키에 대한 액세스가 필요하지 않은 경우 임시 키 컨테이너를 사용하여 CSP에 대한 액세스를 제공할 수 있습니다.

구문

BOOL CryptAcquireContextW(
  [out] HCRYPTPROV *phProv,
  [in]  LPCWSTR    szContainer,
  [in]  LPCWSTR    szProvider,
  [in]  DWORD      dwProvType,
  [in]  DWORD      dwFlags
);

매개 변수

[out] phProv

CSP의 핸들에 대한 포인터입니다. CSP 사용을 마치면 CryptReleaseContext 함수를 호출하여 핸들을 해제합니다.

[in] szContainer

키 컨테이너 이름입니다. CSP에 대한 키 컨테이너를 식별하는 null로 끝나는 문자열입니다. 이 이름은 키를 저장하는 데 사용되는 메서드와 독립적입니다. 일부 CSP는 내부적으로(하드웨어에) 키 컨테이너를 저장하고, 일부는 시스템 레지스트리를 사용하고, 다른 CSP는 파일 시스템을 사용합니다. 대부분의 경우 dwFlags 가 CRYPT_VERIFYCONTEXT 설정된 경우 pszContainerNULL로 설정해야 합니다. 그러나 스마트 카드 CSP와 같은 하드웨어 기반 CSP의 경우 지정된 컨테이너에서 공개적으로 사용 가능한 정보에 액세스할 수 있습니다.

pszContainer 매개 변수의 사용에 대한 자세한 내용은 비고를 참조하세요.

[in] szProvider

사용할 CSP의 이름을 포함하는 null로 끝나는 문자열입니다.

이 매개 변수가 NULL이면 사용자 기본 공급자가 사용됩니다. 자세한 내용은 암호화 서비스 공급자 컨텍스트를 참조하세요. 사용 가능한 암호화 공급자 목록은 암호화 공급자 이름을 참조하세요.

애플리케이션은 CryptGetProvParam 함수를 사용하여 dwParam 매개 변수에서 PP_NAME CSP 값을 읽어 사용 중인 CSP의 이름을 가져올 수 있습니다.

기본 CSP는 운영 체제 릴리스 간에 변경될 수 있습니다. 다른 운영 체제 플랫폼에서 상호 운용성을 보장하려면 기본 CSP를 사용하는 대신 이 매개 변수를 사용하여 CSP를 명시적으로 설정해야 합니다.

[in] dwProvType

획득할 공급자의 유형을 지정합니다. 정의된 공급자 유형은 암호화 공급자 유형에서 설명합니다.

[in] dwFlags

다음 플래그 중 하나 이상. 대부분의 애플리케이션은 디지털 서명을 만들거나 메시지의 암호를 해독할 필요가 없는 한 CRYPT_VERIFYCONTEXT 플래그를 설정해야 합니다.

의미
CRYPT_VERIFYCONTEXT
호출자는 지속형 프라이빗 키에 액세스할 필요가 없습니다. 임시 키를 사용하거나 해시, 암호화디지털 서명 확인만 수행하는 앱은 이 플래그를 설정해야 합니다. 서명을 만들거나 메시지를 암호 해독하는 애플리케이션만 프라이빗 키 에 액세스해야 하며 이 플래그를 설정하면 안 됩니다.

파일 기반 CSP의 경우 이 플래그가 설정되면 pszContainer 매개 변수를 NULL로 설정해야 합니다. 애플리케이션은 퍼블릭/프라이빗 키 쌍의 지속형 프라이빗 키에 액세스할 수 없습니다. 이 플래그를 설정하면 임시 퍼블릭/프라이빗 키 쌍을 만들 수 있지만 유지되지는 않습니다.

스마트 카드 CSP와 같은 하드웨어 기반 CSP의 경우 pszContainer 매개 변수가 NULL이거나 비어 있는 경우 이 플래그는 키에 대한 액세스가 필요하지 않으며 사용자에게 UI를 표시해서는 안 됨을 의미합니다. 이 양식은 기능을 쿼리하기 위해 CSP에 연결하는 데 사용되지만 실제로는 해당 키를 사용하지 않습니다. pszContainer 매개 변수가 NULL이 아니고 비어 있지 않은 경우 이 플래그는 지정된 컨테이너 내에서 공개적으로 사용할 수 있는 정보에만 액세스해야 한다는 것을 의미합니다. CSP는 PIN을 요청해서는 안 됩니다. 개인 정보(예: CryptSignHash 함수)에 액세스하려고 하면 실패합니다.

CryptAcquireContext가 호출되면 많은 CSP는 키 컨테이너의 프라이빗 키에 대한 액세스 권한을 부여하기 전에 소유 사용자의 입력이 필요합니다. 예를 들어 프라이빗 키를 암호화할 수 있으므로 사용하려면 사용자의 암호가 필요합니다. 그러나 CRYPT_VERIFYCONTEXT 플래그를 지정하는 경우 프라이빗 키에 대한 액세스가 필요하지 않으며 사용자 인터페이스를 무시할 수 있습니다.

CRYPT_NEWKEYSET
pszContainer로 지정된 이름으로 새 키 컨테이너를 만듭니다. pszContainerNULL이면 기본 이름을 가진 키 컨테이너가 만들어집니다.
CRYPT_MACHINE_KEYSET
기본적으로 키 및 키 컨테이너는 사용자 키로 저장됩니다. 기본 공급자의 경우 이는 사용자 키 컨테이너가 사용자의 프로필에 저장됨을 의미합니다. 관리자가 이 플래그 없이 만든 키 컨테이너는 키 컨테이너를 만드는 사용자와 관리 권한이 있는 사용자만 액세스할 수 있습니다.

Windows XP: 관리자가 이 플래그 없이 만든 키 컨테이너는 키 컨테이너 및 로컬 시스템 계정을 만드는 사용자만 액세스할 수 있습니다.

관리자가 아닌 사용자가 이 플래그 없이 만든 키 컨테이너는 키 컨테이너 및 로컬 시스템 계정을 만드는 사용자만 액세스할 수 있습니다.

CRYPT_MACHINE_KEYSET 플래그를 다른 모든 플래그와 결합하여 관심 있는 키 컨테이너가 컴퓨터 키 컨테이너이고 CSP가 이를 처리함을 나타낼 수 있습니다. 기본 공급자의 경우 키 컨테이너를 만든 컴퓨터에 키가 로컬로 저장됨을 의미합니다. 키 컨테이너가 컴퓨터 컨테이너인 경우 컴퓨터 컨테이너를 참조하는 CryptAcquireContext 에 대한 모든 호출과 함께 CRYPT_MACHINE_KEYSET 플래그를 사용해야 합니다. CryptSetProvParam을 사용하여 컨테이너에 대한 액세스 권한을 부여하지 않는 한 관리자가 CRYPT_MACHINE_KEYSET 사용하여 만든 키 컨테이너는 작성자 및 관리자 권한이 있는 사용자만 액세스할 수 있습니다.

Windows XP: CryptSetProvParam을 사용하여 컨테이너에 대한 액세스 권한을 부여하지 않는 한 관리자가 CRYPT_MACHINE_KEYSET 사용하여 만든 키 컨테이너는 작성자 및 로컬 시스템 계정에서만 액세스할 수 있습니다.

관리자가 아닌 사용자가 CRYPT_MACHINE_KEYSET 사용하여 만든 키 컨테이너는 CryptSetProvParam을 사용하여 컨테이너에 대한 액세스 권한을 부여하지 않는 한 작성자 및 로컬 시스템 계정에서만 액세스할 수 있습니다.

CRYPT_MACHINE_KEYSET 플래그는 사용자가 대화형으로 로그온하지 않은 서비스 또는 사용자 계정에서 액세스할 때 유용합니다. 키 컨테이너를 만들 때 대부분의 CSP는 퍼블릭/프라이빗 키 쌍을 자동으로 만들지 않습니다. 이러한 키는 CryptGenKey 함수를 사용하여 별도의 단계로 만들어야 합니다.

CRYPT_DELETEKEYSET
pszContainer에서 지정한 키 컨테이너를 삭제합니다. pszContainerNULL이면 기본 이름의 키 컨테이너가 삭제됩니다. 키 컨테이너의 모든 키 쌍도 제거됩니다.

이 플래그를 설정하면 phProv 에서 반환된 값이 정의되지 않으므로 나중에 CryptReleaseContext 함수를 호출할 필요가 없습니다.

CRYPT_SILENT
애플리케이션은 CSP에 이 컨텍스트에 대한 UI(사용자 인터페이스)를 표시하지 않도록 요청합니다. CSP가 작동할 UI를 표시해야 하는 경우 호출이 실패하고 NTE_SILENT_CONTEXT 오류 코드가 마지막 오류로 설정됩니다. 또한 CRYPT_SILENT 플래그를 사용하여 얻은 컨텍스트가 있는 CRYPT_USER_PROTECTED 플래그를 사용하여 CryptGenKey 를 호출하는 경우 호출이 실패하고 CSP가 NTE_SILENT_CONTEXT 설정합니다.

CRYPT_SILENT CSP에서 UI를 표시할 수 없는 애플리케이션에 사용하기 위한 것입니다.

CRYPT_DEFAULT_CONTAINER_OPTIONAL
해시 및 대칭 키 작업에 사용할 수 있지만 PIN을 사용하여 스마트 카드 인증이 필요한 작업에는 사용할 수 없는 스마트 카드 CSP에 대한 컨텍스트를 가져옵니다. 이 유형의 컨텍스트는 CryptSetProvParam을 사용하여 PIN을 설정하는 등 빈 스마트 카드 작업을 수행하는 데 가장 자주 사용됩니다. 이 플래그는 스마트 카드 CSP에서만 사용할 수 있습니다.

Windows Server 2003 및 Windows XP: 이 플래그는 지원되지 않습니다.

반환 값

함수가 성공하면 함수는 0이 아닌 값(TRUE)을 반환합니다.

함수가 실패하면 0(FALSE)을 반환합니다. 확장 오류 정보는 GetLastError를 호출합니다.

NTE가 앞에 있는 오류 코드는 사용 중인 특정 CSP에 의해 생성됩니다. Winerror.h에 정의된 몇 가지 가능한 오류 코드는 다음과 같습니다.

반환 코드/값 설명
ERROR_BUSY
107L
일부 CSP는 CRYPT_DELETEKEYSET 플래그 값이 설정되고 다른 스레드 또는 프로세스가키 컨테이너를 사용하는 경우 이 오류를 설정합니다.
ERROR_FILE_NOT_FOUND
2L
사용자의 프로필이 로드되지 않아 찾을 수 없습니다. 애플리케이션이 사용자를 가장하는 경우(예: IUSR_ComputerName 계정) 이 발생합니다.
ERROR_INVALID_PARAMETER
87L
매개 변수 중 하나에는 유효하지 않은 값이 포함되어 있습니다. 이는 가장 자주 유효하지 않은 포인터입니다.
ERROR_NOT_ENOUGH_MEMORY
8L
작업 중에 운영 체제에 메모리가 부족합니다.
NTE_BAD_FLAGS
0x80090009L
dwFlags 매개 변수에는 유효하지 않은 값이 있습니다.
NTE_BAD_KEY_STATE
0x8009000BL
프라이빗 키가 암호화된 이후 사용자 암호가 변경되었습니다.
NTE_BAD_KEYSET
0x80090016L
키 컨테이너를 열 수 없습니다. 이 오류의 일반적인 원인은 키 컨테이너가 없다는 것입니다. 키 컨테이너를 만들려면 CRYPT_NEWKEYSET 플래그를 사용하여 CryptAcquireContext 를 호출합니다. 이 오류 코드는 기존 키 컨테이너에 대한 액세스가 거부되었음을 나타낼 수도 있습니다. CryptSetProvParam을 사용하여 키 집합 작성자가 컨테이너에 대한 액세스 권한을 부여할 수 있습니다.
NTE_BAD_KEYSET_PARAM
0x8009001FL
pszContainer 또는 pszProvider 매개 변수는 유효하지 않은 값으로 설정됩니다.
NTE_BAD_PROV_TYPE
0x80090014L
dwProvType 매개 변수의 값이 범위를 벗어났습니다. 모든 공급자 형식은 1에서 999까지여야 합니다.
NTE_BAD_SIGNATURE
0x80090006L
공급자 DLL 서명을 확인할 수 없습니다. DLL 또는 디지털 서명이 변조되었습니다.
NTE_EXISTS
0x8009000FL
dwFlags 매개 변수는 CRYPT_NEWKEYSET 키 컨테이너가 이미 있습니다.
NTE_KEYSET_ENTRY_BAD
0x8009001AL
pszContainer 키 컨테이너가 발견되었지만 손상되었습니다.
NTE_KEYSET_NOT_DEF
0x80090019L
요청된 공급자가 없습니다.
NTE_NO_MEMORY
0x8009000EL
작업 중에 CSP 메모리가 부족했습니다.
NTE_PROV_DLL_NOT_FOUND
0x8009001EL
공급자 DLL 파일이 없거나 현재 경로에 없습니다.
NTE_PROV_TYPE_ENTRY_BAD
0x80090018L
dwProvType으로 지정된 공급자 유형이 손상되었습니다. 이 오류는 사용자 기본 CSP 목록 또는 컴퓨터 기본 CSP 목록과 관련이 있습니다.
NTE_PROV_TYPE_NO_MATCH
0x8009001BL
dwProvType으로 지정된 공급자 유형이 찾은 공급자 유형과 일치하지 않습니다. 이 오류는 pszProvider 가 실제 CSP 이름을 지정하는 경우에만 발생할 수 있습니다.
NTE_PROV_TYPE_NOT_DEF
0x80090017L
dwProvType으로 지정된 공급자 형식에 대한 항목이 없습니다.
NTE_PROVIDER_DLL_FAIL
0x8009001DL
공급자 DLL 파일을 로드하거나 초기화하지 못했습니다.
NTE_SIGNATURE_FILE_BAD
0x8009001CL
서명을 확인하기 전에 DLL 파일 이미지를 로드하는 동안 오류가 발생했습니다.

설명

pszContainer 매개 변수는 키를 보유하는 데 사용되는 컨테이너의 이름을 지정합니다. 각 컨테이너에는 하나의 키가 포함될 수 있습니다. 키를 만들 때 기존 컨테이너의 이름을 지정하면 새 키가 이전 컨테이너를 덮어씁니다.

CSP 이름과 키 컨테이너 이름의 조합은 시스템의 단일 키를 고유하게 식별합니다. 다른 애플리케이션에서 키 컨테이너를 사용하는 동안 한 애플리케이션이 키 컨테이너를 수정하려고 하면 예측할 수 없는 동작이 발생할 수 있습니다.

pszContainer 매개 변수를 NULL로 설정하면 기본 키 컨테이너 이름이 사용됩니다. 이러한 방식으로 Microsoft 소프트웨어 CSP가 호출되면 CryptAcquireContext 함수가 호출 될 때마다 새 컨테이너가 만들어집니다. 그러나 이와 관련하여 다른 CSP가 다르게 동작할 수 있습니다. 특히 CSP에는 CSP에 액세스하는 모든 애플리케이션에서 공유하는 단일 기본 컨테이너가 있을 수 있습니다. 따라서 애플리케이션은 기본 키 컨테이너를 사용하여 프라이빗 키를 저장해서는 안 됩니다. 대신 dwFlags 매개 변수에서 CRYPT_VERIFYCONTEXT 플래그를 전달하여 키 스토리지를 방지하거나 다른 애플리케이션에서 사용할 가능성이 없는 애플리케이션별 컨테이너를 사용합니다.

애플리케이션은 CryptGetProvParam 함수를 사용하여 PP_CONTAINER 값을 읽어 사용 중인 키 컨테이너의 이름을 가져올 수 있습니다.

성능상의 이유로 pszContainer 매개 변수를 NULL 로 설정하고 dwFlags 매개 변수를 지속형 키가 필요하지 않은 모든 상황에서 CRYPT_VERIFYCONTEXT 설정하는 것이 좋습니다. 특히 다음 시나리오에서 pszContainer 매개 변수를 NULL 로 설정하고 dwFlags 매개 변수를 CRYPT_VERIFYCONTEXT 설정하는 것이 좋습니다.

  • 해시를 만들고 있습니다.
  • 데이터를 암호화하거나 암호 해독하는 대칭 키를 생성하고 있습니다.
  • 데이터를 암호화하거나 해독하기 위해 해시에서 대칭 키를 파생합니다.
  • 서명을 확인하고 있습니다. CryptImportKey 또는 CryptImportPublicKeyInfo를 사용하여 PUBLICKEYBLOB 또는 인증서에서 공개 키를 가져올 수 있습니다. 공개 키만 가져오려는 경우 CRYPT_VERIFYCONTEXT 플래그를 사용하여 컨텍스트를 가져올 수 있습니다.
  • 대칭 키를 내보낼 계획이지만 암호화 컨텍스트의 수명 내에서 가져오지 않습니다. 마지막 두 시나리오에 대한 공개 키만 가져오려는 경우 CRYPT_VERIFYCONTEXT 플래그를 사용하여 컨텍스트를 가져올 수 있습니다.
  • 프라이빗 키 작업을 수행하지만 키 컨테이너에 저장된 지속형 프라이빗 키를 사용하지 않습니다.
프라이빗 키 작업을 수행하려는 경우 컨텍스트를 획득하는 가장 좋은 방법은 컨테이너를 여는 것입니다. NTE_BAD_KEYSET 이 시도가 실패하면 CRYPT_NEWKEYSET 플래그를 사용하여 컨테이너를 만듭니다.

예제

다음 예제에서는 암호화 컨텍스트를 획득하고 키 컨테이너의 퍼블릭/프라이빗 키 쌍에 액세스하는 방법을 보여 줍니다. 요청된 키 컨테이너가 없으면 생성됩니다.

이 예제의 전체 컨텍스트를 포함하는 예제는 예제 C 프로그램: 키 컨테이너 만들기 및 키 생성을 참조하세요. 추가 예제는 예제 C 프로그램: CryptAcquireContext 사용을 참조하세요.

//-------------------------------------------------------------------
// Declare and initialize variables.

HCRYPTPROV hCryptProv = NULL;        // handle for a cryptographic
                                     // provider context
LPCSTR UserName = "MyKeyContainer";  // name of the key container
                                     // to be used
//-------------------------------------------------------------------
// Attempt to acquire a context and a key
// container. The context will use the default CSP
// for the RSA_FULL provider type. DwFlags is set to zero
// to attempt to open an existing key container.

if(CryptAcquireContext(
   &hCryptProv,               // handle to the CSP
   UserName,                  // container name 
   NULL,                      // use the default provider
   PROV_RSA_FULL,             // provider type
   0))                        // flag values
{
    printf("A cryptographic context with the %s key container \n", 
  UserName);
    printf("has been acquired.\n\n");
}
else
{ 
//-------------------------------------------------------------------
// An error occurred in acquiring the context. This could mean
// that the key container requested does not exist. In this case,
// the function can be called again to attempt to create a new key 
// container. Error codes are defined in Winerror.h.
 if (GetLastError() == NTE_BAD_KEYSET)
 {
   if(CryptAcquireContext(
      &hCryptProv, 
      UserName, 
      NULL, 
      PROV_RSA_FULL, 
      CRYPT_NEWKEYSET)) 
    {
      printf("A new key container has been created.\n");
    }
    else
    {
      printf("Could not create a new key container.\n");
      exit(1);
    }
  }
  else
  {
      printf("A cryptographic service handle could not be "
          "acquired.\n");
      exit(1);
   }
  
} // End of else.
//-------------------------------------------------------------------
// A cryptographic context and a key container are available. Perform
// any functions that require a cryptographic provider handle.

//-------------------------------------------------------------------
// When the handle is no longer needed, it must be released.

if (CryptReleaseContext(hCryptProv,0))
{
  printf("The handle has been released.\n");
}
else
{
  printf("The handle could not be released.\n");
}

참고

wincrypt.h 헤더는 CRYptAcquireContext를 유니코드 전처리기 상수의 정의에 따라 이 함수의 ANSI 또는 유니코드 버전을 자동으로 선택하는 별칭으로 정의합니다. 인코딩 중립 별칭을 인코딩 중립이 아닌 코드와 혼합하면 컴파일 또는 런타임 오류가 발생하는 불일치가 발생할 수 있습니다. 자세한 내용은 함수 프로토타입에 대한 규칙을 참조하세요.

요구 사항

요구 사항
지원되는 최소 클라이언트 Windows XP [데스크톱 앱만 해당]
지원되는 최소 서버 Windows Server 2003 [데스크톱 앱만 해당]
대상 플랫폼 Windows
헤더 wincrypt.h
라이브러리 Advapi32.lib
DLL Advapi32.dll

추가 정보

CryptGenKey

CryptGetProvParam

CryptReleaseContext

서비스 공급자 함수

암호화 서비스 공급자의 스레딩 문제