자습서: Azure Key Vault를 사용하여 Blob 암호화 및 해독

이 자습서에서는 클라이언트 쪽 암호화를 사용하여 Azure Key Vault에 저장된 키를 사용하여 Blob을 암호화 및 암호 해독하는 방법을 알아봅니다.

Azure Blob Storage는 서비스 쪽 암호화 및 클라이언트 쪽 암호화를 모두 지원합니다. 대부분의 시나리오에서 데이터를 쉽게 보호할 수 있도록 서비스 쪽 암호화 기능을 사용하는 것이 좋습니다. 서비스 쪽 암호화에 대한 자세한 내용은 미사용 데이터에 대한 Azure Storage 암호화를 참조하세요.

.NET용 Azure Blob Storage 클라이언트 라이브러리는 Azure Storage에 업로드하기 전에 애플리케이션 내에서 클라이언트 쪽 데이터 암호화를 지원하고, 클라이언트에 다운로드하는 동안 데이터의 암호를 해독하도록 지원합니다. 이 라이브러리는 또한 키 관리를 위해 Azure Key Vault와의 통합을 지원합니다.

이 자습서에서는 다음을 수행하는 방법을 보여 줍니다.

  • Azure Key Vault 리소스에 대한 권한 구성
  • .NET 클라이언트 라이브러리를 사용하여 리소스와 상호 작용하는 콘솔 애플리케이션 만들기
  • Key Vault에 키 추가
  • Key Vault에 저장된 키를 사용하여 클라이언트 쪽 암호화 옵션 구성
  • 클라이언트 쪽 암호화가 설정된 Blob 서비스 클라이언트 개체 만들기
  • 암호화된 Blob을 업로드한 다음, Blob 다운로드 및 암호 해독

필수 조건

Microsoft Entra 사용자에게 역할 할당

로컬로 개발하는 경우 Key Vault에 액세스하는 사용자 계정에 올바른 권한이 있는지 확인합니다. 키를 만들고 Key Vault의 키에 대한 작업을 수행하려면 Key Vault 암호화 책임자 역할이 필요합니다. Azure Portal, Azure CLI 또는 Azure PowerShell을 사용하여 사용자에게 Azure RBAC 역할을 할당할 수 있습니다. 범위 개요 페이지에서 역할 할당에 사용할 수 있는 범위에 대해 자세히 알아볼 수 있습니다.

이 시나리오에서는 최소 권한 원칙을 따르기 위해 범위가 Key Vault로 지정된 사용자 계정에 권한을 할당합니다. 이 방법은 사용자에게 필요한 최소 권한만 부여하고 더 안전한 프로덕션 환경을 만듭니다.

다음 예제에서는 사용자 계정에 Key Vault 암호화 책임자 역할을 할당하여 이 자습서를 완료하는 데 필요한 액세스 권한을 제공하는 방법을 보여 줍니다.

Important

대부분의 경우 Azure에서 역할 할당이 전파되는 데 1~2분이 걸리지만 드문 경우이지만 최대 8분이 걸릴 수 있습니다. 코드를 처음 실행할 때 인증 오류가 발생하면 잠시 기다렸다가 다시 시도하세요.

  1. Azure Portal에서 기본 검색 표시줄이나 왼쪽 탐색을 사용하여 Key Vault를 찾습니다.

  2. Key Vault 개요 페이지의 왼쪽 메뉴에서 액세스 제어(IAM)를 선택합니다.

  3. 액세스 제어(IAM) 페이지에서 역할 할당 탭을 선택합니다.

  4. 위쪽 메뉴에서 + 추가를 선택한 다음, 드롭다운 메뉴에서 역할 할당 추가를 선택합니다.

    A screenshot showing how to assign a role in Azure portal.

  5. 검색 상자를 사용하여 결과를 원하는 역할로 필터링합니다. 이 예제에서는 Key Vault 암호화 책임자를 검색하고 일치하는 결과를 선택한 후 다음을 선택합니다.

  6. 다음에 대한 액세스 할당 아래에서 사용자, 그룹 또는 서비스 주체를 선택한 다음, + 멤버 선택을 선택합니다.

  7. 대화 상자에서 Microsoft Entra 사용자 이름(일반적으로 user@domain 이메일 주소)을 검색한 다음, 대화 상자 하단에서 선택을 선택합니다.

  8. 검토 + 할당을 선택하여 최종 페이지로 이동한 다음, 검토 + 할당을 다시 선택하여 프로세스를 완료합니다.

