1.首先定义注册类RegisterEntity

    [Serializable]
public class RegisterEntity
{
public string RegisterKey;
public bool IsRegistered;
public List<int> RegisterOrder;
public DateTime RegisterDate;
public DateTime ExpireDate;
}

RegisterKey,注册码(序列号)

IsRegistered,是否已注册

RegisterOrder,注册顺序,由于打开注册码生成文件的时候会暴露Guid,这里作了一个简单的加密算法,打乱顺序后存入RegisterKey,而打乱后的顺序会存入这个List,

RegisterDate,注册日期

ExpireDate,过期日期

2.生成序列号

        private RegisterEntity GenerateRegisterKey(RegisterEntity registerEntity)
{
StringBuilder fakeKey = new StringBuilder();
string keyPart;
List<int> registerOrder = new List<int>();
int splitCount = 4;
int currentOrder = 0;
for (int i = 0; i < splitCount; i++)
{
keyPart = Guid.NewGuid().ToString().Substring(0, 6).ToUpper();
currentOrder = new Random().Next(1, splitCount + 1);
while (registerOrder.Contains(currentOrder - 1))
{
Thread.Sleep(100);
currentOrder = new Random().Next(1, splitCount + 1);
}
registerOrder.Add(currentOrder - 1);
keyPart += "-";
fakeKey.Append(keyPart);
}
fakeKey.Remove(fakeKey.Length - 1, 1);
message = fakeKey.ToString();
registerEntity.RegisterOrder = registerOrder;
return registerEntity;
}

这里随机生成了4个六位的Guid,用三个“-”连接起来就是序列号的格式了,打乱顺序用了Random方法,这样顺序也就只有电脑知道了,如果想复杂点可以把splitCount设置大一点,甚至可以把24个字母全部打乱,也就比较难破解了

3.加密

        private string EncipherRegisterKey(RegisterEntity registerEntity)
{
string[] fakeKeyArgs = message.Split('-');
string[] realKeyArgs = new string[4]; for (int i = 0; i < fakeKeyArgs.Length; i++)
{
realKeyArgs[registerEntity.RegisterOrder[i]] = fakeKeyArgs[i];
} StringBuilder realKey = new StringBuilder();
string keyPart = string.Empty;
for (int i = 0; i < realKeyArgs.Length; i++)
{
keyPart = realKeyArgs[i].ToString() + "-";
realKey.Append(keyPart);
}
realKey.Remove(realKey.Length - 1, 1);
return realKey.ToString();
}

实际上加密应该包括第2步,这里只是把序列号按照随机打乱的顺序重新组合了一下

4.把生成的Key写入文件

        public string GenerateRegisterKeyToBinFile(string registerFileName)
{
message = string.Empty;
try
{
registerEntity = new RegisterEntity();
GenerateRegisterKey(registerEntity); // encipher 加密
registerEntity.RegisterKey = EncipherRegisterKey(registerEntity); registerEntity.IsRegistered = false; IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(registerFileName, FileMode.Create,
FileAccess.Write, FileShare.None);
formatter.Serialize(stream, registerEntity);
stream.Close();
}
catch (Exception ex)
{
message = "Error: " + ex.Message;
return message;
}
return message;
}

在这里,每次生成新Key的时候由于会覆盖旧文件,而验证的时候是读取Key文件进行比对,所以在这里把IsRegistered设成了false

5.解密

        private string DecipherRegisterKey(RegisterEntity registerEntity)
{
string[] realKeyArgs = registerEntity.RegisterKey.Split('-');
string[] fakeKeyArgs = new string[4];
if (!Utility.isNullOrEmptyLst(registerEntity.RegisterOrder) && !Utility.isNullOrEmpty(realKeyArgs))
{
for (int i = 0; i < realKeyArgs.Length; i++)
{
fakeKeyArgs[i] = realKeyArgs[registerEntity.RegisterOrder[i]];
}
} StringBuilder decipherKey = new StringBuilder();
string keyPart = string.Empty;
for (int i = 0; i < fakeKeyArgs.Length; i++)
{
keyPart = fakeKeyArgs[i].ToString() + "-";
decipherKey.Append(keyPart);
}
decipherKey.Remove(decipherKey.Length - 1, 1); return decipherKey.ToString();
}

细心的朋友会发现,解密其实和加密差不多,只是fakeKeyArgs和realKeyArgs的顺序换下,是的,验证Key的时候是比较fakeKey而不是真正存储在文件里的realKey

6.验证Key的有效性以及是否过期

        public bool CheckRegister(string registerFileName)
{
RegisterEntity registerEntity = new RegisterEntity();
try
{
string dBFilePath = string.Format("{0}\\{1}", Directory.GetCurrentDirectory(), registerFileName);
if (File.Exists(dBFilePath))
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(registerFileName, FileMode.Open,
FileAccess.Read, FileShare.Read);
registerEntity = (RegisterEntity)formatter.Deserialize(stream);
stream.Close();
if (registerEntity.IsRegistered == true && registerEntity.ExpireDate < DateTime.Today)
{
registerEntity.IsRegistered = false; formatter = new BinaryFormatter();
stream = new FileStream(registerFileName, FileMode.Create,
FileAccess.Write, FileShare.None);
formatter.Serialize(stream, registerEntity);
stream.Close();
}
}
}
catch (Exception ex)
{
return false;
}
return registerEntity.IsRegistered;
}

是指打开软件的时候识别序列号是否已经过期或者是否已经注册

