C# 离线激活码的实现方式

一、简介

离线激活码是一种在软件、游戏、应用程序或其他数字产品领域中常用的授权方式,旨在确保产品的合法使用并维护开发者的权益。当用户购买或获得这些产品的使用权后,开发者会提供一个唯一的、一次性的激活码给用户。与在线激活不同,离线激活码允许用户在没有网络连接的情况下完成产品的激活过程,这对于网络环境不稳定或处于无网络环境的用户尤为便利。

效果:

二、实现效果

当前帖子会展现一个激活软件的完整流程,但也只是一个仅供参考的解决方案,我也做的也那么好,虽然如此,但也不是什么小白都能破解的,还是有一定的用处的。

SoftwareVerification

首先,需要新建一个类库,用来处理激活码和验证相关的问题,取名为:SoftwareVerification

新建一个类 ActivationManager,用来生成激活码,验证激活码,和读取硬盘ID,你也可以改为读取CPU,主板序列号等,我测试了下,读取CPU,主板序列号有点慢,所以就没用了。

因为源码中包含了密匙等信息,不能直接拿了就用,需要拿代码混淆工具对当前DLL进行混淆,可以参考我的帖子:

C# dll代码混淆加密_c# 混淆-CSDN博客

在需要激活的软件中,使用这个混淆加密的DLL进行接口调用,并限制部分接口的访问权限,这样才可以确保软件不那么容易被破解。

cs 复制代码
using System;
using System.IO;
using System.Management;
using System.Security.Cryptography;
using System.Text;

namespace SoftwareVerification
{
    public class ActivationManager
    {
        private static string DllPath = AppDomain.CurrentDomain.BaseDirectory;
        private static string SecretKey = "johusaqj!lkjuh442~34vf?%sfdsfj";

        /// <summary>
        /// 是否激活成功
        /// </summary>
        public static bool IsActivationSuccess { get; set; }

        /// <summary>
        /// 生成激活码
        /// </summary>
        /// <param name="machineCode">机器码</param>
        /// <returns></returns>
        public static string GenerateActivationCode(string machineCode)
        {
            using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(SecretKey)))
            {
                byte[] hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(machineCode));
                return Convert.ToBase64String(hashBytes);
            }
        }

        /// <summary>
        /// 读取本地激活码
        /// </summary>
        /// <returns></returns>
        public static void ReadActivationCode()
        {
            try
            {
                string path = $"{DllPath}activation.key";
                if (!File.Exists(path))
                {
                    ShowActivationForm();
                    return;
                }

                string content = File.ReadAllText(path);
                if (string.IsNullOrEmpty(content))
                {
                    ShowActivationForm();
                    return;
                }

                string decryptAct = AesEncryptionHelper.Decrypt(content);
                string activation = GenerateActivationCode(GetDiskSerialNumber());
                if (activation.Contains(decryptAct))
                {
                    IsActivationSuccess = true;
                    return;
                }
                ShowActivationForm();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// 显示激活界面
        /// </summary>
        private static void ShowActivationForm()
        {
            var activationForm = new ActivationForm();
            activationForm.ShowDialog();
        }

        /// <summary>
        /// 保存激活码
        /// </summary>
        /// <param name="code">激活码</param>
        private static void SaveActivationCode(string code)
        {
            if (string.IsNullOrEmpty(code)) return;

            string path = $"{DllPath}activation.key";
            string act = AesEncryptionHelper.Encrypt(code);
            File.WriteAllText(path, act);
        }

        /// <summary>
        /// 验证激活码
        /// </summary>
        /// <param name="inputActivationCode">激活码</param>
        /// <returns></returns>
        internal static bool ValidateActivationCode(string inputActivationCode)
        {
            if (string.IsNullOrEmpty(inputActivationCode))
                return false;

            string activation = GenerateActivationCode(GetDiskSerialNumber());
            if (activation.Contains(inputActivationCode))
            {
                SaveActivationCode(activation);
                IsActivationSuccess = true;
                return true;
            }
            return false;
        }

        /// <summary>
        /// 获取硬盘序列号
        /// </summary>
        /// <returns></returns>
        internal static string GetDiskSerialNumber()
        {
            try
            {
                var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
                foreach (ManagementObject disk in searcher.Get())
                {
                    var serialNum = disk["SerialNumber"];
                    if (serialNum != null)
                        return serialNum.ToString().Trim();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }
            return null;
        }
    }
}

新建一个类 AesEncryptionHelper,用来对字符串加密和解密用的

cs 复制代码
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace SoftwareVerification
{
    public class AesEncryptionHelper
    {
        // 固定的密钥和 IV,请勿在实际生产环境中使用
        private static readonly byte[] Key = Encoding.UTF8.GetBytes("12345678901234567890123456789012"); // 32 字节的密钥
        private static readonly byte[] IV = Encoding.UTF8.GetBytes("1234567890123456"); // 16 字节的 IV

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="plainText"></param>
        /// <returns></returns>
        public static string Encrypt(string plainText)
        {
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        swEncrypt.Write(plainText);
                    }
                    return Convert.ToBase64String(msEncrypt.ToArray());
                }
            }
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="cipherText"></param>
        /// <returns></returns>
        public static string Decrypt(string cipherText)
        {
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText)))
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                {
                    return srDecrypt.ReadToEnd();
                }
            }
        }
    }
}

