2012-01-12 69 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

相关问题