다음을 통해 공유


NCryptCreateClaim 함수(ncrypt.h)

키 증명 클레임을 만듭니다.

통사론

SECURITY_STATUS NCryptCreateClaim(
  [in]           NCRYPT_KEY_HANDLE hSubjectKey,
  [in, optional] NCRYPT_KEY_HANDLE hAuthorityKey,
  [in]           DWORD             dwClaimType,
  [in, optional] NCryptBufferDesc  *pParameterList,
  [out]          PBYTE             pbClaimBlob,
  [in]           DWORD             cbClaimBlob,
  [out]          DWORD             *pcbResult,
  [in]           DWORD             dwFlags
);

매개 변수

[in] hSubjectKey

클레임이 만들어지는 주체 키 핸들입니다.

[in, optional] hAuthorityKey

클레임의 기반이 되는 기관 키 핸들입니다.

[in] dwClaimType

클레임의 형식입니다.

[in, optional] pParameterList

선택적 매개 변수 목록입니다.

[out] pbClaimBlob

생성된 클레임 Blob의 출력입니다.

[in] cbClaimBlob

pbClaimBlob 버퍼의 크기(바이트)입니다.

[out] pcbResult

생성된 클레임 Blob의 출력입니다.

[in] dwFlags

현재 정의된 플래그가 없습니다. dwFlags 매개 변수는 0설정해야 합니다.

반환 값

함수의 성공 또는 실패를 나타내는 상태 코드를 반환합니다.

발언

VBS(가상화 기반 보안)를 사용하여 프라이빗 키 보호/증명

메모

VBS 플래그에 대한 정보는 상용 출시 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보와 관련하여 명시적이거나 묵시적인 보증을 하지 않습니다.

이 API는 VBS를 사용하여 프라이빗 키를 보호/증명하기 위한 Windows 모듈인 VBS 키 보호를 기반으로 보안 키의 고급 증명을 사용하도록 설정하는 데 도움이 됩니다. 보안 키의 증명은 이 키와 고정된 키, 즉 증명 키의 연결을 증명합니다. 이 기능은 컨텍스트 외부 키의 사용을 제한하여 서로 다른 엔터티 간의 통신 보안 수준을 향상시킬 수 있습니다.

API는 VBS 키 보호의 증명 키를 기반으로 증명 클레임 생성 및 확인을 지원하는 새 플래그를 정의합니다.

다음은 API에 대해 정의된 dwClaimType 형식입니다.

클레임 유형 묘사
NCRYPT_CLAIM_VBS_ROOT 이 형식은 생성된 클레임이 VBS 루트 키에 의해 생성됨을 나타냅니다.
NCRYPT_CLAIM_VBS_IDENTITY 이 형식은 생성된 클레임이 VBS ID/증명에 의해 생성됨을 나타냅니다. 즉, 클레임은 증명 플래그 NCRYPT_ALLOW_KEY_ATTESTATION_FLAG 상승된 VBS 키에 의해 생성됩니다(아래 세부 정보 참조).

다음은 증명 클레임을 만들 때 pParameterList 버퍼에 설정할 버퍼 형식입니다.

버퍼 유형 묘사
NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASH NCryptCreateClaim증명 클레임을 만들 때 매개 변수 버퍼에 설정할 버퍼 형식입니다. NCRYPT_CLAIM_VBS_IDENTITY 클레임에 대한 필수 매개 변수 형식입니다.

이 매개 변수는 증명 클레임 생성을 통해 사용할 해시 함수 형식의 형식을 구성합니다. 이 매개 변수의 값은 ncrypt.h 정의됩니다(예: CNG 알고리즘 식별자상수).

