10

好的,我可能只是星期一过得很糟糕,但我有以下需求,我看到了很多部分解决方案,但我确定我不是第一个需要这个的人,所以我想知道我是否我错过了明显的。

$client 有 50 到 500 字节的二进制数据,必须插入到 URL 的中间并往返于客户的浏览器。由于它是 URL 的一部分,因此我们遇到了 GET URL 的 1K“理论”限制。此外,$client 不希望他们的客户解码数据,或者在不被发现的情况下篡改数据。$client 也不希望在服务器端存储任何东西,所以它必须是完全独立的。必须是 Perl 代码,并且在编码和解码方面都很快。

我认为最后一步可以是base64。但是最有意义的加密和散列步骤是什么?

4

4 回答 4

5

我在 Cat 应用程序中有一些代码,用于Crypt::Util对用户的电子邮件地址进行编码/解码以获取电子邮件验证链接。

我使用密钥建立了一个Crypt::Util模型。Catalyst::Model::Adaptor然后在我的控制器中,我在发送端有以下逻辑:

my $cu = $c->model('CryptUtil');
my $token = $cu->encode_string_uri_base64( $cu->encode_string( $user->email ) );
my $url = $c->uri_for( $self->action_for('verify'), $token );

我将此链接发送到$user->email,当单击它时,我使用以下内容。

my $cu = $c->model('CryptUtil');
if ( my $id = $cu->decode_string( $cu->decode_string_uri_base64($token) ) ) {
    # handle valid link
} else { 
    # invalid link
}

这基本上是edanite另一个答案中刚刚建议的内容。您只需要确保用于形成令牌的任何数据最终$url都不会超过您的任意限制。

于 2010-05-24T23:15:01.603 回答
4

创建一个密钥并将其存储在服务器上。如果有多个服务器并且请求不能保证返回到同一个服务器;您需要在每台服务器上使用相同的密钥。此密钥应定期轮换。

如果您以 CBC(密码块链接)模式加密数据(参见 Crypt::CBC 模块),加密的开销最多为两个块(一个用于 IV,一个用于填充)。128 位(即 16 字节)块很常见,但不是通用的。我建议使用 AES(又名 Rijndael)作为分组密码。

您需要对数据进行身份验证以确保其未被修改。根据应用程序的安全性,仅对消息进行散列并在您加密的明文中包含散列可能就足够了。这取决于攻击者在不知道对称加密密钥的情况下无法更改哈希以匹配消息。如果您使用 128 位密钥作为密码,请使用 SHA-256 之类的 256 位哈希(您可以为此使用 Digest 模块)。您可能还希望在数据中包含一些其他内容,例如时间戳,以防止请求被重复多次。

于 2010-05-24T23:09:45.313 回答
3

我在这里看到三个步骤。首先,尝试压缩数据。使用如此少的数据 bzip2 可能会为您节省 5-20%。我会投入警卫以确保它不会使数据变大。这一步可能不值得。

use Compress::Bzip2 qw(:utilities);
$data = memBzip $data;

您还可以尝试手动减少数据中任何键和值的长度。例如,first_name可以简化为fname.

第二,加密。选择您最喜欢的密​​码并使用 Crypt::CBC。这里我使用 Rijndael,因为它对 NSA 来说已经足够好了。您需要进行基准测试以找到性能和安全性之间的最佳平衡。

use Crypt::CBC;
my $key = "SUPER SEKRET";
my $cipher = Crypt::CBC->new($key, 'Rijndael');
my $encrypted_data = $cipher->encrypt($data);

您必须将密钥存储在服务器上。将其放在受保护的文件中就足够了,保护该文件留作练习。当你说你不能在服务器上存储任何东西时,我认为这不包括密钥。

最后,Base 64 对其进行编码。我将使用修改后的 URL 安全 base 64,它使用 - 和 _ 而不是 + 和 / ,从而使您不必花费空间 URL 对 base 64 字符串中的这些字符进行编码。 MIME::Base64::URLSafe涵盖了这一点。

use MIME::Base64::URLSafe;
my $safe_data = urlsafe_b64encode($encrypted_data);

然后将其粘贴到您想要的 URL 上。反转读取它的过程。

你应该在尺寸上是安全的。加密会增加数据的大小,但可能会增加不到 25%。Base 64 会将数据大小增加三分之一(编码为 2^6 而不是 2^8)。这应该使 500 字节的编码在 1K 内保持舒适。

于 2010-05-24T23:30:23.530 回答
-1

它需要有多安全?你能不能用一个长的随机字符串对数据进行异或运算,然后用另一个秘密盐添加整个批次的 MD5 哈希来检测篡改?

我不会将它用于银行数据,但它可能对大多数网络事物都很好......

大的

于 2010-05-24T22:55:16.580 回答