C#/기술 개발

C# 프로그램 락 기능

sheepone 2021. 6. 22. 11:52
반응형

해당 BIOS에서만 동작 검토

마더보드를 바꾸지 않고 실행파일의 하드를 포맷하지 않으면 유지

  • a. 프로그램 실행 루트 디렉토리에 db.lock 파일 생성후 안에 하드디스크 시리얼과 키값으로 암호화 하여 그값을 파일내에 저장
  • b. 프로그램 시작시 a의 값을 읽어 키값으로 복호화
  • c. 프로그램 시작시 Bios 시리얼 값을 읽어 키값으로 암호화
  • d. b와c의 값을 비교하여 일치하면 실행 아니면 메시지 알림후 종료

 

업데이트

  • 프로그램 새로 제작시 관련 PC들 모두 락파일 매번 만들어야 하는 문제
    암호화된 텍스트로 파일을 만들어 파일의 유무 검사 (단 장비 PC는 락파일 생성 필요)
  • 원격으로 파일을 만들어서 보내줄수 있는가 하는 문제  
    cmd에서 wmic baseboard get serialnumber로 메인보드 시리얼 획득 가능

 

using System;
using System.IO;
using System.Management;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApp37
{
    public partial class Form1 : Form
    {
        public readonly bool bBiosMake = true ;

        public Form1()
        {
            BiosLock(); //생성자에 추가
            InitializeComponent();
        }

        #region BiosLock
        private void BiosLock()
        {
            try
            {
                string mbInfo = String.Empty;
        
                ManagementScope scope = new ManagementScope("\\\\" + Environment.MachineName + "\\root\\cimv2");
                scope.Connect();
                ManagementObject wmiClass = new ManagementObject(scope, new ManagementPath("Win32_BaseBoard.Tag=\"Base Board\""), new ObjectGetOptions());
                
                foreach (PropertyData propData in wmiClass.Properties)
                {
                    if (propData.Name == "SerialNumber")
                        //mbInfo = String.Format("{0,-25}{1}", propData.Name, Convert.ToString(propData.Value));
                        mbInfo = Convert.ToString(propData.Value);
                }
                string sEncrypt = Encrypt(mbInfo,"동우의하루"); //암호화 키 입력
                sEncrypt = RemoveSpecialCharacters(sEncrypt);
                string sPath    = Path.GetPathRoot(System.Environment.CurrentDirectory) + sEncrypt + ".lock";
                //Debug.WriteLine(sPath);
                if (bBiosMake)
                {
                    if(!File.Exists(sPath)) File.Create(sPath);
                }

                if(!File.Exists(sPath)) { 
                    MessageBox.Show("Need license key","Error");
                    System.Environment.Exit(0);
                }
            }
            catch
            {
                MessageBox.Show("Need license key","Error");
                System.Environment.Exit(0);
            }
        }

        public static string Decrypt(string textToDecrypt, string key)
        {
            RijndaelManaged rijndaelCipher = new RijndaelManaged();
            rijndaelCipher.Mode = CipherMode.CBC;
            rijndaelCipher.Padding = PaddingMode.PKCS7;
            rijndaelCipher.KeySize = 128;
            rijndaelCipher.BlockSize = 128;

            byte[] encryptedData = Convert.FromBase64String(textToDecrypt);
            byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
            byte[] keyBytes = new byte[16];

            int len = pwdBytes.Length;
            if (len > keyBytes.Length)
            {
                len = keyBytes.Length;
            }

            Array.Copy(pwdBytes, keyBytes, len);
            rijndaelCipher.Key = keyBytes;
            rijndaelCipher.IV = keyBytes;
            byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length);
            return Encoding.UTF8.GetString(plainText);
        }

        public static string Encrypt(string textToEncrypt, string key)
        {
            RijndaelManaged rijndaelCipher = new RijndaelManaged();
            rijndaelCipher.Mode = CipherMode.CBC;
            rijndaelCipher.Padding = PaddingMode.PKCS7;
            rijndaelCipher.KeySize = 128;
            rijndaelCipher.BlockSize = 128;

            byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
            byte[] keyBytes = new byte[16];
            int len = pwdBytes.Length;
            if (len > keyBytes.Length)
            {
                len = keyBytes.Length;
            }
            Array.Copy(pwdBytes, keyBytes, len);
            rijndaelCipher.Key = keyBytes;
            rijndaelCipher.IV = keyBytes;
            ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
            byte[] plainText = Encoding.UTF8.GetBytes(textToEncrypt);
            return Convert.ToBase64String(transform.TransformFinalBlock(plainText, 0, plainText.Length));
        }

        public static string RemoveSpecialCharacters(string str)
        {
            char[] buffer = new char[str.Length];
            int idx = 0;

            foreach (char c in str)
            {
                if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z')
                    || (c >= 'a' && c <= 'z') || (c == '.') || (c == '_'))
                {
                    buffer[idx] = c;
                    idx++;
                }
            }

            return new string(buffer, 0, idx);
        }
        #endregion
    }
}

 

사용시 참조

  • 참조 추가 System.Management 필요
    (참조 - 참조추가 - 어셈블리 - System.Management)
  • 초기 락키 생성시
    public readonly bool bBiosMake = true ; 로 변경
    이후 사용시
    public readonly bool bBiosMake = false ; 로 사용
  • 암호화키 입력
    string sEncrypt = Encrypt(mbInfo,"동우의하루");

 

에러시 화면

 

 

 

반응형