本文基于RSA加密算法实现C#版本的软件加密注册机制。思路如下:
- 客户端持有公钥,对客户端所运行电脑上获取CPU、硬盘、网卡等信息通过MD5加密生成机器码
- 服务端生成一对公私钥,将客户端上生成的机器码进行数字签名并生成授权码。
- 客户端将给定的公钥、授权码、机器码进行数字验签。
- 如果验证正确则视为通过,否则不通过。
1、封装RSA加密类
using System;
using System.Security.Cryptography;
using System.Text;
namespace RSACryption
{
/// <summary>
/// RSA非对称加密封装类
/// 1、CreateRSAKeys 生成一对公钥、私钥
/// </summary>
public class RSA
{
/// <summary>
/// 生成一对公钥、私钥
/// </summary>
/// <param name="privatekey"></param>
/// <param name="publicekey"></param>
public static void CreateRSAKeys(out string xmlPrivatekey, out string xmlPublicKey)
{
using (RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider())
{
xmlPrivatekey = Convert.ToBase64String(RSAalg.ExportCspBlob(true)); //私钥
xmlPublicKey = Convert.ToBase64String(RSAalg.ExportCspBlob(false));//公钥
}
}
/// <summary>
/// RSA的加密函数
/// </summary>
/// <param name="xmlPublicKey">公钥</param>
/// <param name="encryptString">待加密的字符串</param>
/// <returns></returns>
public static string RSAEncrypt(string xmlPublicKey, string encryptString)
{
try
{
byte[] PlainTextBArray;
byte[] CypherTextBArray;
string Result;
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(xmlPublicKey);
PlainTextBArray = (new UnicodeEncoding()).GetBytes(encryptString);
CypherTextBArray = rsa.Encrypt(PlainTextBArray, false);
Result = Convert.ToBase64String(CypherTextBArray);
return Result;
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// RSA的解密函数
/// </summary>
/// <param name="xmlPrivateKey">私钥</param>
/// <param name="decryptString">待解密的字符串</param>
/// <returns></returns>
public static string RSADecrypt(string xmlPrivateKey, string decryptString)
{
try
{
byte[] PlainTextBArray;
byte[] DypherTextBArray;
string Result;
System.Security.Cryptography.RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(xmlPrivateKey);
PlainTextBArray = Convert.FromBase64String(decryptString);
DypherTextBArray = rsa.Decrypt(PlainTextBArray, false);
Result = (new UnicodeEncoding()).GetString(DypherTextBArray);
return Result;
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 对数据签名
/// </summary>
/// <param name="dataToSign"></param>
/// <param name="privateKey"></param>
/// <returns></returns>
public static string HashAndSign(string dataToSign, string privateKey)
{
try
{
ASCIIEncoding ByteConverter = new ASCIIEncoding();
byte[] byteDataToSign = ByteConverter.GetBytes(dataToSign);
RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider();
RSAalg.ImportCspBlob(Convert.FromBase64String(privateKey));
byte[] byteSignedData = RSAalg.SignData(byteDataToSign, new SHA1CryptoServiceProvider());
return Convert.ToBase64String(byteSignedData);
}
catch (CryptographicException e)
{
return null;
}
catch (Exception e)
{
return null;
}
}
/// <summary>
/// 验证签名
/// </summary>
/// <param name="dataToVerify"></param>
/// <param name="signData"></param>
/// <param name="publicKey"></param>
/// <returns></returns>
public static bool VerifySignedHash(string dataToVerify, string signData, string publicKey)
{
try
{
byte[] byteSignedData = Convert.FromBase64String(signData);
ASCIIEncoding ByteConverter = new ASCIIEncoding();
byte[] byteDataToVerify = ByteConverter.GetBytes(dataToVerify);
RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider();
RSAalg.ImportCspBlob(Convert.FromBase64String(publicKey));
return RSAalg.VerifyData(byteDataToVerify, new SHA1CryptoServiceProvider(), byteSignedData);
}
catch (CryptographicException e)
{
return false;
}
catch (Exception e)
{
return false;
}
}
}
}
2、获取电脑硬件封装类
using System;
using System.Management;
using System.Security.Cryptography;
using System.Text;
namespace RSACryption
{
public class ComputerInfo
{
/// <summary>
/// 获取当前电脑信息
/// </summary>
/// <returns></returns>
public static string ComputerInfoStr()
{
string machineCode = string.Format("Mac:{0};CpuID:{1};HardID:{2}",
GetLocalMac(),
GetCpuID(),
GetHardID());
return machineCode;
}
/// <summary>
/// 获取当前电信信息的MD5
/// </summary>
/// <returns></returns>
public static string GetCoumputerForMD5()
{
HashAlgorithm algorithm = HashAlgorithm.Create("MD5");
byte[] bytes = Encoding.UTF8.GetBytes(ComputerInfoStr());
byte[] inArray = algorithm.ComputeHash(bytes);
return Convert.ToBase64String(inArray);
}
/// <summary>
/// 获取本机的MAC地址
/// </summary>
/// <returns></returns>
public static string GetLocalMac()
{
string mac = null;
ManagementObjectSearcher query = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration");
ManagementObjectCollection queryCollection = query.Get();
foreach (ManagementObject mo in queryCollection)
{
if (mo["IPEnabled"].ToString() == "True")
mac = mo["MacAddress"].ToString();
}
return (mac);
}
/// <summary>
/// 得到CPU序列号
/// </summary>
/// <returns></returns>
public static string GetCpuID()
{
try
{
//获取CPU序列号代码
string cpuInfo = "";//cpu序列号
ManagementClass mc = new ManagementClass("Win32_Processor");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
cpuInfo = mo.Properties["ProcessorId"].Value.ToString();
}
moc = null;
mc = null;
return cpuInfo;
}
catch
{
return "unknow";
}
finally
{
}
}
/// <summary>
/// 获取硬盘ID
/// </summary>
/// <returns>硬盘ID</returns>
public static string GetHardID()
{
string HDInfo = "";
ManagementClass cimobject1 = new ManagementClass("Win32_DiskDrive");
ManagementObjectCollection moc1 = cimobject1.GetInstances();
foreach (ManagementObject mo in moc1)
{
HDInfo = (string)mo.Properties["Model"].Value;
}
return HDInfo;
}
}
}
3、Client端核心代码
using System;
using System.Windows.Forms;
using RSACryption;
namespace RSA.Client
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
tb_computercode.Text = ComputerInfo.GetCoumputerForMD5();
}
private void button1_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(this.rtb_LicenseKey.Text))
{
MessageBox.Show("请输入注册码!");
return;
}
if (string.IsNullOrEmpty(this.rtb_publickey.Text))
{
MessageBox.Show("请输入RSA公钥!");
return;
}
if (RSACryption.RSA.VerifySignedHash(this.tb_computercode.Text, this.rtb_LicenseKey.Text, this.rtb_publickey.Text))//公钥验签
{
MessageBox.Show("注册成功!", "注册", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("注册失败!", "注册", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
4、Server端核心代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace RSA.Server
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string xmlprivatekey, xmlpublicekey;
RSACryption.RSA.CreateRSAKeys(out xmlprivatekey, out xmlpublicekey);
this.rtb_publickey.Text = xmlpublicekey;
this.rtb_privatekey.Text = xmlprivatekey;
}
private void button2_Click(object sender, EventArgs e)
{
//机器码不为空
if (!string.IsNullOrEmpty(rtb_MachineCode.Text))
{
this.rtb_LicenseKey.Text = RSACryption.RSA.HashAndSign(rtb_MachineCode.Text, this.rtb_privatekey.Text);
}
else
{
MessageBox.Show("机器码不能为空");
}
}
}
}
界面图例:
1、客户端


2、服务端

