C# AES 파일 암호화/복호화

Benedictus Park·2022년 12월 15일
0

C#

목록 보기
1/2
post-thumbnail

1. 개요

C#에서는 RijndaelManaged 객체와 CryptoStream 객체를 이용해 파일을 암호화 할 수 있습니다.

2. 사용하는 라이브러리

  • System.IO
  • System.Security.Cryptography

3-1. 예제(암호화)

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

namespace test
{
    class Program
    {
        static void Main()
        {
            int count, blockSizeBytes;
            byte[] data;
            RijndaelManaged aes = new RijndaelManaged();
            ICryptoTransform encryptor;
            CryptoStream cryptoStream;
            FileStream inFs, outFs;

            aes.KeySize = 256;
            aes.BlockSize = 128;
            aes.Padding = PaddingMode.PKCS7;
            aes.Mode = CipherMode.CBC;

            aes.GenerateKey();
            aes.GenerateIV();

            encryptor = aes.CreateEncryptor();

            inFs = new FileStream("test.jpg", FileMode.Open);
            outFs = new FileStream("test.jpg.encrypted", FileMode.Create);

            cryptoStream = new CryptoStream(outFs, encryptor, CryptoStreamMode.Write);

            blockSizeBytes = aes.BlockSize / 8;
            data = new byte[blockSizeBytes];
            do
            {
                count = inFs.Read(data, 0, blockSizeBytes);
                cryptoStream.Write(data, 0, count);
            }
            while (count > 0);

            inFs.Close();

            cryptoStream.FlushFinalBlock();
            cryptoStream.Close();

            outFs.Close()
    }
}
  • aes.KeySize로 Key Size를, aes.BlockSize로 BlockSize를, aes.Padding으로 Padding Mode를, aes.Mode로 Cipher Mode를 지정해 줍니다.
  • 이후 aes.GenerateKey() 메서드로 AES Key를 자동 생성합니다.
  • aes.GenerateIV() 메서드로 AES IV를 자동 생성합니다.
  • Key와 IV를 직접 Byte Array 형태로 만들어 aes.Key와 aes.IV에 할당해주셔도 상관은 없습니다.
  • aes.CreateEncryptor 메서드로 Encryptor 객체를 생성해 ICryptoTransform encryptor 변수에 담아줍니다.
  • 마지막으로 cryptorStream 객체를 만들어 줍니다.
  • cryptoStream 객체를 통해 데이터를 쓰면, 그 데이터가 암호화된 후 outFs 스트림을 통해 파일로 들어가게 됩니다.
  • 여기서 Stream은 무엇이든 사용 가능합니다. 그것이 NetworkStream이든, MemoryStream이든 상관 없습니다. 저는 메모리의 크기를 초과할 정도로 큰 파일을 암호화 할 경우를 염두하여 FileStream에서 데이터를 읽어 FileStream에 쓰는 방식으로 코딩을 했습니다.
.
.
.
cryptoStream = new CryptoStream(inFs, encryptor, CryptoStreamMode.Read);

blockSizeBytes = aes.BlockSize / 8;
data = new byte[blockSizeBytes];
do
{
    count = cryptoStream.Read(data, 0, blockSizeBytes);
    outFs.Write(data, 0, count);
}
while (count > 0);
.
.
.
  • 이런 식으로 CryptoStream의 생성자에 inFs를 넣고 CryptoStreamMode를 Read로 하여, CryptoStream으로부터 데이터를 읽고 파일에 Write로 하는 방법도 있습니다.

3-2. 예제(복호화)

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

namespace test
{
    class Program
    {
        static void Main()
        {
            int count, blockSizeBytes;
            byte[] data;
            RijndaelManaged aes = new RijndaelManaged();
            ICryptoTransform decryptor;
            CryptoStream cryptoStream;
            FileStream inFs, outFs;

            aes.KeySize = 256;
            aes.BlockSize = 128;
            aes.Padding = PaddingMode.PKCS7;
            aes.Mode = CipherMode.CBC;

            aes.key = [AES Key Bytes];
            aes.iv = [AES IV Bytes];

            encryptor = aes.CreateDecryptor();

            inFs = new FileStream("test.jpg.encrypted", FileMode.Open);
            outFs = new FileStream("test.jpg", FileMode.Create);

            cryptoStream = new CryptoStream(outFs, decryptor, CryptoStreamMode.Write);

            blockSizeBytes = aes.BlockSize / 8;
            data = new byte[blockSizeBytes];
            do
            {
                count = inFs.Read(data, 0, blockSizeBytes);
                cryptoStream.Write(data, 0, count);
            }
            while (count > 0);

            inFs.Close();

            cryptoStream.FlushFinalBlock();
            cryptoStream.Close();

            outFs.Close()
    }
}
  • Encryptor를 Decryptor로 변경하고, Key와 IV를 직접 할당해주어야 한다는 것 외에는 차이점이 없습니다.
using System.IO;
using System.Security.Cryptography;

namespace test
{
    class Program
    {
        static void Main()
        {
            int count, blockSizeBytes;
            byte[] data;
            RijndaelManaged aes = new RijndaelManaged();
            ICryptoTransform decryptor;
            CryptoStream cryptoStream;
            FileStream inFs, outFs;

            aes.KeySize = 256;
            aes.BlockSize = 128;
            aes.Padding = PaddingMode.PKCS7;
            aes.Mode = CipherMode.CBC;
            
            key = ~~~
            iv = ~~~

            encryptor = aes.CreateDecryptor(key, iv);

            inFs = new FileStream("test.jpg.encrypted", FileMode.Open);
            outFs = new FileStream("test.jpg", FileMode.Create);

            cryptoStream = new CryptoStream(outFs, decryptor, CryptoStreamMode.Write);

            blockSizeBytes = aes.BlockSize / 8;
            data = new byte[blockSizeBytes];
            do
            {
                count = inFs.Read(data, 0, blockSizeBytes);
                cryptoStream.Write(data, 0, count);
            }
            while (count > 0);

            inFs.Close();

            cryptoStream.FlushFinalBlock();
            cryptoStream.Close();

            outFs.Close()
    }
}
  • Key와 IV를 꼭 aes.Key와 aes.IV에 할당해주어야 하는 것은 아닙니다. CreateDecryptor 메서드의 인자로 Key Byte Array와 IV Byte Array를 직접 넘겨주셔도 됩니다.

0개의 댓글