2011-04-06 88 views
4

比方說,我寫了一個程序,並希望將其分發給人們。我希望能夠在安裝期間向用戶請求序列號,以驗證他們是否擁有該軟件的許可副本。另外,我希望序列號能夠存儲他們有權訪問的軟件版本,以及授權何時到期。實現軟件序列號的

有至少兩個概念上的方法,我能想到的做到這一點:

  1. 生成,其中用戶購買軟件的服務器上的串行,並通過電子郵件發送給他們。該軟件在安裝期間連接到服務器並激活產品。服務器返回許可證權限和到期日期。串行沒有特定的格式/數學規則,它只是針對服務器上的數據庫進行檢查。

  2. 生成客戶序列並通過電子郵件發送給他們。該序列具有一些特殊的數學屬性,允許程序檢查它是否有效,它對應的許可證以及何時到期。

我最感興趣的是第二種方法。序列號中使用哪些技術編碼這些信息?如果你能給出一個簡短的概述,那會很棒。否則,你能推薦一些好的書或討論這個的網站嗎?

我覺得奇怪的是,在所有我一直在編碼這些年來,我從來沒有真正看到這些技術的實現或描述。

回答

1

好了,兩個星期內沒有一個答案。 我打算用一個非常簡單的方法來回答,這個方法是用基本方法生成相對安全,高度可擴展的序列號。

作爲一個數學家,我很積極的,有用於存儲各種信息的序號一些先進的技術 - 但我感興趣的主要是快速和垢。

這裏有一個天真的,非數學,蠻力技術考慮:

創建byte[]陣列包含要使用的字符。您只能使用十六進制,但沒有理由限制自己。爲什麼不使用整個字母數字範圍減去'0'/'O'和'1'/'I'(出於顯而易見的原因)。

接下來,編寫一個函數如下(例子是C#):

byte[] genRandomSerial(int length, byte[] characters, Random r) 
{ 
    var sn = new byte[length]; 

    for (int i = 0; i < length; i++) 
    sn[i] = characters[r.Next(0, characters.Length)]; 

    return sn; 
} 

這會給你一個隨機的序列號,這是我們不知道是否有效。

下一頁:

int sum(byte[] sn, MD5 md5) 
{ 
    val = 0; 

    foreach (byte b in md5.ComputeHash(sn)) 
    val += (int)b; 

    return val; 
} 

然後

bool validate(byte[] sn, uint radix, uint expected, MD5 md5) 
{ 
    return (sum(sn, md5) % radix == expected); 
} 

我們現在已經是加在一起的MD5的16字節輸出散列函數,和評估的方式是否總和模n等於一些x

現在,決定您想要存在多少個序列號。序列號越多,就越容易被某人隨機猜出一個有效的組合。

將你的隨機序列分成塊。比方說5塊4,給予20個字符形式:ABCD-EFGH-IJKL-MNOP-QRST

創建5個陣列出你的序列號:

{A,B,C,d}, {E,F,G,H},{I,J,K,L},{M,N,O,P}和{Q,R,S,T}。

測試,看看你的5個陣列驗證如下:

if (validate(block1, radix, expected, md5)) 
    // This block is valid. 

如果你設置基數爲2,則有1/2的概率,該塊將是有效的。如果將基數設置爲10,則該塊有效的概率爲1/10。如果您有5個塊,並且您將每個基數設置爲10,那麼整個序列號有效的概率爲0.1^5 = 0.00001。 (換句話說,每100000個隨機序列中有1個是有效的,這意味着如果你使用完整的字母數字範圍減去'0'/'O','1'/'I',那麼你有(8 + 24)^ n * 0.00001 =〜1.2 * 10^19有效密鑰的串行長度爲20,這很重要 - 但請記住,無論如何你都不會找到它們,基數越高,串口就越安全,但是產生的時間越長)。

注意,'預期'應該介於0和基數-1之間

所以現在我們有一種驗證特定序列號的方法是有效的,但我們如何存儲它是什麼類型的序列?事實上,我們已經有辦法做到這一點。將全部隨機的(但確認)串行「SN」:

int licenseType = sum(sn, md5) % 4; // Where 4 is the number of licenses you want to have 

if (licenseType == 0) 
{ 
    // Evaluation 
} 
else if (licenseType == 1) 
{ 
    // Standard 
} 
else if (licenseType == 2) 
{ 
    // Full 
} 
else // licenseType == 3 
{ 
    // Unrestricted 
} 

每種類型的許可證的數量將逐漸拉平爲你產生越來越多的按鍵。

如果您想在密鑰中存儲附加信息,例如到期日期,您可以使用類似的方法。例如,您可以將奇數字符模12的和取得到期的月份,並將偶數字符總和的模31取爲到期日。

您應用的這些限制和子部門越多,生成每種類型的密鑰所用的時間就越長。

+0

如何防止惡意用戶編輯分佈式二進制文件以完全繞過檢查? – 2018-01-22 23:07:45

+0

如果對這個問題有一個簡單的答案,那麼基本上每一個商業軟件都不會出現裂縫:) – Ozzah 2018-02-27 02:57:14

+1

這就是我的觀點。在格式結尾處使用一些微不足道的東西 - 也許是一個GPG簽名的JSON文檔 - 並且將精力集中在難以反向工程的措施上,以檢測修補後的二進制文件並使其不可用。 (由於跟蹤導致立即失敗的檢查比較容易,因此,如果檢查失敗的方式會損壞某些內存,而這種方式在運行時不會顯示出來,那麼這樣做會更有意義......但是,是我一段時間都沒參加的貓捉老鼠遊戲)。 – 2018-02-27 14:49:49

3

你想要做的是基本上創建你自己的授權模塊。沒有什麼不對,如果你推出自己的產品,它將是免費的(只是你的時間來編碼和調試它)。然而,如果你這樣做是爲了獲得某種類型的許可證合規性(即版權保護),我將不會感到煩惱,所以它將非常容易被破解。

你打算以某種方式將它綁定到物理機器上嗎?一種方法是獲得CPU序列號,HD序列號,MAC地址等或上述的某些組合,對它們進行散列並在啓動時使用散列檢查以確保許可證有效。當然,如果用戶更改了任何內容,檢查將會失敗,即使他們擁有有效的許可證,他們也可能會激怒他們的軟件不再運行。

如果你這樣做是爲了防止非法複製或使用,你所提出的模式通常很容易破解 - 一個黑客會尋找你檢查正確的許可證的地方,然後將asm代碼修補爲在它周圍分支或總是返回一個積極的。如果你的應用程序是.NET,它們可以逆轉源代碼並刪除許可證檢查部分。免責聲明:我工作的許可證管理/複製保護工具公司([Wibu-Systems])1這就是我們所做的,所以我們知道打敗大多數系統是多麼容易。

我推薦以下三種方法之一:

  1. 留下你的應用程序不受保護,並希望您的銷售盜版率是合理的。
  2. 滾動一個簡單的系統,但認識到如果軟件有價值的人會迅速和容易地破解它。準備一些複雜的編碼和維護工作,甚至可以做到一半。
  3. 購買商業品質保護系統,如CodeMeter,HASPKeyLok。有些人比其他人好(我們認爲我們的自然人是最好的),但沒有一個是免費的。