2011-05-10 104 views
7

我有一種情況,我們打印出「折扣卡」的運行,其中在卡上打印唯一代碼,用戶可以在網上商店兌換折扣。根據算法創建一組「優惠券代碼」;不需要存儲代碼

我們創建了很多這樣的卡片,其中實際使用的數量很少,我希望使用某種方式來使用某種方法來識別有效的代碼,而不是將每個單獨的代碼存儲在數據庫中。我們一次創建5,000個這樣的代碼。大概每年5次左右。

理想情況下,我想能夠像:

$coupons->generate(5000, 'unique_salt', 'prefix_'); 

這將產生像5000「隨機」碼:

prefix-23-3424-4324-3344 or 
prefix-4H-34RE-22K3-PE3W 

unique saltprefix_將被保存到數據庫。這些代碼然後可以通過使用prefix_查找salt並將代碼標識爲有效來驗證。

我有一個這種工作的形式,通過使用一個數字作爲鹽,找到鹽可以整除的數字,然後重新排列數字,使它看起來是隨機的。用足夠長的代碼,需要一些工作來確定模式。但我想認爲還有更好的辦法......因爲只有那麼多的數字纔會產生可被salt整除的大量代碼。

(例如,2的鹽將產生5000碼1和10000之間(並且將是易見的圖案)...但14000鹽將產生1和10000之間的零碼)

這樣做的另一個好處是我可以根據需要生成優惠券(例如,當我們給予個人一個基礎的折扣時),並且能夠跟蹤什麼樣的優惠券使用時等,基於prefix_ ...和可能會看到卡片何時/何時傳出,獲得最佳回報。

我只是在旋轉我的車輪時,我應該將每個代碼存儲在數據庫中? (或者只是開心?):)

+0

我會投票將代碼存儲在數據庫中。 5000 x 5次/年仍然只有25000碼/年。每個代碼可能有20-30個字節,你甚至沒有存儲完整的兆字節值的數據。它也避免了某人破解代碼的問題。 – dlev 2011-05-10 21:25:57

+0

您可以使用一些隨機數字和字母,並在特定索引處選擇字符以生成某種形式的校驗位,並附加到代碼的末尾。然後,在輸入代碼時,您只需選擇字符,運行算法並查看是否結束了最後一個字符。 – 2011-05-10 21:26:06

+0

@ duncan-howe是的,我現在用我目前的方法實際做到了。我添加了一些特定的數字來獲得一個總和,作爲校驗和添加到生成的代碼中。 – drewjoh 2011-05-10 21:34:02

回答

1

一個標準的技術是對鹽和數字使用單向散列來創建一個大的隨機數字。然後使用這個散列來生成你的隱藏代碼。有很多標準的單向散列可以使用。 MD5是常見的。

爲了讓您的生活更輕鬆,我會以簡單的方式將數字嵌入到代碼中。例如前綴2_-3_ -4_ -3 ___將是代碼2343,然後您將使用「前綴鹽號」的MD5中的數據填充空白。這可能就像說你有一個數字和字符的字母表,你願意使用n的東西。以MD5 mod n挑選你的第一個字符。將MD5除以n。然後重複,直到你有你的角色。爲了驗證它,需要前綴,查找salt,提取數字,計算MD5,並按照相同的步驟生成應該在代碼中的其他字符。

2

您可以使用HMAC和適當的編碼方案來執行此操作。首先,爲HMAC生成一個密鑰,並確保保密。要生成每個令牌,請執行以下操作:

  1. 生成一個序列號,無論是隨機或順序 - 所有這些重要的是,它是獨一無二的。
  2. 使用密鑰計算序列號的HMAC(我建議HMAC-SHA1)。這會給你一個散列值(在HMAC-SHA1的情況下爲160位)。
  3. 將序列號與部分散列值連接起來。這是您的優惠券代碼。您使用的散列值的位數決定了通過蠻力創建有效代碼的難度 - 使用n位表示您的攻擊者必須嘗試(平均)2 ^(n-1)代碼來查找有效的。從散列中使用哪些位並不重要。

要驗證碼:

  1. 檢查序列號是不是已經在你的數據庫之前已經贖回。
  2. 如上所述計算序列號的HMAC。
  3. 比較HMAC的相關位與其餘代碼中的相關位。
  4. 將序列號添加到您的數據庫中以將其註冊爲已使用。
相關問題