CryptAcquireContextA 함수(wincrypt.h)

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

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

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

구문

BOOL CryptAcquireContextA(
  [out] HCRYPTPROV *phProv,
  [in]  LPCSTR     szContainer,
  [in]  LPCSTR     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

플래그 값입니다. 이 매개 변수는 일반적으로 0으로 설정되지만 일부 애플리케이션은 다음 플래그 중 하나 이상을 설정합니다.

의미
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

서비스 공급자 함수

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