#define NCRYPT_SHA1_ALGORITHM BCRYPT_SHA1_ALGORITHM
#define NCRYPT_SHA256_ALGORITHM BCRYPT_SHA256_ALGORITHM
#define NCRYPT_SHA384_ALGORITHM BCRYPT_SHA384_ALGORITHM
#define NCRYPT_SHA512_ALGORITHM BCRYPT_SHA512_ALGORITHM
NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_SCHEME NCryptCreateClaim증명 클레임을 만들 때 매개 변수 버퍼에 설정할 버퍼 형식입니다. 생성된 NCRYPT_CLAIM_VBS_IDENTITY 클레임의 증명 키가 RSA 키인 경우 필수 매개 변수입니다.

이 매개 변수는 증명 클레임 생성을 통해 사용할 서명 함수 형식에 대한 패딩 구성표를 구성합니다. 이 매개 변수의 선택적 값은 bcrypt.h 정의됩니다(예: NCryptSignHashdwFlags 상수).

#define BCRYPT_PAD_PSS 0x00000008
NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_ALGO NCryptCreateClaim증명 클레임을 만들 때 매개 변수 버퍼에 설정할 새 버퍼 형식입니다. 생성된 NCRYPT_CLAIM_VBS_IDENTITY 클레임의 증명 키가 RSA 키인 경우 필수 매개 변수입니다. 매개 변수는 패딩을 만드는 데 사용할 암호화 알고리즘을 식별하는 null로 끝나는 유니코드 문자열에 대한 포인터입니다. 이 알고리즘은 해시 알고리즘이어야 합니다. 이 매개 변수의 값은 ncrypt.h 정의됩니다(예: CNG 알고리즘 식별자상수).

#define NCRYPT_SHA1_ALGORITHM BCRYPT_SHA1_ALGORITHM
#define NCRYPT_SHA256_ALGORITHM BCRYPT_SHA256_ALGORITHM
#define NCRYPT_SHA384_ALGORITHM BCRYPT_SHA384_ALGORITHM
#define NCRYPT_SHA512_ALGORITHM BCRYPT_SHA512_ALGORITHM
NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_SALT_SIZE NCryptCreateClaim증명 클레임을 만들 때 매개 변수 버퍼에 설정할 새 버퍼 형식입니다. 생성된 NCRYPT_CLAIM_VBS_IDENTITY 클레임의 증명 키가 RSA 키인 경우 필수 매개 변수입니다.

매개 변수는 패딩에 사용할 임의 솔트의 크기(바이트)를 나타냅니다.
NCRYPTBUFFER_ATTESTATION_STATEMENT_NONCE NCryptCreateClaim증명 클레임을 만들 때 매개 변수 버퍼에 설정할 버퍼 형식입니다. 이 매개 변수는 NCRYPTBUFFER_CLAIM_KEYATTESTATION_NONCE별칭입니다.

예제

이 예제에서는 새 API 플래그 NCRYPT_ALLOW_KEY_ATTESTATION_FLAG사용하는 방법을 보여 줍니다. 또한 클레임 만들기에 대한 nonce 값은 NCRYPTBUFFER_ATTESTATION_STATEMENT_NONCE 매개 변수 형식에 의해 설정됩니다.

이 예제는 다음 주요 단계로 구성됩니다.

  1. 새 증명 키가 만들어집니다. 키는 NCryptSetPropertyAPI 함수를 사용하여 특수화됩니다. 증명 생성은 서명 키를 기반으로 합니다.
  2. 추가 증명을 위해 클레임이 생성됩니다. 클레임은 증명 키 및 기본 제공 VBS 키와 연결됩니다. 증명 키를 제공하여 NCryptVerifyClaim 클레임을 확인할 수 있습니다.
  3. 메모리 누수 방지를 위해 증명 키 개체가 해제됩니다.
