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

一、简介

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

效果:

二、实现效果

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

SoftwareVerification

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

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

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

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

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

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,用来对字符串加密和解密用的

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,用来显示提示信息的

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

代码:

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 类库项目的引用,代码如下:

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 类库项目的引用

代码如下:

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

以下是一个简单的 C# 离线语音识别实现实时说话实时显示的例子: ```csharp using System; using System.Speech.Recognition; class Program { static void Main(string[] args) { // 创建语音识别引擎 SpeechRecognitionEngine recognizer = new SpeechRecognitionEngine(new System.Globalization.CultureInfo("en-US")); // 设置识别模式为离线模式 recognizer.SetInputToDefaultAudioDevice(); // 加载语音识别语法 var grammar = new Grammar("MyGrammar.xml"); recognizer.LoadGrammar(grammar); // 注册语音识别事件处理程序 recognizer.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(recognizer_SpeechRecognized); // 开始语音识别 recognizer.RecognizeAsync(RecognizeMode.Multiple); Console.WriteLine("Say something..."); while (true) { Console.Write("> "); string text = Console.ReadLine(); // 实时显示识别结果 Console.WriteLine("Recognized text: " + recognizer.RecognizeAsyncCancel().Text); if (text.ToLower() == "exit") { break; } } recognizer.Dispose(); } static void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e) { Console.WriteLine("Recognized text: " + e.Result.Text); } } ``` 上述代码中,我们使用了一个无限循环来等待用户输入文字,同时调用 `recognizer.RecognizeAsyncCancel().Text` 实时获取语音识别结果并显示在控制台上。当用户输入 "exit" 时,退出程序并释放语音识别引擎。注意,由于 `recognizer.RecognizeAsyncCancel()` 方法会取消当前正在进行的语音识别操作,因此在实际应用中需要根据具体需求进行适当调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熊思宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值