7.注册并验证

        public bool RegisterKey(string inputKey, string registerFileName)
{
RegisterEntity registerEntity = new RegisterEntity();
try
{
string dBFilePath = string.Format("{0}\\{1}", Directory.GetCurrentDirectory(), registerFileName);
if (File.Exists(dBFilePath))
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(registerFileName, FileMode.Open,
FileAccess.Read, FileShare.Read);
registerEntity = (RegisterEntity)formatter.Deserialize(stream);
stream.Close(); string fakeKey = DecipherRegisterKey(registerEntity); if (inputKey == fakeKey)
{
registerEntity.IsRegistered = true;
registerEntity.RegisterDate = DateTime.Today;
registerEntity.ExpireDate = registerEntity.RegisterDate.AddDays(30); //Enable Register Key
formatter = new BinaryFormatter();
stream = new FileStream(registerFileName, FileMode.Create,
FileAccess.Write, FileShare.None);
formatter.Serialize(stream, registerEntity);
stream.Close();
}
}
}
catch (Exception ex)
{
return false;
}
return registerEntity.IsRegistered;
}

输入序列号后,注册,验证序列号是否有效,如果有效,则激活软件

[Serializable]的应用--注册码的生成,加密和验证的更多相关文章

  1. 使用apache htpasswd生成加密的password文件,并使用.htaccess控制文件夹訪问

    htpasswd 是apache的小工具.在apache安装文件夹bin下可找到. Usage: htpasswd [-cmdpsD] passwordfile username htpasswd - ...

  2. (6) openssl passwd(生成加密的密码)

    该伪命令用于生成加密的密码 [root@docker121 ssl]# man -f passwd passwd (1) - update user's authentication tokens p ...

  3. 第十五个知识点:RSA-OAEP和ECIES的密钥生成,加密和解密

    第十五个知识点:RSA-OAEP和ECIES的密钥生成,加密和解密 1.RSA-OAEP RSA-OAEP是RSA加密方案和OAEP填充方案的同时使用.现实世界中它们同时使用.(这里介绍的只是&quo ...

  4. openssl生成签名与验证签名

    继上一篇RSA对传输信息进行加密解密,再写个生成签名和验证签名. 一般,安全考虑,比如接入支付平台时,请求方和接收方要互相验证是否是你,就用签名来看. 签名方式一般两种,对称加密和非对称加密.对称加密 ...

  5. Yii2处理密码加密及验证

    在Yii2中提供了密码加密以及验证的一系列方法,方便我们的使用,它使用的是bcrypt算法.查看源码我们可以发现它使用的是PHP函数password_hash()和crypt()生成. 加密: /** ...

  6. 利用strut2标签自动生成form前端验证代码

    利用strut2标签自动生成form前端验证代码,使用到的技术有1.struts2标签,如<s:form> <s:textfieled>2.struts2读取*Validati ...

  7. shiro盐值加密并验证

    在数据表中存的密码不应该是123456,而应该是123456加密之后的字符串,而且还要求这个加密算法是不可逆的,即由加密后的字符串不能反推回来原来的密码,如果能反推回来那这个加密是没有意义的.著名的加 ...

  8. 第十六个知识点:描述DSA,Schnorr,RSA-FDH的密钥生成,签名和验证

    第十六个知识点:描述DSA,Schnorr,RSA-FDH的密钥生成,签名和验证 这是密码学52件事系列中第16篇,这周我们描述关于DSA,Schnorr和RSA-FDH的密钥生成,签名和验证. 1. ...

  9. (转)DES、RSA、MD5、SHA、随机生成加密与解密

    一.数据加密/编码算法列表   常见用于保证安全的加密或编码算法如下:   1.常用密钥算法   密钥算法用来对敏感数据.摘要.签名等信息进行加密,常用的密钥算法包括:   DES(Data Encr ...

随机推荐

  1. AttributeError: 'NoneType' object has no attribute 'bytes' python3.4 win64

    解决方法: easy_install -U pip 详见: https://github.com/pypa/pip/issues/2669

  2. Vue.js相关知识3-路由

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  3. 越狱Season 1-Episode 19: The Key

    Season 1, Episode 19: The Key -Kellerman: WeusedtohaveaGreatDane, Dane: 丹麦大狗 我们以前有一只大丹犬 bigandwild. ...

  4. jQuery 1.10.3 参考手册

    Jquery是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器(IE 6.0+, FF 1.5+, Safari 2.0+, Opera 9.0+),jQuery2.0及后续版本将不再支持IE6/7 ...

  5. 黑马程序员——JAVA基础之程序控制流结构之循环结构,循环嵌套

    ------- android培训.java培训.期待与您交流! ---------- 循环结构: 代表语句:while ,do while ,for while语句格式 : while(条件表达式) ...

  6. java基础之:详解内部类(转载)

    可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二). 第一次见面 内部类我们从外面 ...

  7. pdo的工作方式与查错

    pdo某些方法如prepare()会返回PDOStatement对象; 然后需要通过返回的PDOStatement对象的方法操作 当查错通过$pdo->errInfo()方法可能查不出错误信息 ...

  8. oracle_dblink配置

    说明:一下是未配置本地服务的dblink. 前提:   授权>  grant create public database link,create database link to myAcco ...

  9. javascript 遍历object对象

    (function(){ var str = ''; for(var i in obj){ //遍历object str += '\n'+(i+' : '+obj[i]); // i+' : '+ob ...

  10. PHP安装libevent扩展

    1. 下载扩展 官方地址http://pecl.php.net/package/libevent 请根据自己的PHP脚本选择相应版本 如 wget http://pecl.php.net/get/li ...