// Create an attestation/identity key. This function is invoked in the main code flow below.
NCRYPT_KEY_HANDLE CreateAttestationKey(NCRYPT_PROV_HANDLE provider)
{

    NCRYPT_KEY_HANDLE attestationKey = NULL;
    HRESULT hr;

    if (FAILED(hr = NCryptCreatePersistedKey(
                    provider,
                    &attestationKey,
                    BCRYPT_RSA_ALGORITHM,
                    L"AttestationKey", // a unique name for the attestation key in the key store
                    0, //dwLegacyKeySpec, not used
                    NCRYPT_REQUIRE_VBS_FLAG/*This flag targets VBS */)))
    {
        wprintf(L"Error creating an Attestation Identity Key with NCryptCreatePersistedKey(): 0x%X\n", hr);
        goto cleanup;
    }

    // This is a new flag. It’s used to enable the capability in an attestation key.
    DWORD keyUsagePolicy = NCRYPT_ALLOW_KEY_ATTESTATION_FLAG;
    if (FAILED(hr = NCryptSetProperty(
                    attestationKey,
                    NCRYPT_KEY_USAGE_PROPERTY,
                    (PUCHAR)&keyUsagePolicy,
                    sizeof(keyUsagePolicy),
                    0 /*dwFlags*/)))
    {
        wprintf(L"Error setting property with NCryptSetProperty (): 0x%X\n", hr);
        goto cleanup;
    }

    DWORD keySizeBits = 2048; // minimum allowed RSA key size
    if (FAILED(hr = NCryptSetProperty(
                    attestationKey,
                    NCRYPT_LENGTH_PROPERTY,
                    (PUCHAR)&keySizeBits,
                    sizeof(keySizeBits),
                    0 /*dwFlags*/)))
    {
        wprintf(L"Error setting property with NCryptSetProperty (): 0x%X\n", hr);
        goto cleanup;
    }
    
    if (FAILED(hr = NCryptFinalizeKey(attestationKey, 0 /*dwFlags*/)))
    {
        wprintf(L"Error finalizing key with NCryptFinalizeKey (): 0x%X\n", hr);
        goto cleanup;
    }

    return attestationKey;
cleanup:
    if (attestationKey != NULL)
    {
        NCryptFreeObject(attestationKey);
    }

    return NULL;
}

HRESULT CreateAttestation()
{
    HRESULT hr = S_OK;
    NCRYPT_PROV_HANDLE provider = NULL;
    
    BYTE nonce[] = "TheSuperSecretNonce";
    // This way of setting parameters is an existent pattern for NCrypt APIs
    NCryptBuffer paramBuffers[] =
    {
        { sizeof(nonce), NCRYPTBUFFER_ATTESTATION_STATEMENT_NONCE, (PBYTE)&nonce },
    };
    NCryptBufferDesc params = { NCRYPTBUFFER_VERSION, ARRAYSIZE(paramBuffers), paramBuffers };
    
    if (FAILED(hr = NCryptOpenStorageProvider(&provider, MS_KEY_STORAGE_PROVIDER, 0)))
    {
        wprintf(L"Error opening storage provider in NCryptOpenStorageProvider: 0x%X\n", hr);
        goto cleanup;
    }
    
    // Create a VBS attestation key
    NCRYPT_KEY_HANDLE attestationKey = CreateAttestationKey(provider);
    if (attestationKey == NULL)
    {
        hr = E_ABORT;
        goto cleanup;
    }
    
    DWORD bytesWritten = 0;
    
    if (FAILED(hr = NCryptCreateClaim(
                    attestationKey, // key that is being attested here and may attest other keys.
                    NULL, // implies that IDKS (VBS root signing key) will be used.
                    NCRYPT_CLAIM_VBS_ROOT, // used to attest a key with IDKS (VBS root signing key).
                    &params, // parameters list
                    NULL, // getting the size
                    0, // getting the size
                    &bytesWritten,
                    0 /*dwFlags*/)))
    {
        wprintf(L"Error creating claim with NCryptCreateClaim (): 0x%X\n", hr);
        goto cleanup;
    }
    
    DWORD claimBufferSize = bytesWritten;
    
    PBYTE claimBuffer = (PBYTE) HeapAlloc(GetProcessHeap(), 0,claimBufferSize);
    if (NULL == claimBuffer)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        wprintf(L"Error allocating buffer for the claim: 0x%X\n", hr);
        goto cleanup;
    }
    
    bytesWritten = 0;
    if (FAILED(hr = NCryptCreateClaim(
                    attestationKey, // key that is being attested here and may attest other keys.
                    NULL, //implies that IDKS (VBS root signing key) will be used.
                    NCRYPT_CLAIM_VBS_ROOT, // used to attest with IDKS (VBS root signing key).
                    &params, // parameters list
                    claimBuffer,
                    claimBufferSize,
                    &bytesWritten,
                    0)))
    {
        wprintf(L"Error creating claim with NCryptCreateClaim (): 0x%X\n", hr);
        goto cleanup;
    }
    
    wprintf(L"The claim is created successfully. It may be shared with the verifier side.\n");

