php 缩短字符串,php - 具有解码可能性(缩短url)的最短可能编码字符串仅使用PHP...

我正在寻找一种方法,将字符串编码到尽可能短的长度,并使其可解码(纯PHP,无SQL)。我有工作脚本,但对编码字符串的长度不满意。

脚本:

链接到图像(取决于我要向用户显示的文件分辨率):

www.mysite.com/share/index.php?img=/dir/dir/hi-res img.jpg&w=700&h=500

编码链接(因此用户无法猜测如何获得更大的图像):

www.mysite.com/share/encodedquerystring

因此,basicaly我只想对URL的搜索查询部分进行编码:

img=/dir/dir/hi-res img.jpg&w=700&h=500

我现在使用的方法将上述查询字符串编码为:

Y8xNT9vpyswc44xm3润滑油3m3hs9rij0txjbcwmdtqxbuwmdaa

我使用的方法是:$raw_query_string = 'img=/dir/dir/hi-res-img.jpg&w=700&h=500';

$encoded_query_string = base64_encode(gzdeflate($raw_query_string));

$decoded_query_string = gzinflate(base64_decode($encoded_query_string));

如何缩短编码结果,并且仍然可以只用PHP对其进行解码?

最佳答案:

我怀疑如果您不希望散列方法被用户诱骗,那么您需要更多地考虑它。base64的问题是base64字符串看起来像base64字符串。有一个很好的机会,一个足够聪明的人看你的网页来源可能也会认识到它。

第一部分:

将字符串编码为尽可能短的长度的方法。

如果你对你的网址词汇/字符很灵活,这将是一个很好的开始。由于gzip使用返回引用获得了很大的收益,所以由于字符串太短,所以没有什么意义。

考虑您的示例-您在压缩中只保存了2个字节,这些字节在base64 padding中再次丢失:

非gzipped:string(52) "aW1nPS9kaXIvZGlyL2hpLXJlcy1pbWcuanBnJnc9NzAwJmg9NTAw"

gzipped:string(52) "y8xNt9VPySwC44xM3aLUYt3M3HS9rIJ0tXJbcwMDtQxbUwMDAA=="

如果你减少你的声乐大小,这自然会让你更好的压缩。假设我们删除了一些冗余信息

看看功能:function compress($input, $ascii_offset = 38){

$input = strtoupper($input);

$output = '';

//We can try for a 4:3 (8:6) compression (roughly), 24 bits for 4 chars

foreach(str_split($input, 4) as $chunk) {

$chunk = str_pad($chunk, 4, '=');

$int_24 = 0;

for($i=0; $i<4; $i++){

//Shift the output to the left 6 bits

$int_24 <<= 6;

//Add the next 6 bits

//Discard the leading ascii chars, i.e make

$int_24 |= (ord($chunk[$i]) - $ascii_offset) & 0b111111;

}

//Here we take the 4 sets of 6 apart in 3 sets of 8

for($i=0; $i<3; $i++) {

$output = pack('C', $int_24) . $output;

$int_24 >>= 8;

}

}

return $output;

}

function decompress($input, $ascii_offset = 38) {

$output = '';

foreach(str_split($input, 3) as $chunk) {

//Reassemble the 24 bit ints from 3 bytes

$int_24 = 0;

foreach(unpack('C*', $chunk) as $char) {

$int_24 <<= 8;

$int_24 |= $char & 0b11111111;

}

//Expand the 24 bits to 4 sets of 6, and take their character values

for($i = 0; $i < 4; $i++) {

$output = chr($ascii_offset + ($int_24 & 0b111111)) . $output;

$int_24 >>= 6;

}

}

//Make lowercase again and trim off the padding.

return strtolower(rtrim($output, '='));

}

接下来基本上是删除冗余信息,然后将4个字节压缩为3个字节。这是通过有效地拥有ASCII表的6位子集来实现的。移动此窗口,使偏移从有用的字符开始,并包括当前使用的所有字符。

使用我使用的偏移量,您可以使用从ASCII 38到102的任何内容。这会给您一个30字节的字符串,即9字节(24%)的压缩!不幸的是,您需要保证它的URL安全(可能是base64),这使它恢复到40字节。

我认为在这一点上,假设你已经达到了阻止99.9%的人所需要的“通过默默无闻的安全”水平,你是相当安全的。不过,让我们继续,到问题的第二部分

所以用户无法猜测如何获得更大的图像

可以说,上面已经解决了这个问题,但是您需要做的是通过服务器上的一个秘密来传递这个问题,最好使用php openssl。以下代码显示了上述函数和加密的完整使用流程:

$method = 'AES-256-CBC';

$secret = base64_decode('tvFD4Vl6Pu2CmqdKYOhIkEQ8ZO4XA4D8CLowBpLSCvA=');

$iv = base64_decode('AVoIW0Zs2YY2zFm5fazLfg==');

$input = 'img=/dir/dir/hi-res-img.jpg&w=700&h=500';

var_dump($input);

$compressed = compress($input);

var_dump($compressed);

$encrypted = openssl_encrypt($compressed, $method, $secret, false, $iv);

var_dump($encrypted);

$decrypted = openssl_decrypt($encrypted, $method, $secret, false, $iv);

var_dump($decrypted);

$decompressed = decompress($compressed);

var_dump($decompressed);

此脚本的输出如下:

string(39) "img=/dir/dir/hi-res-img.jpg&w=700&h=500"

string(30) "

string(44) "xozYGselci9i70cTdmpvWkrYvGN9AmA7djc5eOcFoAM="

string(30) "

string(39) "img=/dir/dir/hi-res-img.jpg&w=700&h=500"

您将看到整个循环:压缩>加密>base64编码/解码>解密>解压。它的输出将尽可能接近你真正得到的长度,接近你能得到的最短长度。

除此之外,我觉得有必要得出这样的结论:它只是理论上的,这是一个值得思考的挑战。当然有更好的方法来达到你想要的结果-我会第一个承认我的解决方案有点荒谬!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值