즐겁게 개발을...

개발보다 게임이 더 많이 올라오는 것 같은...

개발/C#

[2022.09] 맥 어드레스를 이용한 라이선스 기법

다물칸 2022. 9. 20. 20:22
728x90
반응형

단순한 맥어드레스를 이용한 라이선스를 프로그램에 적용시켜봅시다. 

 

우선 클래스 투척합니다.

 

public class LicGenerator
    {
        // base64 + Sha256 Hash
        public string CalculateHash(string rawData)
        {
            // Create a SHA256   
            using (SHA256 sha256Hash = SHA256.Create())
            {
                // ComputeHash - returns byte array  
                byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));

                // Convert byte array to a string   
                StringBuilder builder = new StringBuilder();
                for (int i = 0; i < bytes.Length; i++)
                {
                    builder.Append(bytes[i].ToString("x2"));
                }
                return builder.ToString();
            }
        }

        public void SaveEnvironment(string configFile, string currentMac)
        {
            string strEnc = CalculateHash(currentMac);
            File.WriteAllText(configFile, strEnc);
        }

        public bool CheckValidation(string configFile)
        {
            string LoadEnc = File.ReadAllText(configFile);
            Dictionary<string, string> lst = GetMacAddresses();

            foreach (KeyValuePair<string, string> item in lst)
            {
                string strEnc = CalculateHash(item.Value);
                if (LoadEnc == strEnc) return true;
            }

            return false;
        }

        public Dictionary<string, string> GetMacAddresses(string splitChar = "-")
        {
            Dictionary<string, string> macAddresses = new Dictionary<string, string>();
            var kkk = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface ni in kkk)
            {
                string strMac = ni.GetPhysicalAddress().ToString();
                if (strMac != string.Empty)
                {
                    strMac = string.Join(splitChar, Enumerable.Range(0, 6).Select(i => strMac.Substring(i * 2, 2)));
                    macAddresses.Add(ni.Name, strMac);
                }
            }
            return macAddresses;
        }
    }

 

사용방법)

   라이선스 생성기 프로그램 또는 메인 프로그램 설정화면에 Combobox 하나 추가합니다. 

   여기에는 맥어드레스를 선택할 수 있도록 다음 작업을 해줍니다. 

 

// 저는 Combobox가 Devexpress Combobox입니다. 알아서 봐주세요. 
private void RefreshMacAddress()
{
    LicGenerator lic = new LicGenerator();
    Dictionary<string, string> lst = lic.GetMacAddresses();
    CboMacAddress.Properties.Items.Clear();
    foreach (KeyValuePair<string, string> item in lst)
    {
        CboMacAddress.Properties.Items.Add(item);
    }
}

// 보기 쉽게 이런작업도 했으나, 안해도 이름과 맥어드레스가 잘 보입니다. 
private void CboMacAddress_CustomDisplayText(object sender, DevExpress.XtraEditors.Controls.CustomDisplayTextEventArgs e)
{
    if (e.Value == null) return;
    KeyValuePair<string, string> item = (KeyValuePair<string, string>)e.Value;
    e.DisplayText = String.Format("[{0}] {1}", item.Key, item.Value);
}

// this.LicFile는 라이선스 파일입니다. 여기에는 선택된 맥어드레스를 Sha256+base64로 해시뜬 문자열이 들어갑니다.
private void SaveData() 
{
	if (CboMacAddress.SelectedItem == null) 
    {
        XtraMessageBox.Show("맥어드레스를 선택해주세요.", "SpiderR1", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        return; 
    }
    LicGenerator lic = new LicGenerator();
    KeyValuePair<string, string> item = (KeyValuePair<string, string>)CboMacAddress.SelectedItem;
    lic.SaveEnvironment(this.LicFile, item.Value);
}

라이선스 파일을 잘 생성되죠? 

이제 프로그램 시작 부분에서 라이선스 파일이 있는 경우에 대한 로직을 추가해줍니다. 

이때, 별도 라이선스 생성기를 만들었다면 문제가 되지 않지만 저처럼 메인 프로그램에 추가됐다면 라이선스 규칙을 설정해야 합니다. 라이선스 파일이 없는 상태로 시작됐다면 엔지니어 로그인만 되게 한다던지 해주시면 될 것 같습니다. 혹은 DEMO로 시작되는 식이지요. 

 

// Program.cs에서 실행하면 되겠죠? 
public static bool InitValidationCheck()
{
    #region 맥어드레스 체크
    LicGenerator = new LicGenerator();
    // 라이선스 파일이 없어도 우선 실행은 되야 합니다. 대신 예외처리가 필요합니다. 
    if (File.Exists(SpiderLicFile))
    {
    	// 위 클래스에서 보시면 라이선스에 있는 암호화된 문자열이 존재하는지 체크하는 함수입니다.
        if (!spiderLic.CheckValidation(SpiderLicFile))
        {
        	// Devexpress 메시지 박스가 너무 길어서 따로 추가한 함수입니다. 
            // Locale.__는 다국어처리함수입니다.(여기선 PASS) Node.js하다가 오니 i18N라이브러리를 사용했습니다.
            GlobalClass.MsgBox(GlobalClass.Locale.__("It is not the same as the registered license key.\n\rExit the program."),
                GlobalClass.Locale.__("Error"), MessageBoxButtons.OK, MessageBoxIcon.Error);
            return false;
        }
    }
    #endregion
}

대충 단순히 프로그램 복사해서 다른 PC에서는 사용하지는 못하게 할 수 있는 방법이 되겠습니다. 

그럼 이만.... 

반응형