添加一个类 LogShow,用来显示提示信息的

cs 复制代码
using System;
using System.Windows.Forms;

public class LogShow
{
    public Label Label_Log = null;
    private Timer Timers = null;
    private int TimeOut = 3;

    private void Init()
    {
        Timers = new Timer();
        Timers.Interval = (int)TimeSpan.FromSeconds(TimeOut).TotalMilliseconds;
        Timers.Tick += Timers_Tick;
    }

    private void Timers_Tick(object sender, EventArgs e)
    {
        if (Label_Log == null) return;

        Label_Log.Text = string.Empty;
        Timers.Enabled = false;
    }

    public void Show(string message)
    {
        if (Label_Log == null) return;

        Label_Log.Invoke(new Action(() =>
        {
            Label_Log.Text = message;
            if (Timers.Enabled)
                Timers.Enabled = false;
            Timers.Enabled = true;
        }));
    }

    public void Show(string message, params object[] objs)
    {
        if (Label_Log == null) return;

        Label_Log.Invoke(new Action(() =>
        {
            string content = string.Empty;
            if (objs != null && objs.Length > 0)
                content = string.Format(message, objs);
            else
                content = message;

            Label_Log.Text = content;
            if (Timers.Enabled)
                Timers.Enabled = false;
            Timers.Enabled = true;
        }));
    }

    public LogShow() => Init();
}

接下来添加一个 Form 界面,取名:ActivationForm

代码:

cs 复制代码
using System;
using System.Threading;
using System.Windows.Forms;

namespace SoftwareVerification
{
    public partial class ActivationForm : Form
    {
        public ActivationForm()
        {
            InitializeComponent();
        }

        //提示工具
        private LogShow LogShows = new LogShow();
        //机器码
        private string MachineCode = string.Empty;
        //激活失败次数
        private int ActivationErrorCount;

        private void ActivationForm_Load(object sender, EventArgs e)
        {
            LogShows.Label_Log = Label_Log;

            //显示机器码
            MachineCode = ActivationManager.GetDiskSerialNumber();
            TextBox_MachineCode.Text = AesEncryptionHelper.Encrypt(MachineCode);
        }

