如何使用SHA256创建密钥,值对和秘密签名的标记?

时间:2012-01-12 05:07:25

标签: perl encryption sha

我希望在这些隐藏字段的键值对的sha编码字符串的帮助下验证一些隐藏的输入字段(以确保它们在提交时未被更改)。我在网上看到了这个例子,但我不明白如何编码和 使用动态秘密值解码值。有人可以帮我理解如何在perl中执行此操作吗?

哪种签名类型(MD5,SHA1,SHA256等)在性能和安全性方面有很好的平衡?

更新

那么,一旦你编码了字符串,你如何解码?

3 个答案:

答案 0 :(得分:3)

我不知道“unpack”是什么意思,但你不能从哈希中获取原始字符串。

让我们理解这个问题:你渲染一些隐藏的字段,你想确保它们的提交不变,对吧?以下是您如何确保这一点。

假设您有两个变量:

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中没有已知的弱点。

答案 1 :(得分:2)

对于此应用程序,任何加密算法都可以。您可以按照您想要的方式打包值,只要它是可重复的。一种常见的方法是将字段打包成字符串,就像将它们编码为GET请求的URL(name = value)一样。

要计算哈希值,请创建一个文本密钥,可以是您想要的任何内容。它应该至少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,因为他们不知道在字符串前加上。

请注意,攻击者可以重复使用任何旧的有效值集。他们只是无法从头创建自己的值集或修改现有的值并使其测试有效。因此,请确保在信息中包含一些内容,以便验证它是否适合其使用目的。

答案 2 :(得分:2)

您真正需要的不是普通哈希函数,而是message authentication code,例如HMAC。既然你说你想使用SHA-256,你可能会喜欢HMAC_SHA256,它可以通过Digest::SHA模块在​​Perl中使用:

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 );
}

您还可以将网址编码设为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(这样用户就无法将数据从一个表单复制到另一个表单) )并且可能是表格中(和MAC计算中)的时间戳和/或会话ID(以便您可以拒绝旧数据)。

相关问题