cleanup:
    if (provider != NULL)
    {
        NCryptFreeObject(provider);
    }
    if (attestationKey != NULL)
    {
        NCryptFreeObject(attestationKey);
    }
    if (claimBuffer)
    {
        HeapFree(GetProcessHeap(), 0, claimBuffer);
    }
    
    return hr;
}

다음 예제에서는 범용 암호화 키 및 관련 증명 클레임을 만들기 위한 새 API 매개 변수를 사용하는 방법을 보여 줍니다. 이 범용 키는 증명 클레임을 생성하는 데 사용됩니다.

클레임 생성에 대한 해시 알고리즘 유형과 패딩은 각각 NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASHNCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_[SCHEME/ALGO/SALT_SIZE] 매개 변수에 설정됩니다.

다음 사항에 유의하세요.

  • NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASH 매개 변수는 NCRYPT_CLAIM_VBS_IDENTITY 클레임에만 필수이며 다른 유형의 클레임에서는 의미가 없습니다.
  • NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING 매개 변수는 RSA 증명 키의 경우 NCRYPT_CLAIM_VBS_IDENTITY 클레임에 대해서만 필수입니다. 다른 유형의 클레임에서는 의미가 없습니다.

클레임을 통해 범용 키가 증명 키와 연결되어 있는지 확인할 수 있습니다.

//
HRESULT hr = S_OK;
NCRYPT_PROV_HANDLE provider = NULL;

if (FAILED(hr = NCryptOpenStorageProvider(&provider, MS_KEY_STORAGE_PROVIDER, 0)))
{
    wprintf(L"Error opening storage provider in NCryptOpenStorageProvider: 0x%X\n", hr);
    goto cleanup;
}

NCRYPT_KEY_HANDLE attestationKey = NULL;

// Open the attestation key, created in CreateAttestationKey(), see previous example
if (FAILED(hr = NCryptOpenKey(
                provider,
                &attestationKey,
                L"AttestationKey",
                0, //dwLegacyKeySpec, not used
                0 ,/* dwFlags */)))
{
    wprintf(L"Error openning the attestation key with NCryptOpenKey (): 0x%X\n", hr);
    goto cleanup;
}

NCRYPT_KEY_HANDLE tokenKey = NULL; // Token key that is bound to the security token

// Create VBS token (general purpose) key
if (FAILED(hr = NCryptCreatePersistedKey(
                provider,
                &tokenKey,
                BCRYPT_RSA_ALGORITHM,
                L"TokenKey",
                0, //dwLegacyKeySpec, not used
                NCRYPT_REQUIRE_VBS_FLAG /*This flag targets VBS*/)))
{
    wprintf(L"Error creating an token key with NCryptCreatePersistedKey(): 0x%X\n", hr);
    goto cleanup;
}

DWORD keySizeBits = 2048;
if (FAILED(hr = NCryptSetProperty(
                tokenKey,
                NCRYPT_LENGTH_PROPERTY,
                (PUCHAR)&keySizeBits,
                sizeof(keySizeBits),
                0 /*dwFlags*/)))
{
    wprintf(L"Error setting property with NCryptSetProperty (): 0x%X\n", hr);
    goto cleanup;
}

