如何使用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