데이터 보호: 데이터 보호 구성하기

등록일시: 2017-04-14 08:00,  수정일시: 2017-08-09 10:00
조회수: 4,664
이 문서는 ASP.NET Core 기술을 널리 알리고자 하는 개인적인 취지로 제공되는 번역문서입니다. 이 문서에 대한 모든 저작권은 마이크로소프트에 있으며 요청이 있을 경우 언제라도 게시가 중단될 수 있습니다. 번역 내용에 오역이 존재할 수 있고 주석은 번역자 개인의 의견일 뿐이며 마이크로소프트는 이에 관한 어떠한 보장도 하지 않습니다. 번역이 완료된 이후에도 대상 제품 및 기술이 개선되거나 변경됨에 따라 원문의 내용도 변경되거나 보완되었을 수 있으므로 주의하시기 바랍니다.
본문에서는 다양한 API를 사용해서 데이터 보호 시스템을 구성하는 방법을 살펴봅니다.

데이터 보호 시스템이 초기화 될 때, 운영 환경에 따라서 자체적으로 일부 기본 설정이 적용됩니다. 일반적으로 이런 기본 설정은 단일 머신에서 실행되는 응용 프로그램에 적합한 경우가 많습니다. 그러나 때로는 응용 프로그램이 여러 머신에 분산되어 배포되기 때문에, 또는 규정을 준수하기 위해서 개발자가 이런 설정을 변경해야 하는 경우도 존재하며, 데이터 보호 시스템은 이런 시나리오를 지원하기 위한 다양한 풍부한 API들을 제공합니다.

먼저 연이어 함께 호출하는 방식으로 다양한 데이터 보호 옵션을 구성할 수 있는 메서드들을 자체적으로 노출하는 IDataProtectionBuilder를 반환하는 AddDataProtection 확장 메서드가 제공됩니다. 예를 들어서, %LOCALAPPDATA% (기본값) 대신 UNC 공유에 키를 저장하려면 다음과 같이 시스템을 구성합니다:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
            .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));
}
주의

키의 저장 위치를 변경하면 데이터 보호 시스템이 더 이상 저장된 비활성 키를 자동으로 암호화하지 않는데, 이는 DPAPI가 적절한 암호화 메커니즘인지 판단하기가 곤란하기 때문입니다.

ProtectKeysWith* 구성 API들 중 하나를 호출하면 시스템이 저장된 비활성 키를 보호하도록 구성할 수 있습니다. 다음 예제는 키를 UNC 공유에 저장하고 특정 X.509 인증서를 이용해서 저장된 비활성 키를 암호화합니다:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
            .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
            .ProtectKeysWithCertificate("thumbprint");
}

내장 키 암호화 메커니즘에 대한 더 많은 예제와 설명은 Key Encryption At Rest 문서를 참고하시기 바랍니다.

다음 예제는 기본 키 수명을 90일 대신 14일로 지정하도록 시스템을 구성합니다:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
            .SetDefaultKeyLifetime(TimeSpan.FromDays(14));
}

기본적으로 데이터 보호 시스템은 응용 프로그램들이 동일한 물리적 키 저장소를 공유하는 경우에도 응용 프로그램들을 서로 격리합니다. 따라서 응용 프로그램들은 서로 다른 응용 프로그램이 보호한 페이로드를 이해할 수 없습니다. 서로 다른 두 응용 프로그램 간에 보호된 페이로드를 공유하려면, 다음과 같이 두 응용 프로그래 모두에 동일한 응용 프로그램 이름을 전달해서 시스템을 구성해야 합니다:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
            .SetApplicationName("my application");
}

마지막으로, 키 만료가 다가오더라도 응용 프로그램이 자동으로 키를 롤링하지 않도록 구성해야 하는 시나리오도 있을 수 있습니다. 한 가지 사례는 응용 프로그램들이 주/보조 관계를 갖도록 설정되어 있어서 주 응용 프로그램만 키 관리 작업을 수행하고 나머지 모든 보조 응용 프로그램들은 단순히 키 링의 읽기 전용 뷰만 갖고 있는 경우입니다. 그런 경우에는, 다음과 같이 시스템을 구성해서 보조 응용 프로그램은 키 링을 읽기 전용으로만 처리하도록 구성할 수 있습니다:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
            .DisableAutomaticKeyGeneration();
}

응용 프로그램 별 격리

ASP.NET Core 호스트에 의해서 데이터 보호 시스템이 제공되는 경우, 여러 응용 프로그램들이 동일한 작업자 프로세스 계정으로 실행되고 동일한 마스터 키 관련 자료를 사용하더라도 서로 자동으로 격리됩니다. 이런 특징은 System.Web의 <machinekey> 요소에서 제공되는 IsolateApps 수정자의 동작과 다소 유사합니다.

