加密数字 URL 参数,结果不应长于原始值

发布于 2025-01-07 21:56:30 字数 85 浏览 0 评论 0 原文

我必须加密特定的 URL 参数。如果我希望输出少于 6-7 个字符,我应该使用什么算法?

输入仅为 1 到 1,000,000 之间的整数。

I have to encrypt a particular URL parameter. If I want the output to be below 6-7 characters, what algorithm should I use?

The inputs are integer only ranging from 1 to 1,000,000.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦里兽 2025-01-14 21:56:30

如果您需要加密并需要尽可能短的结果,则必须使用流密码。 Blowfish(您之前使用的)是一种块密码,结果始终具有单个块的最小大小。

维基百科上查找流密码的比较以及PHP 手册mcrypt

另外,加密的结果可能包含特殊字符,因此将其作为参数放入 URL 时,应该使用 urlencode()base64_encode()

使用 urlencode()base64_encode() 将扩展字符串,使其比原始数据更长。这是确保传输/URL 安全所必需的。

但是,由于您的输入始终是数字,因此您可以使用 base_convert() 来缩短输入。在解码方面,您必须做相反的事情。

要获得更短的结果,您可以使用enminicode() / Aron Cederholm 提供的 deminicode() 函数,而不是使用 base_convert()

下面是一个使用 RC4 流密码(顺便说一句,它不是很强)以及从基数 10 到基数 36 的转换的示例。

注意:此示例仅适用于数字,因此它使用 base_convert() 缩小输入字符串!

function my_number_encrypt($data, $key, $base64_safe=true, $shrink=true) {
        if ($shrink) $data = base_convert($data, 10, 36);
        $data = @mcrypt_encrypt(MCRYPT_ARCFOUR, $key, $data, MCRYPT_MODE_STREAM);
        if ($base64_safe) $data = str_replace('=', '', base64_encode($data));
        return $data;
}

function my_number_decrypt($data, $key, $base64_safe=true, $expand=true) {
        if ($base64_safe) $data = base64_decode($data.'==');
        $data = @mcrypt_encrypt(MCRYPT_ARCFOUR, $key, $data, MCRYPT_MODE_STREAM);
        if ($expand) $data = base_convert($data, 36, 10);
        return $data;
}

$data = "15231223";
$key = "&/ASD%g/..&FWSF2csvsq2we!%%";

echo "data: ", $data, "\n";
$encrypted = my_number_encrypt($data, $key);
echo "encrypted: ", $encrypted, "\n";
$decrypted = my_number_decrypt($encrypted, $key);
echo "decrypted: ", $decrypted, "\n";

结果:

data: 15231223
encrypted: BuF3xdE
decrypted: 15231223

If you require encryption and need to have the shortest result possible, you must use a stream cipher. Blowfish (what you previously used) is a blockcipher and the result will always have the minimum size of one single block.

Find a comparison of stream ciphers on Wikipedia and the list of supported ciphers in the PHP manual on mcrypt

Also, the result of the encryption may contain special chars, so when putting it into an URL as a parameter, you should use urlencode() or base64_encode()

Using urlencode() or base64_encode() will expand your string, making it longer than the original data. This is necessary to make it transport/URL safe.

However, since your input is always a number you can use base_convert() to shorten your input. On the decoding side, you'd have to do reverse the same thing.

To get even shorter results, you could make use of the enminicode() / deminicode() function provided by Aron Cederholm instead of using base_convert().

Here is an example using the RC4 stream cipher (which is not very strong, by the way) and conversion from base 10 to base 36.

NOTE: this example only works on numbers hence its using base_convert() to shrink the input string!

function my_number_encrypt($data, $key, $base64_safe=true, $shrink=true) {
        if ($shrink) $data = base_convert($data, 10, 36);
        $data = @mcrypt_encrypt(MCRYPT_ARCFOUR, $key, $data, MCRYPT_MODE_STREAM);
        if ($base64_safe) $data = str_replace('=', '', base64_encode($data));
        return $data;
}

function my_number_decrypt($data, $key, $base64_safe=true, $expand=true) {
        if ($base64_safe) $data = base64_decode($data.'==');
        $data = @mcrypt_encrypt(MCRYPT_ARCFOUR, $key, $data, MCRYPT_MODE_STREAM);
        if ($expand) $data = base_convert($data, 36, 10);
        return $data;
}

