다음을 통해 공유


방법: 데이터 보호 사용

참고 항목

이 문서는 Windows에 적용됩니다.

ASP.NET Core에 대한 자세한 내용은 ASP.NET Core 데이터 보호를 참조하세요.

.NET에서는 현재 사용자 계정이나 컴퓨터의 정보를 사용하여 데이터를 암호화할 수 있는 DPAPI(데이터 보호 API)에 대한 액세스를 제공합니다. DPAPI를 사용하는 경우 명시적으로 암호화 키를 생성 및 저장하는 어려운 문제가 완화됩니다.

ProtectedData 클래스를 사용하여 바이트 배열 복사본을 암호화합니다. 현재 사용자 계정에서 암호화된 데이터가 동일한 사용자 계정에 의해서만 암호 해독될 수 있도록 지정하거나, 현재 사용자 계정에서 암호화된 데이터가 컴퓨터의 모든 계정에 의해 암호 해독될 수 있도록 지정할 수 있습니다. ProtectedData 옵션에 대한 자세한 내용은 DataProtectionScope 열거형을 참조하세요.

데이터 보호를 사용하여 파일 또는 스트림에 데이터 암호화

  1. 임의 엔트로피를 만듭니다.

  2. 암호화할 바이트 배열, 엔트로피 및 데이터 보호 범위를 전달하는 동안 정적 Protect 메서드를 호출합니다.

  3. 파일 또는 스트림에 암호화된 데이터를 씁니다.

데이터 보호를 사용하여 파일 또는 스트림에서 데이터를 암호 해독하려면

  1. 파일 또는 스트림에서 암호화된 데이터를 읽습니다.

  2. 암호 해독할 바이트 배열 및 데이터 보호 범위를 전달하는 동안 정적 Unprotect 메서드를 호출합니다.

예시

다음 코드 예제에서는 두 가지 형태의 암호화 및 암호 해독을 보여 줍니다. 먼저 코드 예제에서 메모리 내 바이트 배열을 암호화한 다음 암호 해독합니다. 그런 다음 코드 예제에서 바이트 배열의 복사본을 암호화하고 파일에 저장한 다음 파일에서 다시 데이터를 로드하고 데이터를 암호 해독합니다. 이 예제에서는 원본 데이터, 암호화된 데이터 및 암호 해독된 데이터를 표시합니다.

using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;

public class MemoryProtectionSample
{
    public static void Main() => Run();

    public static void Run()
    {
        try
        {
            ///////////////////////////////
            //
            // Memory Encryption - ProtectedMemory
            //
            ///////////////////////////////

            // Create the original data to be encrypted (The data length should be a multiple of 16).
            byte[] toEncrypt = UnicodeEncoding.ASCII.GetBytes("ThisIsSomeData16");

            Console.WriteLine($"Original data: {UnicodeEncoding.ASCII.GetString(toEncrypt)}");
            Console.WriteLine("Encrypting...");

            // Encrypt the data in memory.
            EncryptInMemoryData(toEncrypt, MemoryProtectionScope.SameLogon);

            Console.WriteLine($"Encrypted data: {UnicodeEncoding.ASCII.GetString(toEncrypt)}");
            Console.WriteLine("Decrypting...");

            // Decrypt the data in memory.
            DecryptInMemoryData(toEncrypt, MemoryProtectionScope.SameLogon);

            Console.WriteLine($"Decrypted data: {UnicodeEncoding.ASCII.GetString(toEncrypt)}");

            ///////////////////////////////
            //
            // Data Encryption - ProtectedData
            //
            ///////////////////////////////

            // Create the original data to be encrypted
            toEncrypt = UnicodeEncoding.ASCII.GetBytes("This is some data of any length.");

            // Create a file.
            FileStream fStream = new FileStream("Data.dat", FileMode.OpenOrCreate);

            // Create some random entropy.
            byte[] entropy = CreateRandomEntropy();

            Console.WriteLine();
            Console.WriteLine($"Original data: {UnicodeEncoding.ASCII.GetString(toEncrypt)}");
            Console.WriteLine("Encrypting and writing to disk...");

            // Encrypt a copy of the data to the stream.
            int bytesWritten = EncryptDataToStream(toEncrypt, entropy, DataProtectionScope.CurrentUser, fStream);

            fStream.Close();

            Console.WriteLine("Reading data from disk and decrypting...");

            // Open the file.
            fStream = new FileStream("Data.dat", FileMode.Open);

            // Read from the stream and decrypt the data.
            byte[] decryptData = DecryptDataFromStream(entropy, DataProtectionScope.CurrentUser, fStream, bytesWritten);

            fStream.Close();

            Console.WriteLine($"Decrypted data: {UnicodeEncoding.ASCII.GetString(decryptData)}");
        }
        catch (Exception e)
        {
            Console.WriteLine($"ERROR: {e.Message}");
        }
    }