프로젝트 설정

  1. 콘솔 창(예: PowerShell 또는 Bash)에서 dotnet new 명령을 사용하여 BlobEncryptionKeyVault라는 새 콘솔 앱을 만듭니다. 이 명령은 Program.cs라는 원본 파일 하나만 들어 있는 간단한 "Hello World" C# 프로젝트를 만듭니다.

    dotnet new console -n BlobEncryptionKeyVault
    
  2. 새로 만든 BlobEncryptionKeyVault 디렉터리로 전환합니다.

    cd BlobEncryptionKeyVault
    
  3. 원하는 코드 편집기에서 프로젝트를 엽니다. 프로젝트를 열려면 다음을 수행합니다.

    • Visual Studio에서 BlobEncryptionKeyVault.csproj 파일을 찾아 두 번 클릭합니다.
    • Visual Studio Code에서 다음 명령을 실행합니다.
    code .
    

이 예제에서 Azure 서비스와 상호 작용하려면 dotnet add package를 사용하여 다음 클라이언트 라이브러리를 설치합니다.

dotnet add package Azure.Identity
dotnet add package Azure.Security.KeyVault.Keys
dotnet add package Azure.Storage.Blobs

다음 using 지시문을 추가하고 System.Configuration에 대한 참조를 프로젝트에 추가해야 합니다.

using Azure;
using Azure.Core;
using Azure.Identity;
using Azure.Security.KeyVault.Keys;
using Azure.Security.KeyVault.Keys.Cryptography;
using Azure.Storage;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Azure.Storage.Blobs.Specialized;

환경 변수 설정

이 애플리케이션은 Key Vault의 이름을 검색하기 위해 KEY_VAULT_NAME라는 환경 변수를 찾습니다. 이 환경 변수를 설정하려면 콘솔 창을 열고 사용 중인 운영 체제의 지침을 따릅니다. <your-key-vault-name>을 키 자격 증명 모음의 이름으로 바꿉니다.

Windows:

명령줄에서 Windows에 대한 환경 변수를 설정할 수 있습니다. 그러나 이 방법을 사용하는 경우 해당 운영 체제에서 실행되는 모든 애플리케이션에서 해당 값에 액세스할 수 있으므로 주의하지 않으면 충돌이 발생할 수 있습니다. 환경 변수는 사용자 또는 시스템 수준에서 설정할 수 있습니다.

setx KEY_VAULT_NAME "<your-key-vault-name>"

Windows에서 환경 변수가 추가되면 명령 창의 새 인스턴스를 시작해야 합니다. Windows에서 Visual Studio를 사용하는 경우 변경 내용을 검색하려면 환경 변수를 만든 후 Visual Studio를 다시 시작해야 할 수 있습니다.

Linux:

export KEY_VAULT_NAME=<your-key-vault-name>

Azure Key Vault에서 키 추가

이 예제에서는 Azure Key Vault 클라이언트 라이브러리를 사용하여 키를 만들고 Key Vault에 추가합니다. Azure CLI, Azure Portal 또는 PowerShell을 사용하여 키를 만들고 Key Vault에 추가할 수도 있습니다.

아래 샘플에서는 지정된 자격 증명 모음에 대한 KeyClient 개체를 만듭니다. 그런 다음, KeyClient 개체를 사용하여 지정된 자격 증명 모음에 새 RSA 키를 만듭니다.

var keyName = "testRSAKey";
var keyVaultName = Environment.GetEnvironmentVariable("KEY_VAULT_NAME");

// URI for the key vault resource
var keyVaultUri = $"https://{keyVaultName}.vault.azure.net";

TokenCredential tokenCredential = new DefaultAzureCredential();

// Create a KeyClient object
var keyClient = new KeyClient(new Uri(keyVaultUri), tokenCredential);

// Add a key to the key vault
var key = await keyClient.CreateKeyAsync(keyName, KeyType.Rsa);

키 및 키 확인자 인스턴스 만들기