$data = "15231223";
$key = "&/ASD%g/..&FWSF2csvsq2we!%%";

echo "data: ", $data, "\n";
$encrypted = my_number_encrypt($data, $key);
echo "encrypted: ", $encrypted, "\n";
$decrypted = my_number_decrypt($encrypted, $key);
echo "decrypted: ", $decrypted, "\n";

Result:

data: 15231223
encrypted: BuF3xdE
decrypted: 15231223
夏末的微笑 2025-01-14 21:56:30
function enminicode($int) {
    $foo = '';
    while ($int) {
        $tmp =  $int%256;
        $int = floor($int/256);
        $foo = chr($tmp) . $foo;
    }
    return base64_encode($foo);
}

function deminicode($b64) {
    $moo = base64_decode($b64);
    $res = 0;
    for ($i = 0; $i <= strlen($moo) - 1; ++$i) {
        $res *= 256;
        $res += ord($moo[$i]);
    }
    return $res;
}

$ii = array(12, 123456, 1000000, 467, 9456724645);
foreach ($ii as $i) {
    echo $i, ': ', enminicode($i), ' => ', deminicode(enminicode($i)), PHP_EOL;
}

其输出:

12: DA== => 12
123456: AeJA => 123456
1000000: D0JA => 1000000
467: AdM= => 467
9456724645: AjOqKqU= => 9456724645

像魅力一样工作。对于 1000000 以内的整数,它将消耗 4 个字母。但为了安全起见,请勿使用此功能!隐匿安全永远不是一种选择,如果用户不知道的话,您永远不会尝试使用这种方法来向用户隐藏号码。

另一个更优雅的解决方案是使用 base_convert,它会产生稍长的字符串,但仍适合 6-7 个字符。

$int = 987654;
$convert = base_convert($int, 10, 16)
$original = base_convert($convert, 16, 10)
echo $convert, PHP_EOL; #f1206
echo $original, PHP_EOL; #987654

输出:

f1206
987654
function enminicode($int) {
    $foo = '';
    while ($int) {
        $tmp =  $int%256;
        $int = floor($int/256);
        $foo = chr($tmp) . $foo;
    }
    return base64_encode($foo);
}

function deminicode($b64) {
    $moo = base64_decode($b64);
    $res = 0;
    for ($i = 0; $i <= strlen($moo) - 1; ++$i) {
        $res *= 256;
        $res += ord($moo[$i]);
    }
    return $res;
}

$ii = array(12, 123456, 1000000, 467, 9456724645);
foreach ($ii as $i) {
    echo $i, ': ', enminicode($i), ' => ', deminicode(enminicode($i)), PHP_EOL;
}

Which outputs:

12: DA== => 12
123456: AeJA => 123456
1000000: D0JA => 1000000
467: AdM= => 467
9456724645: AjOqKqU= => 9456724645

Works like a charm. For integers up to 1000000 it will consume 4 letters. But do not use this for security! Security by obscurity is never an option, and you never try this method to hide a number from the user if they are not meant to know about it.

Another more elegant solution is to use base_convert, which will yield slightly longer strings, but it will still fit within 6-7 characters.

$int = 987654;
$convert = base_convert($int, 10, 16)
$original = base_convert($convert, 16, 10)
echo $convert, PHP_EOL; #f1206
echo $original, PHP_EOL; #987654

output:

f1206
987654
世界等同你 2025-01-14 21:56:30

将其转换为十六进制很简单。

$number= 1000000;
echo base_convert($number, 10, 16); // f4240

您甚至想玩得开心并将其转换为基数 36

$number= 1000000;
echo base_convert($number, 10, 36); 

并执行相反的操作来解码:

$base46_number = 'LFLS';
$decimal = base_convert($base46_number, 36, 10);

It's simple convert it to hexadecimal.

$number= 1000000;
echo base_convert($number, 10, 16); // f4240

You want even have fun and convert it to a base 36

$number= 1000000;
echo base_convert($number, 10, 36); 

And do the reverse operation to decode :

$base46_number = 'LFLS';
$decimal = base_convert($base46_number, 36, 10);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文