zoukankan      html  css  js  c++  java
  • [C#]简单离线注册码生成与验证

    本文使用RSA非对称加密和Base64简单地实现离线注册码的生成与验证功能。

    主要思路就是提供者持有密钥,通过RSA加密客户机标识或时间标识,再通过Base64加密成不太难看的注册码,然后分发给客户机。
    客户机解Base64后,通过持有的公钥来验证注册码是否与本机标识或时间标识相符。

    一、生成公密钥

    RSACryptoServiceProvider cryptor = new RSACryptoServiceProvider();
    File.WriteAllText("PrivateKey.xml", cryptor.ToXmlString(true));
    File.WriteAllText("PublicKey.xml", cryptor.ToXmlString(false));

    为了方便长期保存这里就直接存入文件了。
    为了避免客户机公钥丢失,我比较倾向于将公钥直接编译到验证程序中,但是这样也就意味着如果更换了密钥,老的验证程序就验不了新生成的注册码了。

    二、生成注册码

     1 static string CreateRegCode(string mac, DateTime date)
     2 {
     3     RSACryptoServiceProvider cryptor = new RSACryptoServiceProvider();
     4     cryptor.FromXmlString(File.ReadAllText("PrivateKey.xml"));
     5     string signature = String.Format("[{0}][{1}]", mac, date.ToString("yyyy-MM-dd"));
     6     byte[] regCodeBytes = cryptor.SignData(
     7         Encoding.UTF8.GetBytes(signature),
     8         "SHA1");
     9     return Convert.ToBase64String(regCodeBytes);
    10 }

    这个方法是通过加密MAC和日期的组合来生成注册码,需要注意几点:

    1.参数中的MAC是客户机的地址2.第四行的文件是上一步生成的密钥文件
    3.由于只考虑验证,所以客户机还必须知道参数中的date

    三、验证注册码

     1 static bool Verify(string regCode)
     2 {
     3     const string PUBLIC_KEY = "";
     4     try
     5     {
     6         RSACryptoServiceProvider cryptor = new RSACryptoServiceProvider();
     7         cryptor.FromXmlString(PUBLIC_KEY);
     8         byte[] signedData = Convert.FromBase64String(regCode);
     9 
    10         bool today = cryptor.VerifyData(
    11             Encoding.UTF8.GetBytes(String.Format("[{0}][{0}]", DateTime.Now.ToString("yyyy-MM-dd"))),
    12             "SHA1", signedData);
    13         bool machineToday = cryptor.VerifyData(
    14             Encoding.UTF8.GetBytes(String.Format("[{0}][{1}]", MAC, DateTime.Now.ToString("yyyy-MM-dd"))),
    15             "SHA1", signedData);
    16         bool forever = cryptor.VerifyData(
    17             Encoding.UTF8.GetBytes(String.Format("[{0}][{1}]", MAC, Environment.MachineName)),
    18             "SHA1", signedData);
    19         return today || machineToday || forever;
    20     }
    21     catch
    22     {
    23         return false;
    24     }
    25 }

    这个方法验证了三种类型的注册码:当天可用、本机当天可用和永久可用。需要注意:

    1.第三行的公钥就是第一步的PublicKey.xml中的内容
    2.十四和十七行的MAC是客户机的物理地址,至于怎么获取不是本文的重点,请各位看官自行百度
    3.考虑到客户机填写的注册码有可能不是合法的Base64文本,需要捕获解析时异常

    其实RSACryptoServiceProvider也提供了解密的方法,这样就可以验证更多种类的验证码了。

  • 相关阅读:
    Linux 系统的启动过程
    Oracle中row_number()、rank()、dense_rank() 的区别
    Java 动态打印菱形代码之for循环的使用
    Oracle 体系结构chapter2
    Oracle 11g 概述 chaper1
    go解决ctrl+鼠标左键或F12失效问题
    解决unrecognized import path "golang.org/x/sys/windows"问题
    设计规范
    性能分析
    用IDEA导入项目时,项目中的SpringBoot注解无法识别
  • 原文地址:https://www.cnblogs.com/vd630/p/4841523.html
Copyright © 2011-2022 走看看