if (FAILED(hr = NCryptFinalizeKey(tokenKey, 0 /*dwFlags*/)))
{
    wprintf(L"Error finalizing key with NCryptFinalizeKey (): 0x%X\n", hr);
    goto cleanup;
}

DWORD bytesWritten = 0;

DWORD hashAlgoType; // This is a new flag. It’s used to set type of hash algorithm of the claim// Set specific hash function type to produce the claim
wchar_t pHashAlgo[] = NCRYPT_SHA512_ALGORITHM;
// Set specific padding scheme for hash function to produce the claim
ULONG paddingScheme = BCRYPT_PAD_PSS;
wchar_t pPaddingAlgo[] = NCRYPT_SHA256_ALGORITHM;
ULONG paddingSalt = 345;

// This way of setting parameters is an existent pattern for NCrypt APIs
NCryptBuffer paramBuffers[] =
{
    { sizeof(NCRYPT_SHA512_ALGORITHM), NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASH, (PBYTE)&pHashAlgo },
    { sizeof(paddingScheme), NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_SCHEME , (PBYTE)&paddingScheme },
    { sizeof(NCRYPT_SHA256_ALGORITHM), NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_ALGO, (PBYTE)&pPaddingAlgo },
    { sizeof(paddingSalt, NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_SALT_SIZE, (PBYTE)&paddingSalt }
};
NCryptBufferDesc params = { NCRYPTBUFFER_VERSION, ARRAYSIZE(paramBuffers), paramBuffers };

if (FAILED(hr = NCryptCreateClaim(
                tokenKey, // key that is being attested
                attestationKey,
                NCRYPT_CLAIM_VBS_IDENTITY, // attest general-purpose key with an attestation (identity) key.
                &params, // parameters list
                NULL, // getting the size
                0, // getting the size
                &bytesWritten,
                0 /*dwFlags*/)))
{
    wprintf(L"Error creating claim with NCryptCreateClaim (): 0x%X\n", hr);
    goto cleanup;
}

DWORD claimBufferSize = bytesWritten;

PBYTE claimBuffer = (PBYTE) HeapAlloc(GetProcessHeap(), 0,claimBufferSize);
if (NULL == claimBuffer)
{
    hr = HRESULT_FROM_WIN32(GetLastError());
    wprintf(L"Error allocating buffer for the claim: 0x%X\n", hr);
    goto cleanup;
}
bytesWritten = 0;

if (FAILED(hr = NCryptCreateClaim(
                tokenKey, // key that is being attested
                attestationKey, // we assume that it is already initialized
                NCRYPT_CLAIM_VBS_IDENTITY, // attest general-purpose key with an attestation (identity) key
                &params,
                claimBuffer,
                claimBufferSize,
                &bytesWritten,
                0)))
{
    wprintf(L"Error creating claim with NCryptCreateClaim (): 0x%X\n", hr);
    goto cleanup;
}

wprintf(L"The claim is created successfully. It may be shared with the verifier side.\n");

cleanup:
    if (provider != NULL)
    {
    NCryptFreeObject(provider);
    }
    if (tokenKey != NULL)
    {
    NCryptFreeObject(tokenKey);
    }
    if (attestationKey != NULL)
    {
    NCryptDeleteKey(attestationKey);
    }
    if (claimBuffer)
    {
    HeapFree(GetProcessHeap(), 0, claimBuffer);
    }
    
return hr;

요구 사항

요구
지원되는 최소 클라이언트 Windows 10 [데스크톱 앱 | UWP 앱]
지원되는 최소 서버 Windows Server 2016 [데스크톱 앱 | UWP 앱]
대상 플랫폼 Windows
헤더 ncrypt.h
라이브러리 Ncrypt.lib
DLL Ncrypt.dll