다음으로, 방금 자격 증명 모음에 추가한 키를 사용하여 암호화 클라이언트 및 키 확인자 인스턴스를 만듭니다. CryptographyClientIKeyEncryptionKey를 구현하며 Azure Key Vault에 저장된 키를 사용하여 암호화 작업을 수행하는 데 사용됩니다. KeyResolverIKeyEncryptionResolver를 구현하고 키 식별자에서 키 암호화 키를 검색하고 키를 확인합니다.

// Cryptography client and key resolver instances using Azure Key Vault client library
CryptographyClient cryptoClient = keyClient.GetCryptographyClient(key.Value.Name, key.Value.Properties.Version);
KeyResolver keyResolver = new (tokenCredential);

자격 증명 모음에 암호화하려는 기존 키가 있는 경우 URI를 전달하여 키 및 키 확인자 인스턴스를 만들 수 있습니다.

var keyVaultKeyUri = $"https://{keyVaultName}.vault.azure.net/keys/{keyName}";
CryptographyClient cryptoClient = new CryptographyClient(new Uri(keyVaultKeyUri), tokenCredential);

암호화 옵션 구성

이제 Blob 업로드 및 다운로드에 사용할 암호화 옵션을 구성해야 합니다. 클라이언트 쪽 암호화를 사용하려면 먼저 ClientSideEncryptionOptions 개체를 만들고, 클라이언트를 만들 때 SpecializedBlobClientOptions를 사용하여 해당 개체를 설정합니다.

ClientSideEncryptionOptions 클래스는 클라이언트 쪽 암호화를 사용하여 Blob Storage에 연결하기 위한 클라이언트 구성 옵션을 제공합니다. KeyEncryptionKey는 업로드 작업에 필요하며 생성된 콘텐츠 암호화 키를 래핑하는 데 사용됩니다. KeyResolver는 다운로드 작업에 필요하며 다운로드한 콘텐츠 암호화 키를 래핑 해제하기 위해 올바른 키 암호화 키를 가져옵니다. KeyWrapAlgorithm은 업로드에 필요하며 콘텐츠 암호화 키를 래핑할 때 사용할 알고리즘 식별자를 지정합니다.

Important

버전 1의 보안 취약성으로 인해 버전 매개 변수에 ClientSideEncryptionVersion.V2_0를 사용하여 ClientSideEncryptionOptions 개체를 생성하는 것이 좋습니다. 앱의 취약성을 완화하는 방법에 대한 자세한 내용은 애플리케이션의 보안 취약성 완화를 참조하세요. 이 보안 취약성에 대한 자세한 내용은 보안 취약성을 해결하기 위해 SDK에서 클라이언트 쪽 암호화를 업데이트하는 Azure Storage를 참조하세요.

// Configure the encryption options to be used for upload and download
ClientSideEncryptionOptions encryptionOptions = new (ClientSideEncryptionVersion.V2_0)
{
    KeyEncryptionKey = cryptoClient,
    KeyResolver = keyResolver,
    // String value that the client library will use when calling IKeyEncryptionKey.WrapKey()
    KeyWrapAlgorithm = "RSA-OAEP"
};

// Set the encryption options on the client options.
BlobClientOptions options = new SpecializedBlobClientOptions() { ClientSideEncryption = encryptionOptions };

클라이언트 쪽 암호화를 사용하도록 클라이언트 개체 구성

이 예제에서는 클라이언트 쪽 암호화 구성 옵션을 BlobServiceClient 개체에 적용합니다. 서비스 클라이언트 수준에서 적용하면 이러한 암호화 옵션이 서비스 클라이언트에서 컨테이너 클라이언트로, 컨테이너 클라이언트에서 Blob 클라이언트로 전달됩니다. BlobClient 개체가 업로드 또는 다운로드 작업을 수행하는 경우 Azure Blob Storage 클라이언트 라이브러리는 봉투 암호화를 사용하여 클라이언트 쪽에서 Blob을 암호화 및 암호 해독합니다. 봉투 암호화는 하나 이상의 추가 키를 사용하여 키를 암호화합니다.

// Create a blob client with client-side encryption enabled.
// Attempting to construct a BlockBlobClient, PageBlobClient, or AppendBlobClient from a BlobContainerClient
// with client-side encryption options present will throw, as this functionality is only supported with BlobClient.
Uri blobUri = new (string.Format($"https://{accountName}.blob.core.windows.net"));
BlobClient blob = new BlobServiceClient(blobUri, tokenCredential, options).GetBlobContainerClient("test-container").GetBlobClient("testBlob");

