基于C#實(shí)現(xiàn)簡(jiǎn)單離線注冊(cè)碼生成與驗(yàn)證
主要思路就是提供者持有密鑰,通過(guò)RSA加密客戶(hù)機(jī)標(biāo)識(shí)或時(shí)間標(biāo)識(shí),再通過(guò)Base64加密成不太難看的注冊(cè)碼,然后分發(fā)給客戶(hù)機(jī)。
客戶(hù)機(jī)解Base64后,通過(guò)持有的公鑰來(lái)驗(yàn)證注冊(cè)碼是否與本機(jī)標(biāo)識(shí)或時(shí)間標(biāo)識(shí)相符。
一、 生成公密鑰
RSACryptoServiceProvider cryptor = new RSACryptoServiceProvider();
File.WriteAllText("PrivateKey.xml", cryptor.ToXmlString(true));
File.WriteAllText("PublicKey.xml", cryptor.ToXmlString(false));
為了方便長(zhǎng)期保存這里就直接存入文件了。
為了避免客戶(hù)機(jī)公鑰丟失,我比較傾向于將公鑰直接編譯到驗(yàn)證程序中,但是這樣也就意味著如果更換了密鑰,老的驗(yàn)證程序就驗(yàn)不了新生成的注冊(cè)碼了。
二、 生成注冊(cè)碼
static string CreateRegCode(string mac, DateTime date)
{
RSACryptoServiceProvider cryptor = new RSACryptoServiceProvider();
cryptor.FromXmlString(File.ReadAllText("PrivateKey.xml"));
string signature = String.Format("[{}][{}]", mac, date.ToString("yyyy-MM-dd"));
byte[] regCodeBytes = cryptor.SignData(
Encoding.UTF.GetBytes(signature),
"SHA");
return Convert.ToBaseString(regCodeBytes);
}
這個(gè)方法是通過(guò)加密MAC和日期的組合來(lái)生成注冊(cè)碼,需要注意幾點(diǎn):
1.參數(shù)中的MAC是客戶(hù)機(jī)的地址2.第四行的文件是上一步生成的密鑰文件
3.由于只考慮驗(yàn)證,所以客戶(hù)機(jī)還必須知道參數(shù)中的date
三、 驗(yàn)證注冊(cè)碼
static bool Verify(string regCode)
{
const string PUBLIC_KEY = "";
try
{
RSACryptoServiceProvider cryptor = new RSACryptoServiceProvider();
cryptor.FromXmlString(PUBLIC_KEY);
byte[] signedData = Convert.FromBaseString(regCode);
bool today = cryptor.VerifyData(
Encoding.UTF.GetBytes(String.Format("[{}][{}]", DateTime.Now.ToString("yyyy-MM-dd"))),
"SHA", signedData);
bool machineToday = cryptor.VerifyData(
Encoding.UTF.GetBytes(String.Format("[{}][{}]", MAC, DateTime.Now.ToString("yyyy-MM-dd"))),
"SHA", signedData);
bool forever = cryptor.VerifyData(
Encoding.UTF.GetBytes(String.Format("[{}][{}]", MAC, Environment.MachineName)),
"SHA", signedData);
return today || machineToday || forever;
}
catch
{
return false;
}
}
這個(gè)方法驗(yàn)證了三種類(lèi)型的注冊(cè)碼:當(dāng)天可用、本機(jī)當(dāng)天可用和永久可用。
需要注意:
1.第三行的公鑰就是第一步的PublicKey.xml中的內(nèi)容
2.十四和十七行的MAC是客戶(hù)機(jī)的物理地址,至于怎么獲取不是本文的重點(diǎn),請(qǐng)各位看官自行百度
3.考慮到客戶(hù)機(jī)填寫(xiě)的注冊(cè)碼有可能不是合法的Base64文本,需要捕獲解析時(shí)異常
其實(shí)RSACryptoServiceProvider也提供了解密的方法,這樣就可以驗(yàn)證更多種類(lèi)的驗(yàn)證碼了。
相關(guān)文章
C# FileSystemWatcher 在監(jiān)控文件夾和文件時(shí)的使用方法
這篇文章主要介紹了C# FileSystemWatcher 在監(jiān)控文件夾和文件時(shí)的使用方法,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以參考下2020-06-06
C#運(yùn)算符大全_各種運(yùn)算符號(hào)的概述及作用
以下是對(duì)C#中各種運(yùn)算符號(hào)的說(shuō)明及作用進(jìn)行了詳細(xì)的總結(jié)介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-10-10
用?FieldMask?提高?C#?gRpc?的服務(wù)性能
這篇文章主要介紹了用?FieldMask?提高?C#?gRpc?的服務(wù)性能,FieldMask?是一個(gè)?protobuf?消息,包含一個(gè)名為?paths?的字段,用于指定用于指定讀取操作返回或更新操作修改的字,下文詳細(xì)內(nèi)容,需要的朋友可以參考一下2022-03-03
C#實(shí)現(xiàn)密碼驗(yàn)證與輸錯(cuò)密碼賬戶(hù)鎖定
這篇文章介紹了C#實(shí)現(xiàn)密碼驗(yàn)證與輸錯(cuò)密碼賬戶(hù)鎖定的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04
秒表計(jì)時(shí)器以及STOPWATCH(實(shí)例講解)
C#實(shí)現(xiàn)將浮點(diǎn)數(shù)表示的貨幣數(shù)量以漢字大寫(xiě)形式輸出的方法
C#實(shí)現(xiàn)定義一套中間SQL可以跨庫(kù)執(zhí)行的SQL語(yǔ)句(案例詳解)
C#中如何自定義配置上周和本周起始日來(lái)查詢(xún)業(yè)務(wù)數(shù)據(jù)(思路詳解)

