我無法為這個問題想出一個好的標題,但我希望我能把它說得更清楚。
在某些應用程式中,例如自動取款機或投資經紀人,您不會通過常規鍵盤輸入密碼,而是通過虛擬鍵盤輸入密碼,其中每個鍵映射到兩個不同的數字。例如,假設您的密碼是9657,并且界面上出現以下選項:
- A) 4 或 2
- B) 5 或 1
- C) 3 或 7
- D) 6 或 0
- E) 8 或 9
要插入密碼,您必須輸入/單擊:E、D、B、C。這是因為 E 映射到 9,D 映射到 6,B 映射到 5,C 映射到 7。
但是,由于每個密鑰可以映射到 2 個不同的數字,因此 EDBC 序列也可以映射到 15 個其他密碼。那么如何檢查用戶是否插入了正確的?
我的意思是,我知道蠻力是一種選擇。更具體地說 - 我們可以遍歷序列 EDBC 生成的所有密碼,并檢查其中一個是否是正確的密碼。8653、8657、8613、8617……等等。
但是有沒有更有效的方法來做到這一點?根據哈希檢查密碼的計算成本可能很高,更不用說為每個登錄請求設定 16、32 或 64 個不同的密碼了。
例子

uj5u.com熱心網友回復:
聽起來像一個糟糕的安全機制,因為它使猜測和蠻力更容易。
假設演算法可以訪問實際密碼(pin 碼),您可以將該密碼映射到其在虛擬鍵盤上的表示,然后進行一次比較。
static readonly IReadOnlyDictionary<char, char> convertDigit =
new Dictionary<char, char>()
{
{'4', 'A' }, {'2', 'A' },
{'5', 'B' }, {'1', 'B' },
{'3', 'C' }, {'7', 'C' },
{'6', 'D' }, {'0', 'D' },
{'8', 'E' }, {'9', 'E' },
};
string ConvertToKeys(string pin)
{
return new string(pin.Select(d => convertDigit[d]).ToArray());
}
var pin = "9657"; // From database
var input = "EDBC"; // From virtual keypad
Console.WriteLine(input == ConvertToKeys(pin));
uj5u.com熱心網友回復:
您的數字密碼無關緊要。轉換9657為EDBC,你就完成了。
順便說一句,將四個字符的密碼與其他 64 個字符進行核對是很簡單的。
對于真正偏執的解決方案,您可以使用 base-5 分解 (EDBC -> 4x125 3x25 1x5 2 = 582) 將密碼字串編碼為單個整數。然后在一條指令中進行比較。
uj5u.com熱心網友回復:
這里的演算法只是每個按鈕按下的for回圈。檢查第一個按鈕按下的位數是否包含 PIN 的第一位。如果是這樣,請繼續按下第二個按鈕。如果您通過所有字母,則為真,否則為假。這個演算法在 PIN 中的位數上是 O(n),雖然在這么小的一個n上,這并不重要。
您永遠不會在這里“插入密碼”。事實上,這是預期的安全措施。缺點是系統必須知道確切的 PIN,而不是 PIN 的散列(但散列 PIN 通常是浪費時間,因為它們的空間太小了)。
如果此處“插入”了某些內容,則正確的資料格式將類似于:
89.60.51.37
(8 或 9、6 或 0、5 或 1、3 或 7)
但是這個系統的優勢在于按鈕到數字的映射每次使用都會改變,所以散列在這里并不是一個很好的解決方案。(當然它只需要計算和比較 16 個散列,所以也許這很好,但是這個空間太小了,散列不能提供太多。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/505862.html