이 격리 메커니즘은 로컬 머신의 각각의 응용 프로그램들을 고유한 테넌트로 간주하는 방식으로 동작하며, 따라서 해당하는 모든 응용 프로그램에 루트로 제공되는 IDataProtector에는 자동으로 응용 프로그램 ID가 판별자로 포함됩니다. 여기에 사용되는 응용 프로그램 고유 ID는 다음 두 가지 방법 중 한 가지 방식으로 얻어집니다.

  1. 응용 프로그램이 IIS에서 호스트 될 경우, 응용 프로그램의 구성 경로가 고유 식별자로 사용됩니다. 만약 응용 프로그램이 팜 환경에 배포된다면 팜에 포함된 모든 머신 간에 IIS 환경이 비슷하게 구성되었다는 전제 하에 이 값이 일정해야 합니다.

  2. 응용 프로그램이 IIS에서 호스트 되지 않을 경우, 응용 프로그램의 물리적 경로가 고유 식별자로 사용됩니다.

고유 식별자는 개별 응용 프로그램 및 머신 자체가 재설정되더라도 유지되도록 설계되었습니다.

이 격리 메커니즘은 응용 프로그램에 악의적인 의사가 없음을 전제로 합니다. 악의적인 응용 프로그램은 언제든지 동일한 작업자 프로세스 계정으로 동작하는 다른 모든 응용 프로그램에 영향을 미칠 수 있습니다. 응용 프로그램들 간에 서로 신뢰할 수 없는 공유 호스팅 환경에서는 호스팅 공급자가 응용 프로그램의 기본 키 저장소를 분리하는 등, OS 수준에서 응용 프로그램 간의 격리를 담보할 수 있는 조취를 취해야만 합니다.

데이터 보호 시스템이 ASP.NET Core 호스트에 의해서 제공되지 않는 경우에는 (가령, 개발자가 직접 구체적인 DataProtectionProvider 형식을 이용해서 인스턴스를 생성하는 등), 자동으로 응용 프로그램 격리가 비활성화되며 적절한 용도를 제공하기만 하면 동일한 키 관련 자료를 사용하는 모든 응용 프로그램들 간에 페이로드를 공유할 수 있습니다. 이런 환경에서 응용 프로그램 간 격리를 제공하려면 앞에서 살펴본 예제처럼 구성 개체의 SetApplicationName 메서드를 호출하면 됩니다.

알고리즘 변경하기

새로 생성된 키에 의해 사용되는 데이터 보호 스택의 기본 알고리즘을 변경할 수도 있습니다. 이 작업을 수행하는 가장 간단한 방법은 다음 예제와 같이 구성 콜백에서 UseCryptographicAlgorithms 메서드를 호출하는 것입니다.

services.AddDataProtection()
    .UseCryptographicAlgorithms(new AuthenticatedEncryptionSettings()
    {
        EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
        ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
    });

EncryptionAlgorithm 및 ValidationAlgorithm의 기본값은 각각 AES-256-CBC와 HMACSHA256 입니다. 시스템 관리자가 머신 수준 정책을 통해서 기본 정책을 설정할 수도 있지만, 명시적으로 UseCryptographicAlgorithms 메서드를 호출하면 기본 정책이 재정의 됩니다.

UseCryptographicAlgorithms 메서드를 호출하면 개발자가 알고리즘 구현을 걱정할 필요 없이 미리 제공되는 목록 중에서 원하는 알고리즘을 지정할 수 있습니다. 예를 들어서, 위의 시나리오에서 데이터 보호 시스템이 Windows에서 실행 중이라면 AES의 CNG 구현을 사용하려고 시도하고, 그렇지 않으면 관리되는 System.Security.Cryptography.Aes 클래스로 대체됩니다.

필요한 경우, 개발자는 다음 예제와 같이 UseCustomCryptographicAlgorithms 메서드를 호출해서 원하는 구현을 직접 수작업으로 지정할 수도 있습니다.

알고리즘을 변경하더라도 키 링에 존재하는 기존 키에는 영향을 주지 않습니다. 알고리즘 변경은 새로 생성되는 키에만 영향을 줍니다.

관리되는 사용자 지정 알고리즘 지정하기

관리되는 사용자 지정 알고리즘을 지정하려면, 구현 형식을 가리키는 ManagedAuthenticatedEncryptionSettings의 인스턴스를 생성합니다.

