2014-11-22 68 views
0

假設我有一個表Orders帶有自動遞增的ID,例如, 1,2,3,4 ...,他們當前查詢爲http://www.example.com/order?id= {1,2,3 ..}訂單號的安全整數散列法

現在,我想要散列主鍵[1,2,3,...]另一個號碼稱爲訂單號,以便我們的客戶可以在他們的請求中引用他們,例如

1 -> 100192938303 
2 -> 293029200002 

我想以下幾點:

  • 不能夠通過查看自動遞增ID
  • 沒有DB額外的查找猜多少順序我已經創建了天天都是neeed,通過純粹的哈希PHP(和預定義的鹽)
  • 未發生衝突

這可能嗎?

+2

更好地實施適當的授權,並允許客戶只看到自己的訂單。 – Gumbo 2014-11-22 14:17:45

+0

這個問題的答案[加密短標識符](http://security.stackexchange.com/q/33761/8343)可能對你很有意思。 – martinstoeckli 2014-11-25 21:09:26

回答

-2

可以使用BASE64_ENCODE()你在你的GET形式提交之前,然後BASE64_DECODE()編碼您的訂單ID,當你捕捉的形式發送

,你甚至可以添加鹽,例如BASE64_ENCODE($ ID變量。「salt」)

+1

這是一種不安全的方法。客戶端可以解碼編碼的訂單ID以獲得原始訂單ID(可能含有鹽)。 – drf 2014-11-22 15:40:18

+0

你不能正確解碼它,而不知道鹽 – DLastCodeBender 2014-11-22 15:42:46

+1

這是不正確的。假設,在你的例子中,你用salt'salt'來處理訂單42。 「42salt」(編碼爲UTF-8)的Base64編碼是'NDJzYWx0'。攻擊者可以解碼該字符串以獲取包含訂單ID的原始「42salt」。 – drf 2014-11-22 15:47:32

0

你建議使用salted hash。由於哈希是單向函數,因此需要將哈希轉換爲原始值,因此需要將以下哈希轉換爲原始訂單值:

  • 通過合理的循環然後取出每個值的哈希值,直到找到匹配的哈希值或耗盡允許的訂單ID池。
  • 緩存一次可信的訂單值(例如,在應用程序啓動時),並存儲在散列表中。一旦創建了緩存,這種方法會更快,但需要額外的查找。

您還注意到原始訂單標識符是保密的,因爲可以獲取多個訂單ID的攻擊者可以推斷訂單量。訂單標識符的機密性與訂單本身的機密性有關,這個問題沒有解決,可以通過單獨的訪問控制機制來處理。

我想你的例子中的首選方法是使用加密而不是散列。對訂單ID進行加密將滿足機密性和往返需求,而不會產生散列或數據庫查找緩存的開銷。該方法可能如下所示:

  1. 使用您的密鑰加密訂單ID。
  2. Base64對Order ID進行編碼並作爲令牌返回給客戶端。
  3. 從客戶端收到加密的令牌後,解碼Base64字符串
  4. 使用您的密鑰解密已解碼的字符串以生成原始訂單號。

例如,對於第42和DES密鑰E0EC4E44EF2C6CEE和零IV,你會發送dmTt0kbIlcA=到客戶端的命令ID(如果編碼42作爲小端的32位整數)。(因爲擁有一個唯一的密文在你的場景中不是一個問題,所以在這裏適合使用零IV。)

2

我認爲你可以選擇更簡單的方法 - 不要使用自動遞增ID,使用隨機整數作爲ID。例如:

while (true) { 
    $id = get_random_integer(); 
    $stmt = $db->prepare("INSERT INTO Orders (id, foo, bar) VALUES (:id, 'foo', 'bar')"); 
    try { 
     $stmt->execute(array(':id' => $id)); 
     //OK 
     break; 
    } catch (Exception $ex) { 
     if (is_duplicate_id_exception) { 
      //generate new id and try again 
      continue; 
     } 
     //Some other problem 
     throw $ex; 
    } 
} 

這樣你:

  • 避免衝突
  • 不需要散列函數和{哈希 - > ID}映射
  • 有不包含有關量信息IDS的訂單
0

這裏有兩個想法:

  1. 使用可逆散列。這是否有效取決於你認爲的安全性,因爲它本質上只是混淆。但是,如果你定製它(可能會改變算法中的某些步驟),並且防止源泄漏,它將阻止除最堅決的攻擊者之外的所有其他攻擊者。 (根據您的安全目標,您可能需要結合其他一些技術來減少泄漏風險,例如員工離開公司,考慮保留算法的一部分祕密,就好像它是一個加密密鑰,以及對輸入有額外的,可變的,預先轉換)

關於我的頭頂,簡單的可逆散列可能只是位的「橫向加法」。對於更復雜的東西,我的頭頂上,流行的「MurmurHash」算法家族聲稱是可逆的。

我不知道任何加密強可逆哈希。但是,關於對稱加密主題的其他答案與此想法類似。

  1. 使用流密碼,AKA加密RNG。如果訂單總數相當小,這是適當的。您需要的是與計數編號序列一一對應的唯一序列號碼。因此,使用您選擇的RC4或HMAC生成一系列獨特的隨機數字,隨時消除重複。 (也許一個創造性的方法可以讓這個過程變得更快是一個布隆過濾器。)

對於從內部ID映射到外部ID,您只需生成序列。相反,你會一直走下去,直到找到ID,或者擊中最大訂單ID。這個算法是O(n),這顯然不是理想的,但如果你願意妥協一點,增加更多的複雜性,或者很聰明,你可能會找到一種方法來緩解這種情況。例如,您可能能夠在RAM中保存ID的緩存。

編輯:

我自己感到懷疑#2,由於線性複雜,所以我跑了一些數字。使用Core2處理器的Crypto ++基準數字,如果您預算10毫秒到數字轉換,並且您使用40位ID(假設您獲得1萬億個訂單),那麼您的訂單ID最大值爲2,500,000。而且我認爲你可以通過使用更小的鑰匙來加倍。

所以這種方法可以採取任何方式。對於小規模的東西,沒關係。 (上面的假設是保守的。)但對於大規模的東西,這可能是一個煩惱。這足以讓你通過產品發佈;在您開始討論如何將您的軟件構建爲分佈式系統時,您會希望重新訪問它,這也有助於解決此問題。但是在那個時候,你可能會更好地質疑最初的假設,並將這個東西存儲在某個數據庫中。