1.首先定义注册类RegisterEntity
[Serializable] public class RegisterEntity { public string RegisterKey; public bool IsRegistered; public List RegisterOrder; public DateTime RegisterDate; public DateTime ExpireDate; }
IsRegistered,是否已注册
RegisterOrder,注册顺序,由于打开注册码生成文件的时候会暴露Guid,这里作了一个简单的加密算法,打乱顺序后存入RegisterKey,而打乱后的顺序会存入这个List,
RegisterDate,注册日期
ExpireDate,过期日期
2.生成序列号
private RegisterEntity GenerateRegisterKey(RegisterEntity registerEntity) { StringBuilder fakeKey = new StringBuilder(); string keyPart; List registerOrder = new List (); 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; }
输入序列号后,注册,验证序列号是否有效,如果有效,则激活软件