我想驗證一些隱藏的輸入字段(以確保它們在提交時沒有改變),藉助於這些隱藏字段的鍵值對的sha編碼的字符串的幫助。我看到這個在線的例子,但我不明白如何編碼,並用動態祕密值解碼值。有人可以幫助我瞭解如何在perl中執行此操作嗎?如何使用SHA256創建密鑰,值對和祕密簽名的令牌?
另外哪種簽名類型(MD5,SHA1,SHA256等)在性能和安全性方面具有良好的平衡性?
更新
那麼,你怎麼一旦你得到它的編碼解碼字符串?
我想驗證一些隱藏的輸入字段(以確保它們在提交時沒有改變),藉助於這些隱藏字段的鍵值對的sha編碼的字符串的幫助。我看到這個在線的例子,但我不明白如何編碼,並用動態祕密值解碼值。有人可以幫助我瞭解如何在perl中執行此操作嗎?如何使用SHA256創建密鑰,值對和祕密簽名的令牌?
另外哪種簽名類型(MD5,SHA1,SHA256等)在性能和安全性方面具有良好的平衡性?
更新
那麼,你怎麼一旦你得到它的編碼解碼字符串?
你真正需要的不是一個普通的散列函數,而是一個message authentication code,如HMAC。既然你說你想使用SHA-256,你可能會喜歡HMAC_SHA256,這是可以在Perl通過Digest::SHA模塊:
use Digest::SHA qw(hmac_sha256_base64);
my $mac = hmac_sha256_base64($string, $key);
這裏,$key
是任意鍵,你應該保持祕密, $string
包含您要簽名的數據。要將其應用於更復雜的數據結構(例如鍵值爲–的哈希值),首先需要將其轉換爲字符串。有幾種方法可以做到這一點;例如,你可以使用Storable:
use Storable qw(freeze);
sub pairs_to_string {
local $Storable::canonical = 1;
my %hash = @_;
return freeze(\%hash);
}
你也可以URL編碼,如suggested by David Schwartz。重要的是,無論使用何種方法,當給定相同的散列作爲輸入時,它總是應該返回完全相同的字符串。
然後,在將數據發送給用戶之前,您需要爲它們計算一個MAC並將其作爲額外字段包含在數據中。當您接收到數據時,您將刪除MAC字段(並保存其值),重新計算剩餘字段的MAC並將其與您收到的值進行比較。如果他們不匹配,某人(或某事)已經篡改了數據。就像這樣:
my $key = "secret";
sub mac { hmac_sha256_base64(pairs_to_string(@_), $key) }
# before sending data to client:
my %data = (foo => "something", bar => "whatever");
$data{mac} = mac(%data);
# after receiving %data back from client:
my $mac = delete $data{mac};
die "MAC mismatch" if $mac ne mac(%data);
注意,有一些潛在的招數這種技術不會自動阻止,如replay attacks:一旦你的數據和MAC發送給用戶,他們將學會對應於特定的MAC數據集,並且可能會用稍後形式中的字段替換從先前形式保存的值。爲了保護您免受此類攻擊,您應該在MAC保護的數據中包含足夠的識別信息,以確保您可以檢測到任何可能有害的重播。理想情況下,您希望在每種表單中都包含一個唯一的ID,並檢查是否沒有ID提交兩次,但這可能並不總是實用。否則,包含用戶ID(以便惡意用戶不能欺騙別人提交他們的數據)和表單ID(以便用戶不能將數據從一種表單複製到另一種表單)可能是一個好主意),也可能是一個時間戳和/或一個會話ID(以便您可以拒絕舊數據)的形式(以及在MAC計算中)。
我不知道你是什麼意思的「解壓」,但你不能從哈希中獲得原始字符串。
讓我們來理解這個問題:你渲染一些隱藏的字段,並且你想確保它們沒有被提交,對吧?以下是您可以確保的方法。
讓我們假設你有兩個變量:
first: foo
second: bar
您可以用密鑰一起湊他們:
secret_key = "ysEJbKTuJU6u"
source_string = secret_key + "first" + "foo" + "second" + "bar"
hash = MD5(source_string)
# => "1adfda97d28af6535ef7e8fcb921d3f0"
現在你可以使您的標記:
<input type="hidden" name="first" value="foo" />
<input type="hidden" name="second" value="bar" />
<input type="hidden" name="hash" value="1adfda97d28af6535ef7e8fcb921d3f0">
在表單提交,您可以獲得first
和second
字段的值,並將它們連接以類似的方式將您的密鑰加密並再次散列。
如果哈希值相等,則您的值未被更改。
注意:從不將密鑰呈現給客戶端。在散列之前對鍵/值對進行排序(以消除對順序的依賴)。
(免責聲明:我不是一個加密的人,所以你可能只是現在停止閱讀)
至於性能/安全性,即使MD5被發現有一個弱點,它仍然是相當有用,恕我直言。 SHA1有一個理論上的弱點,儘管還沒有成功的攻擊。 SHA-256沒有已知的弱點。
是的,補充說,在您的評論之前:-) – 2012-01-12 05:27:55
通過包/解壓縮我的意思是編碼/解碼 – qodeninja 2012-01-12 19:22:35
對於這個應用程序,任何加密算法都很好。只要可重複,您可以隨心所欲地打包這些值。一種常見的方法是將字段打包成字符串,就像將它們編碼到GET請求(name = value)的URL中一樣。
要計算哈希,創建一個文本祕密,可以是任何你想要的。它應該至少有12個字節長。計算與壓縮字段連接的密碼的散列並將其附加到結尾。
所以,說你選擇MD5的JS90320ERHe2
一個祕密,你有這些領域:
first_name = Jack
last_name = Smith
other_field = 7=2
首先,URL編碼是:
first_name=Jack&last_name=Smith&other_field=7%3d=2
然後計算的
MD5哈希JS90320ERHe2first_name=Jack&last_name=Smith&other_field=7%3d=2
這是6d0fa69703935efaa183be57f81d38ea
。最終的編碼字段是:
first_name=Jack&last_name=Smith&other_field=7%3d=2&hash=6d0fa69703935efaa183be57f81d38ea
所以這就是你傳遞給用戶的內容。爲了驗證它,從最後刪除哈希,通過連接剩下的祕密來計算MD5哈希,如果哈希匹配,那麼該字段沒有被篡改。
沒有人可以計算自己的有效MD5,因爲他們不知道在字符串前加上。
請注意,攻擊者可以重新使用任何舊的有效值集。他們不能從頭開始創建自己的值集或修改現有的值並使其測試有效。因此,請確保您在信息中包含了某些內容,以便您可以驗證它是否適合其使用目的。
一旦你收回了弦,你如何解碼絃樂? – qodeninja 2012-01-12 23:34:59
你不(不能)解碼它。你所做的是重新計算它,並檢查它與你回來的相同。我添加了一些示例代碼來展示如何去做。 – 2012-01-12 23:53:34