    public static void EncryptInMemoryData(byte[] Buffer, MemoryProtectionScope Scope )
    {
        if (Buffer == null)
            throw new ArgumentNullException(nameof(Buffer));
        if (Buffer.Length <= 0)
            throw new ArgumentException("The buffer length was 0.", nameof(Buffer));

        // Encrypt the data in memory. The result is stored in the same array as the original data.
        ProtectedMemory.Protect(Buffer, Scope);
    }

    public static void DecryptInMemoryData(byte[] Buffer, MemoryProtectionScope Scope)
    {
        if (Buffer == null)
            throw new ArgumentNullException(nameof(Buffer));
        if (Buffer.Length <= 0)
            throw new ArgumentException("The buffer length was 0.", nameof(Buffer));

        // Decrypt the data in memory. The result is stored in the same array as the original data.
        ProtectedMemory.Unprotect(Buffer, Scope);
    }

    public static byte[] CreateRandomEntropy()
    {
        // Create a byte array to hold the random value.
        byte[] entropy = new byte[16];

        // Create a new instance of the RNGCryptoServiceProvider.
        // Fill the array with a random value.
        new RNGCryptoServiceProvider().GetBytes(entropy);

        // Return the array.
        return entropy;
    }

    public static int EncryptDataToStream(byte[] Buffer, byte[] Entropy, DataProtectionScope Scope, Stream S)
    {
        if (Buffer == null)
            throw new ArgumentNullException(nameof(Buffer));
        if (Buffer.Length <= 0)
            throw new ArgumentException("The buffer length was 0.", nameof(Buffer));
        if (Entropy == null)
            throw new ArgumentNullException(nameof(Entropy));
        if (Entropy.Length <= 0)
            throw new ArgumentException("The entropy length was 0.", nameof(Entropy));
        if (S == null)
            throw new ArgumentNullException(nameof(S));

        int length = 0;

        // Encrypt the data and store the result in a new byte array. The original data remains unchanged.
        byte[] encryptedData = ProtectedData.Protect(Buffer, Entropy, Scope);

        // Write the encrypted data to a stream.
        if (S.CanWrite && encryptedData != null)
        {
            S.Write(encryptedData, 0, encryptedData.Length);

            length = encryptedData.Length;
        }

        // Return the length that was written to the stream.
        return length;
    }

    public static byte[] DecryptDataFromStream(byte[] Entropy, DataProtectionScope Scope, Stream S, int Length)
    {
        if (S == null)
            throw new ArgumentNullException(nameof(S));
        if (Length <= 0 )
            throw new ArgumentException("The given length was 0.", nameof(Length));
        if (Entropy == null)
            throw new ArgumentNullException(nameof(Entropy));
        if (Entropy.Length <= 0)
            throw new ArgumentException("The entropy length was 0.", nameof(Entropy));

        byte[] inBuffer = new byte[Length];
        byte[] outBuffer;

        // Read the encrypted data from a stream.
        if (S.CanRead)
        {
            S.Read(inBuffer, 0, Length);

            outBuffer = ProtectedData.Unprotect(inBuffer, Entropy, Scope);
        }
        else
        {
            throw new IOException("Could not read the stream.");
        }

        // Return the decrypted data
        return outBuffer;
    }
}
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography



Public Module MemoryProtectionSample

    Sub Main()
        Run()

    End Sub


    Sub Run()
        Try

            ''''''''''''''''''''''''''''''''''''
            '
            ' Memory Encryption - ProtectedMemory
            '
            ''''''''''''''''''''''''''''''''''''
            ' Create the original data to be encrypted (The data length should be a multiple of 16).
            Dim toEncrypt As Byte() = UnicodeEncoding.ASCII.GetBytes("ThisIsSomeData16")

            Console.WriteLine("Original data: " + UnicodeEncoding.ASCII.GetString(toEncrypt))
            Console.WriteLine("Encrypting...")

            ' Encrypt the data in memory.
            EncryptInMemoryData(toEncrypt, MemoryProtectionScope.SameLogon)

            Console.WriteLine("Encrypted data: " + UnicodeEncoding.ASCII.GetString(toEncrypt))
            Console.WriteLine("Decrypting...")

            ' Decrypt the data in memory.
            DecryptInMemoryData(toEncrypt, MemoryProtectionScope.SameLogon)

            Console.WriteLine("Decrypted data: " + UnicodeEncoding.ASCII.GetString(toEncrypt))


            ''''''''''''''''''''''''''''''''''''
            '
            ' Data Encryption - ProtectedData
            '
            ''''''''''''''''''''''''''''''''''''
            ' Create the original data to be encrypted
            toEncrypt = UnicodeEncoding.ASCII.GetBytes("This is some data of any length.")

            ' Create a file.
            Dim fStream As New FileStream("Data.dat", FileMode.OpenOrCreate)

            ' Create some random entropy.
            Dim entropy As Byte() = CreateRandomEntropy()

            Console.WriteLine()
            Console.WriteLine("Original data: " + UnicodeEncoding.ASCII.GetString(toEncrypt))
            Console.WriteLine("Encrypting and writing to disk...")

            ' Encrypt a copy of the data to the stream.
            Dim bytesWritten As Integer = EncryptDataToStream(toEncrypt, entropy, DataProtectionScope.CurrentUser, fStream)

            fStream.Close()

            Console.WriteLine("Reading data from disk and decrypting...")

            ' Open the file.
            fStream = New FileStream("Data.dat", FileMode.Open)

            ' Read from the stream and decrypt the data.
            Dim decryptData As Byte() = DecryptDataFromStream(entropy, DataProtectionScope.CurrentUser, fStream, bytesWritten)

            fStream.Close()

            Console.WriteLine("Decrypted data: " + UnicodeEncoding.ASCII.GetString(decryptData))


        Catch e As Exception
            Console.WriteLine("ERROR: " + e.Message)
        End Try

    End Sub



    Sub EncryptInMemoryData(ByVal Buffer() As Byte, ByVal Scope As MemoryProtectionScope)
        If Buffer Is Nothing Then
            Throw New ArgumentNullException("Buffer")
        End If
        If Buffer.Length <= 0 Then
            Throw New ArgumentException("Buffer")
        End If

        ' Encrypt the data in memory. The result is stored in the same array as the original data.
        ProtectedMemory.Protect(Buffer, Scope)

    End Sub


    Sub DecryptInMemoryData(ByVal Buffer() As Byte, ByVal Scope As MemoryProtectionScope)
        If Buffer Is Nothing Then
            Throw New ArgumentNullException("Buffer")
        End If
        If Buffer.Length <= 0 Then
            Throw New ArgumentException("Buffer")
        End If

        ' Decrypt the data in memory. The result is stored in the same array as the original data.
        ProtectedMemory.Unprotect(Buffer, Scope)

    End Sub


    Function CreateRandomEntropy() As Byte()
        ' Create a byte array to hold the random value.
        Dim entropy(15) As Byte

        ' Create a new instance of the RNGCryptoServiceProvider.
        ' Fill the array with a random value.
        Dim RNG As New RNGCryptoServiceProvider()

        RNG.GetBytes(entropy)

        ' Return the array.
        Return entropy

    End Function 'CreateRandomEntropy



    Function EncryptDataToStream(ByVal Buffer() As Byte, ByVal Entropy() As Byte, ByVal Scope As DataProtectionScope, ByVal S As Stream) As Integer
        If Buffer Is Nothing Then
            Throw New ArgumentNullException("Buffer")
        End If
        If Buffer.Length <= 0 Then
            Throw New ArgumentException("Buffer")
        End If
        If Entropy Is Nothing Then
            Throw New ArgumentNullException("Entropy")
        End If
        If Entropy.Length <= 0 Then
            Throw New ArgumentException("Entropy")
        End If
        If S Is Nothing Then
            Throw New ArgumentNullException("S")
        End If
        Dim length As Integer = 0

        ' Encrypt the data and store the result in a new byte array. The original data remains unchanged.
        Dim encryptedData As Byte() = ProtectedData.Protect(Buffer, Entropy, Scope)

        ' Write the encrypted data to a stream.
        If S.CanWrite AndAlso Not (encryptedData Is Nothing) Then
            S.Write(encryptedData, 0, encryptedData.Length)

            length = encryptedData.Length
        End If

        ' Return the length that was written to the stream. 
        Return length

    End Function 'EncryptDataToStream


    Function DecryptDataFromStream(ByVal Entropy() As Byte, ByVal Scope As DataProtectionScope, ByVal S As Stream, ByVal Length As Integer) As Byte()
        If S Is Nothing Then
            Throw New ArgumentNullException("S")
        End If
        If Length <= 0 Then
            Throw New ArgumentException("Length")
        End If
        If Entropy Is Nothing Then
            Throw New ArgumentNullException("Entropy")
        End If
        If Entropy.Length <= 0 Then
            Throw New ArgumentException("Entropy")
        End If


        Dim inBuffer(Length - 1) As Byte
        Dim outBuffer() As Byte

        ' Read the encrypted data from a stream.
        If S.CanRead Then
            S.Read(inBuffer, 0, Length)

            outBuffer = ProtectedData.Unprotect(inBuffer, Entropy, Scope)
        Else
            Throw New IOException("Could not read the stream.")
        End If

        ' Return the unencrypted data as byte array. 
        Return outBuffer

    End Function 'DecryptDataFromStream 
End Module 'MemoryProtectionSample

코드 컴파일

이 예는 .NET Framework를 대상으로 하고 Windows에서 실행되는 경우에만 컴파일하고 실행됩니다.

참고 항목