如何生成合理短的臨時解鎖碼?
我需要一種方法來為應用程序生成臨時解鎖碼,以便在應用程序無法上線時使用,以確認其啟動訂閱仍然是最新的。
應用程序需要能夠離線 30 天而無需重新授權,這只是延長網路中斷/等的備份選項。
我的第一個想法是只儲存一個時間戳,用於顯示保持解鎖狀態的時間,並結合應用程序可以用來確認解鎖來自我們的 RSA 簽名,而不是使用者剛剛編造的東西。
如果我們在應用程序中嵌入公鑰,這似乎可以滿足我們的安全需求(如果破解者修改了二進製文件,他們可以完全刪除檢查,而不是安裝自己的密鑰)。對於正常操作,將數據作為與相關 Web 應用程序之間正常數據傳輸的一部分向下發送意味著我們可以毫無困難地做到這一點。
我看到的問題是,由於這需要在網路中斷時可用,因此解鎖程式碼需要足夠短以通過電話或同等方式發送。具有安全密鑰長度的 RSA 簽名在那裡失敗。
使用基於雜湊的密碼學。
首先,定義一個單向函式
F
。它將一個小的(10-16 字節)字元串作為輸入,並使用安全散列函式 (EG:SHA2) 生成另一個相同大小的字元串。我們從(2000 年 1 月 1 日)到(2100 年 1 月 1 日)的每一天都用一個數字編號
n
(n=0 ... 36500)
每天都分配一個程式碼。如果使用者擁有特定日期的程式碼,則允許他們在當天之前(包括當天)的所有日子裡使用該軟體。如果我們提供當天的程式碼,
x
我們不在乎使用者是否可以找到當天x-1
的程式碼,因為當天的程式碼x
也允許他們在當天使用該軟體。考慮到這一點,我們執行以下操作:
code(x)=f(code(x+1))
這些程式碼形成一個鏈。對於每次安裝,您選擇第 36500 天的隨機程式碼,然後反復對其進行雜湊處理,直到獲得第 0 天的程式碼。然後您簽署一條消息,告訴應用程序第 0 天的程式碼。
屆時,請提供特定日期的程式碼以解鎖該日期的軟體。
任何人都可以將 F 應用於程式碼以獲取前一天的程式碼。但是他們無法反轉 F 來獲取第二天的程式碼。由於您在鏈的開頭選擇了程式碼,因此您擁有所有這些程式碼。這是使該系統安全的不對稱性。是的,不對稱……這是公鑰密碼學。
為了驗證程式碼,應用程序重複應用 F,直到它到達第 0 天程式碼。如果這在鏈的任何設定長度內都沒有發生,則程式碼無效。在此過程中保留一個計數器以獲取程式碼編號。出於安全考慮,不需要強制執行此限制,如果使用者在輸入程式碼時出錯,它只會使驗證過程超時。
執行
F
可以截斷 SHA2。保留的位數決定了安全級別。80位就足夠了。您需要一個二進製文本編碼,以使人類可以閱讀並輸入您的應用程序。
我目前的機器每秒可以執行 ~1e6 SHA2 操作。那是價值 3000 年的解鎖程式碼。遍歷在伺服器上生成程式碼並在客戶端驗證它們的鏈不會花費太多時間。
相信時鐘
這取決於應用程序有權訪問正確的時間。使用者可以隨時更改系統時間,這不是許可證執行系統可以解決的問題。如果應用程序做了一些時間敏感的事情(比如記錄時間戳記錄),使用者可能不想在錯誤的時間執行軟體。我建議保留一個內部保存的時間值,該值會在軟體使用時增加,並且永遠不會倒退。這是你能做的最好的。使用者始終可以隨意製作系統映像並從備份中恢復任意多次。
有些事情你應該已經在做。
我假設您已經在某處保存了每個安裝 ID。這是對這個的一種要求。每個已安裝的軟體副本都必須具有唯一的 ID、程式碼 (0) 和 (ID,code(0)) 對的儲存簽名才能正常工作。這可以防止客戶端部署大量相同安裝的相同映像並為所有這些映像使用相同的程式碼。這是另一件無法真正幫助的事情。
如果您提供安裝在機器上並將執行的客戶端軟體,則客戶端可以進行完整的系統備份。正如我之前提到的,他們可以從備份中恢復並根據需要多次調回時鐘。但他們也可以從同一個備份中重新映像另一台機器。處理這兩種情況是一場貓捉老鼠的遊戲,他們試圖欺騙您的應用程序執行的環境,而您試圖確保他們沒有這樣做。
從硬體派生 ID是一種簡單的選擇。這可以防止相同的許可證數據在另一台機器上工作……但 ID可以被 欺騙。在這個貓捉老鼠的遊戲中,您嘗試獲取合法的未經欺騙的硬體 ID,並且客戶端嘗試為您的應用程序提供欺騙值。沒有像 TPM 這樣的特殊硬體可以做任何事情。