Blob 암호화 및 업로드

BlobClient 개체가 upload 메서드를 호출하면 클라이언트 쪽 암호화를 수행하기 위한 다음과 같은 몇 가지 단계가 발생합니다.

  1. Azure Storage 클라이언트 라이브러리는 16바이트의 임의 IV(초기화 벡터) 및 32바이트의 임의 CEK(콘텐츠 암호화 키)를 생성하고, 이 정보를 사용하여 Blob 데이터의 봉투 암호화를 수행합니다.
  2. Blob 데이터가 CEK를 사용하여 암호화됩니다.
  3. 그런 다음, ClientSideEncryptionOptions에 지정된 키 암호화 KEK를 사용하여 CEK를 래핑(암호화)합니다. 이 예제에서 KEK는 지정된 Azure Key Vault 리소스에 저장된 비대칭 키 쌍입니다. Blob 클라이언트 자체는 KEK에 액세스할 수 없으며 Key Vault에서 제공하는 키 래핑 알고리즘을 호출하기만 합니다.
  4. 그러면 암호화된 Blob 데이터가 스토리지 계정에 업로드됩니다.

Blob을 암호화하고 Azure Storage 계정에 업로드하는 다음과 같은 코드를 추가합니다.

// Upload the encrypted contents to the blob
Stream blobContent = BinaryData.FromString("Ready for encryption, Captain.").ToStream();
await blob.UploadAsync(blobContent);

Blob이 업로드되면 스토리지 계정의 Blob을 보고 암호화된 콘텐츠와 암호화 메타데이터를 볼 수 있습니다.

Blob 암호 해독 및 다운로드

Azure Storage 클라이언트 라이브러리에서 사용자가 KEK를 로컬로 또는 Azure Key Vault에서 관리한다고 가정합니다. 사용자는 암호화에 사용된 특정 키를 알 필요가 없습니다. ClientSideEncryptionOptions에 지정된 키 확인자는 Blob 데이터를 다운로드하고 암호 해독할 때 키 식별자를 확인하는 데 사용됩니다.

BlobClient 개체가 download 메서드를 호출하면 암호화된 Blob 데이터의 암호를 해독하는 몇 가지 단계가 발생합니다.

  1. 클라이언트 라이브러리는 암호화 메타데이터를 포함하여 암호화된 Blob 데이터를 스토리지 계정에서 다운로드합니다.
  2. 그런 다음, 래핑된 CEK가 KEK를 사용하여 래핑 해제(암호 해독)됩니다. 클라이언트 라이브러리는 이 프로세스 중에 KEK에 액세스하지 않으며 ClientSideEncryptionOptions에 지정된 키 래핑 해제 알고리즘을 호출하지만 합니다. RSA 키 쌍의 프라이빗 키는 Key Vault에 남아 있으므로 CEK를 포함하는 Blob 메타데이터의 암호화된 키가 암호 해독을 위해 Key Vault로 전송됩니다.
  3. 클라이언트 라이브러리에서 CEK를 사용하여 암호화된 Blob 데이터의 암호를 해독합니다.

이전에 업로드한 Blob을 다운로드하고 암호 해독하려면 다음 코드를 추가합니다.

// Download and decrypt the encrypted contents from the blob
Response<BlobDownloadInfo>  response = await blob.DownloadAsync();
BlobDownloadInfo downloadInfo = response.Value;
Console.WriteLine((await BinaryData.FromStreamAsync(downloadInfo.Content)).ToString());

다음 단계

이 자습서에서는 .NET 클라이언트 라이브러리를 사용하여 Blob 업로드 및 다운로드 작업을 위한 클라이언트 쪽 암호화를 수행하는 방법을 알아보았습니다.

암호화된 데이터를 버전 2로 마이그레이션하는 지침을 포함하여 Blob에 대한 클라이언트 쪽 암호화에 대한 광범위한 개요는 Blob에 대한 클라이언트 쪽 암호화를 참조하세요.

Azure Key Vault에 대한 자세한 내용은 Azure Key Vault 개요 페이지를 참조하세요.