파일에 암호를 걸 때 보통은 알집 같은 압축 프로그램으로 묶으면서 비밀번호를 넣습니다. 그런데 매번 압축하고 풀기가 번거롭고, 폴더 안 파일을 원래 이름 그대로 두고 내용만 잠가 두고 싶을 때도 있죠. 이럴 때 쓸 수 있는 방법을 두 가지 적어 둡니다. 하나는 Windows에 들어 있는 기능이고, 다른 하나는 제가 만들어 올린 무료 프로그램입니다.

Windows 기본 기능(EFS)으로 암호화

Windows 10 Pro 이상에는 파일 시스템 차원의 암호화 기능이 있습니다. Home 에디션에서는 이 메뉴가 비활성화돼 있어서 쓸 수 없습니다.

광고

방법은 간단합니다. 암호화할 파일이나 폴더를 마우스 오른쪽 버튼으로 눌러 속성을 열고, 일반 탭의 고급 버튼을 누릅니다. 고급 특성 창에서 "데이터 보호를 위해 내용을 암호화"에 체크하고 확인, 다시 속성 창에서 적용과 확인을 누르면 끝입니다. 적용되면 아이콘에 자물쇠 표시가 붙습니다.

Windows 탐색기에서 EFS로 암호화되어 자물쇠 아이콘이 붙은 파일

이 방식은 비밀번호를 따로 묻지 않습니다. 현재 Windows 사용자 계정의 인증서로 암호화되기 때문에, 같은 계정으로 로그인한 상태에서는 평소처럼 열리고 다른 계정이나 다른 PC에서는 열리지 않습니다. 편하지만 그 계정 인증서를 잃어버리면(Windows 재설치 등) 본인도 못 여는 상황이 생기니, 인증서 백업을 같이 해 두는 게 안전합니다. 또 파일을 USB나 메일로 다른 곳에 보내면 암호화가 풀린 채로 나갈 수 있어서, "파일 자체에 비밀번호를 거는" 용도와는 조금 다릅니다.

무료 프로그램으로 폴더 통째로 암호화

비밀번호로 잠그고, 다른 PC로 옮겨도 잠긴 상태가 유지되길 원하면 프로그램으로 파일 내용 자체를 암호화하는 쪽이 맞습니다. 게시글 첨부파일을 내려받아 압축을 풀면 실행 파일이 나옵니다.

첨부파일 압축을 해제한 폴더 화면

프로그램을 실행해서 대상 폴더를 지정하고 암호를 입력한 뒤, Encryption 에 체크하고 "적 용" 버튼을 누르면 폴더 안 파일들이 암호화됩니다.

폴더와 암호를 입력하고 Encryption을 선택한 프로그램 화면

암호화가 끝나면 이미지 파일의 미리 보기가 깨져서 엑박으로 표시됩니다. 파일 이름과 확장자는 그대로인데 내용이 바뀌었기 때문에 프로그램들이 더 이상 이미지로 읽지 못하는 겁니다.

암호화 후 미리 보기가 엑박으로 표시되는 이미지 파일들

되돌릴 때는 같은 폴더와 같은 암호를 넣고 Decryption 에 체크한 뒤 "적 용"을 누릅니다.

Decryption을 선택해 복호화하는 프로그램 화면

복호화되면 미리 보기가 다시 정상으로 나옵니다.

복호화 후 이미지 미리 보기가 정상으로 돌아온 화면

내부에서 쓰는 암호화 코드

프로그램 안에서는 아래 두 함수로 파일 바이트를 암호화·복호화합니다. 입력 비밀번호를 MD5로 해시해 16바이트를 얻고, 이걸 32바이트 배열에 두 번 복사해서 AES(RijndaelManaged) 키로 씁니다. 비밀번호를 비워 두면 클래스에 정의된 기본 키 enckey 를 대문자로 바꿔 사용합니다.

        Public Shared Function Encrypt(ByVal input() As Byte, Optional ByVal pass As String = "") As Byte()
            Dim AES As New System.Security.Cryptography.RijndaelManaged
            Dim Hash_AES As New System.Security.Cryptography.MD5CryptoServiceProvider
            If pass.Length = 0 Then pass = enckey.ToUpper
            Dim encrypted As String = ""
            Try
                Dim hash(31) As Byte
                Dim temp As Byte() = Hash_AES.ComputeHash(System.Text.Encoding.UTF8.GetBytes(pass))
                Array.Copy(temp, 0, hash, 0, 16)
                Array.Copy(temp, 0, hash, 15, 16)
                AES.Key = hash
                AES.Mode = Security.Cryptography.CipherMode.ECB
                Dim DESEncrypter As System.Security.Cryptography.ICryptoTransform = AES.CreateEncryptor
                Return DESEncrypter.TransformFinalBlock(input, 0, input.Length)
            Catch ex As Exception
                Return Nothing
            End Try
        End Function

        Public Shared Function Decrypt(ByVal input() As Byte, Optional ByVal pass As String = "") As Byte()
            Dim AES As New System.Security.Cryptography.RijndaelManaged
            Dim Hash_AES As New System.Security.Cryptography.MD5CryptoServiceProvider
            If pass.Length = 0 Then pass = enckey.ToUpper
            Dim decrypted As String = ""
            Try
                Dim hash(31) As Byte
                Dim temp As Byte() = Hash_AES.ComputeHash(System.Text.Encoding.UTF8.GetBytes(pass))
                Array.Copy(temp, 0, hash, 0, 16)
                Array.Copy(temp, 0, hash, 15, 16)
                AES.Key = hash
                AES.Mode = Security.Cryptography.CipherMode.ECB
                Dim DESDecrypter As System.Security.Cryptography.ICryptoTransform = AES.CreateDecryptor
                Return DESDecrypter.TransformFinalBlock(input, 0, input.Length)
            Catch ex As Exception
                Return Nothing
            End Try
        End Function

두 번째 Array.Copy 가 15번 위치부터 복사하기 때문에 15번 바이트는 덮어쓰이고 마지막 31번 바이트는 0으로 남습니다. 암호화와 복호화가 같은 방식으로 키를 만드니 동작에는 문제가 없지만, 이 코드를 가져다 다른 프로그램과 호환되게 만들 생각이라면 이 점을 그대로 맞춰야 합니다.

복호화할 때 암호가 틀리면 TransformFinalBlock 에서 패딩 오류가 나면서 Nothing 이 반환됩니다. 호출하는 쪽에서 Nothing 을 확인하지 않고 파일에 쓰면 원본을 날릴 수 있으니, 결과를 검사한 뒤 저장하도록 짜야 합니다.

참고로 ECB 모드는 같은 내용의 블록이 같은 결과로 바뀌어서 데이터 패턴이 드러나는 약점이 있습니다. 개인 파일을 남이 쉽게 못 열게 막는 용도로는 충분하지만, 중요한 데이터를 보호하는 용도로 새로 만든다면 CBC 같은 모드에 IV를 함께 쓰고 키도 MD5 대신 Rfc2898DeriveBytes 로 만드는 편이 낫습니다. 그리고 어떤 방식이든 암호를 잊으면 복구할 방법이 없으니, 처음엔 사본 폴더로 먼저 시험해 보세요.