        private void ActivationForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!ActivationManager.IsActivationSuccess)
                Application.Exit();
        }

        //激活
        private void Button_Activation_Click(object sender, EventArgs e)
        {
            string act = TextBox_Activation.Text;
            if (string.IsNullOrEmpty(act))
            {
                LogShows.Show("请输入激活码");
                return;
            }
            if (ActivationErrorCount >= 3)
            {
                LogShows.Show("激活失败次数过多");
                return;
            }

            bool result = ActivationManager.ValidateActivationCode(act);
            if (result)
            {
                LogShows.Show("激活成功");
                Thread.Sleep(500);
                this.Close();
            }

            ActivationErrorCount++;
            LogShows.Show("激活码失败,次数:{0}", ActivationErrorCount);
        }

        //复制
        private void Button_Copy_Click(object sender, EventArgs e)
        {
            string content = TextBox_MachineCode.Text;
            if (!string.IsNullOrEmpty(content))
            {
                Clipboard.SetText(content);
                LogShows.Show("复制成功");
            }
        }

        //粘贴
        private void Button_Paste_Click(object sender, EventArgs e)
        {
            TextBox_Activation.Text = (string)Clipboard.GetDataObject().GetData(DataFormats.Text);
        }
    }
}

ActivationCodeGenerate

第二个项目是激活码生成工具,根据机器码来生成激活码,这个软件主要是掌握在软件所有人这边的,你需要给谁激活码,让它发一下机器码,你就可以生成对于的激活码了。

界面如下:

这个界面和上面的 SoftwareVerification 项目中的界面类似,首先需要添加 SoftwareVerification 类库项目的引用,代码如下:

cs 复制代码
using SoftwareVerification;
using System;
using System.Windows.Forms;

namespace ActivationCodeGenerate
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //提示工具
        private LogShow LogShows = new LogShow();

        private void Form1_Load(object sender, EventArgs e)
        {
            LogShows.Label_Log = Label_Log;
        }

        //粘贴
        private void Button_Paste_Click(object sender, EventArgs e)
        {
            TextBox_MachineCode.Text = (string)Clipboard.GetDataObject().GetData(DataFormats.Text);
        }

        //生成
        private void Button_Generate_Click(object sender, EventArgs e)
        {
            string machineCode = TextBox_MachineCode.Text;
            if (string.IsNullOrEmpty(machineCode))
            {
                LogShows.Show("请输入机器码");
                return;
            }

            machineCode = AesEncryptionHelper.Decrypt(machineCode);
            string activation = ActivationManager.GenerateActivationCode(machineCode);
            TextBox_Activation.Text = activation;
        }

        //复制
        private void Button_Copy_Click(object sender, EventArgs e)
        {
            string content = TextBox_Activation.Text;
            if (!string.IsNullOrEmpty(content))
            {
                Clipboard.SetText(content);
                LogShows.Show("复制成功");
            }
        }
    }
}

测试

新建一个 Winform 项目 Test,用来当做需要激活码的软件,随便加了点文字,要添加 SoftwareVerification 类库项目的引用

代码如下:

cs 复制代码
using SoftwareVerification;
using System;
using System.Windows.Forms;

namespace Test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ActivationManager.ReadActivationCode();
        }
    }
}

项目整体结构如下:

项目源码:

https://download.csdn.net/download/qq_38693757/89767636

运行后效果如下:

结束

如果这个帖子对你有所帮助,欢迎 关注 + 点赞 + 留言

end

相关推荐
君莫愁。1 小时前
【Unity】检测鼠标点击位置是否有2D对象
unity·c#·游戏引擎
Lingbug2 小时前
.Net日志组件之NLog的使用和配置
后端·c#·.net·.netcore
咩咩觉主2 小时前
Unity实战案例全解析:PVZ 植物卡片状态分析
unity·c#·游戏引擎
Echo_Lee02 小时前
C#与Python脚本使用共享内存通信
开发语言·python·c#
__water9 小时前
『功能项目』QFrameWork框架重构OnGUI【63】
c#·unity引擎·重构背包框架
Crazy Struggle9 小时前
C# + WPF 音频播放器 界面优雅,体验良好
c#·wpf·音频播放器·本地播放器
晨曦_子画10 小时前
C#实现指南:将文件夹与exe合并为一个exe
c#
花开莫与流年错_10 小时前
C# 继承父类,base指定构造函数
开发语言·c#·继承·base·构造函数
hillstream311 小时前
oracle中NUMBER(1,0)的字段如何映射到c#中
数据库·oracle·c#
那个那个鱼11 小时前
.NET 框架版本年表
开发语言·c#·.net