2012-01-12 72 views
4

我想驗證一些隱藏的輸入字段(以確保它們在提交時沒有改變),藉助於這些隱藏字段的鍵值對的sha編碼的字符串的幫助。我看到這個在線的例子,但我不明白如何編碼,並用動態祕密值解碼值。有人可以幫助我瞭解如何在perl中執行此操作嗎?如何使用SHA256創建密鑰,值對和祕密簽名的令牌?

另外哪種簽名類型(MD5,SHA1,SHA256等)在性能和安全性方面具有良好的平衡性?

更新

那麼,你怎麼一旦你得到它的編碼解碼字符串?

回答

2

你真正需要的不是一個普通的散列函數,而是一個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計算中)。

+0

一旦你收回了弦,你如何解碼絃樂? – qodeninja 2012-01-12 23:34:59

+1

你不(不能)解碼它。你所做的是重新計算它,並檢查它與你回來的相同。我添加了一些示例代碼來展示如何去做。 – 2012-01-12 23:53:34

3

我不知道你是什麼意思的「解壓」,但你不能從哈希中獲得原始字符串。

讓我們來理解這個問題:你渲染一些隱藏的字段,並且你想確保它們沒有被提交,對吧?以下是您可以確保的方法。

讓我們假設你有兩個變量:

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"> 

在表單提交,您可以獲得firstsecond字段的值,並將它們連接以類似的方式將您的密鑰加密並再次散列。

如果哈希值相等,則您的值未被更改。

注意:從不將密鑰呈現給客戶端。在散列之前對鍵/值對進行排序(以消除對順序的依賴)。

免責聲明:我不是一個加密的人,所以你可能只是現在停止閱讀)

至於性能/安全性,即使MD5被發現有一個弱點,它仍然是相當有用,恕我直言。 SHA1有一個理論上的弱點,儘管還沒有成功的攻擊。 SHA-256沒有已知的弱點。

+0

是的,補充說,在您的評論之前:-) – 2012-01-12 05:27:55

+0

通過包/解壓縮我的意思是編碼/解碼 – qodeninja 2012-01-12 19:22:35

2

對於這個應用程序,任何加密算法都很好。只要可重複,您可以隨心所欲地打包這些值。一種常見的方法是將字段打包成字符串,就像將它們編碼到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,因爲他們不知道在字符串前加上。

請注意,攻擊者可以重新使用任何舊的有效值集。他們不能從頭開始創建自己的值集或修改現有的值並使其測試有效。因此,請確保您在信息中包含了某些內容,以便您可以驗證它是否適合其使用目的。

+0

我喜歡URL參數化 – qodeninja 2012-01-12 21:25:59

+0

如何解碼字符串,一旦你得到它回來? – qodeninja 2012-01-12 23:36:50

+0

你從最後去掉'&hash = ...'。驗證散列,然後URL就像在GET請求中那樣解碼字符串的其餘部分。 – 2012-01-12 23:53:09

相關問題