serviceCollection.AddDataProtection()
    .UseCustomCryptographicAlgorithms(new ManagedAuthenticatedEncryptionSettings()
    {
        // a type that subclasses SymmetricAlgorithm
        EncryptionAlgorithmType = typeof(Aes),

        // specified in bits
        EncryptionAlgorithmKeySize = 256,

        // a type that subclasses KeyedHashAlgorithm
        ValidationAlgorithmType = typeof(HMACSHA256)
    });

일반적으로 *Type 속성들은 구체적인, 인스턴스를 생성할 수 있는 (매개변수가 없는 public 생성자를 통해서) SymmetricAlgorithm 및 KeyedHashAlgorithm의 구현을 가리켜야 하지만, 시스템 상 특수한 경우에는 편의를 위해 typeof(Aes) 같은 특정 값들을 지정하기도 합니다.

노트

SymmetricAlgorithm은 반드시 키 길이가 128 비트 이상이고 블럭 크키가 64 비트 이상이어야 하며, PKCS #7 패딩을 사용하는 CBC 모드 암호화를 지원해야 합니다. KeyedHashAlgorithm은 다이제스트 크기가 128 비트 이상이어야 하고, 해시 알고리즘의 다이제스트 길이와 동일한 키 길이를 지원해야 합니다. KeyedHashAlgorithm이 반드시 HMAC여야 할 필요는 없습니다.

사용자 지정 Windows CNG 알고리즘 지정하기

CBC 모드 암호화 + HMAC 유효성 검사를 사용하는 사용자 지정 Windows CNG 알고리즘을 지정하려면, 알고리즘 정보를 담고 있는 CngCbcAuthenticatedEncryptionSettings의 인스턴스를 생성합니다.

services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(new CngCbcAuthenticatedEncryptionSettings()
    {
        // passed to BCryptOpenAlgorithmProvider
        EncryptionAlgorithm = "AES",
        EncryptionAlgorithmProvider = null,

        // specified in bits
        EncryptionAlgorithmKeySize = 256,

        // passed to BCryptOpenAlgorithmProvider
        HashAlgorithm = "SHA256",
        HashAlgorithmProvider = null
    });
노트

대칭형 블럭 암호화 알고리즘(Symmetric Block Cipher Algorithm)은 반드시 키 길이가 128 비트 이상이고 블럭 크키가 64 비트 이상이어야 하며, PKCS #7 패딩을 사용하는 CBC 모드 암호화를 지원해야 합니다. 해시 알고리즘은 다이제스트 크기가 128 비트 이상이어야 하고, BCRYPT_ALG_HANDLE_HMAC_FLAG 플래그로 시작할 수 있도록 지원해야 합니다. *Provider 속성들을 null로 설정해서 지정된 알고리즘에 대한 기본 공급자를 사용할 수 있습니다. 보다 자세한 정보는 BCryptOpenAlgorithmProvider 문서를 참고하시기 바랍니다.

갈루아(Galois)/카운터 모드 암호화 + 유효성 검사를 사용하는 사용자 지정 Windows CNG 알고리즘을 지정하려면, 알고리즘 정보를 담고 있는 CngGcmAuthenticatedEncryptionSettings의 인스턴스를 생성합니다.

services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(new CngGcmAuthenticatedEncryptionSettings()
    {
        // passed to BCryptOpenAlgorithmProvider
        EncryptionAlgorithm = "AES",
        EncryptionAlgorithmProvider = null,

        // specified in bits
        EncryptionAlgorithmKeySize = 256
    });
노트

대칭형 블럭 암호화 알고리즘(Symmetric Block Cipher Algorithm)은 반드시 키 길이가 128 비트 이상이고 블럭 크키가 정확히 128 비트여야 하며, GCM 암호화를 지원해야 합니다. EncryptionAlgorithmProvider 속성을 null로 설정해서 지정된 알고리즘에 대한 기본 공급자를 사용할 수 있습니다. 보다 자세한 정보는 BCryptOpenAlgorithmProvider 문서를 참고하시기 바랍니다.

다른 사용자 지정 알고리즘 지정하기

비록 기본적인 API로 제공되지는 않았지만 데이터 보호 시스템은 거의 모든 유형의 알고리즘을 지정할 수 있도록 충분한 확장이 가능합니다. 예를 들어서, HSM 내에 포함된 모든 키들을 유지하고, 핵심 암호화 및 복호화 루틴의 사용자 지정 구현을 제공하는 것도 가능합니다. 보다 자세한 정보는 핵심 암호화 확장성(Core Cryptography Extensibility) 문서의 IAuthenticatedEncryptorConfiguration 절을 참고하시기 바랍니다.

참고자료

비-DI 인식 시나리오

머신 수준 정책