无法解密
为了Ø能够创建我用我发现这里的代码中的6个字符大小写不敏感可逆灰:http://web.archive.org/web/20130727034425/http://blog.kevburnsjr.com/php-unique-hash其使用Base64工作并将其转化与base36工作。无法解密
不过,我不能哈希逆转到其原始值的原始代码类的base64一样。
编辑: 为了回应我在这里得到的反馈,我明白我没有使用正确的术语。我很清楚散列意味着什么,加密是什么,但我只是用它,因为它是如何在我用于此目的的原始代码中呈现的。 我没有花时间来更好地解释我真正想要的,但我的目标是要1转换任何整数让说10.000.000为6或8个字节的唯一字符串。
编辑:张贴我的解决方案下面作为答案。
class PseudoCrypt {
/* Key: Next prime greater than 36^n/1.618033988749894848 */
/* Value: modular multiplicative inverse */
private static $golden_primes = array(
'1' => '1',
'41' => '59',
'2377' => '1677',
'147299' => '187507',
'9132313' => '5952585',
'5662' => '643566407',
'35104476161' => '22071637057',
'2176477521929' => '294289236153',
'134941606358731' => '88879354792675',
'8366379594239857' => '7275288500431249',
'518715534842869223' => '280042546585394647'
);
/* Ascii : 0 9, A Z, a z */
/* $chars = array_merge(range(48,57), range(65,90), range(97,122)) */
private static $chars36 = array(
0=>48,
1=>49,
2=>50,
3=>51,
4=>52,
5=>53,
6=>54,
7=>55,
8=>56,
9=>57,
10=>65,
11=>66,
12=>67,
13=>68,
14=>69,
15=>70,
16=>71,
17=>72,
18=>73,
19=>74,
20=>75,
21=>76,
22=>77,
23=>78,
24=>79,
25=>80,
26=>81,
27=>82,
28=>83,
29=>84,
30=>85,
31=>86,
32=>87,
33=>88,
34=>89,
35=>90
);
public static function base36($int) {
$key = '';
while($int > 0) {
$mod = $int-(floor($int/36)*36);
$key .= chr(self::$chars36[$mod]);
$int = floor($int/36);
}
return strrev($key);
}
public static function hash($num, $len = 5) {
$ceil = bcpow(36, $len);
$primes = array_keys(self::$golden_primes);
$prime = $primes[$len];
$dec = bcmod(bcmul($num, $prime), $ceil);
$hash = self::base36($dec);
return str_pad($hash, $len, "0", STR_PAD_LEFT);
}
public static function unbase36($key) {
$int = 0;
foreach(str_split(strrev($key)) as $i => $char) {
$dec = array_search(ord($char), self::$chars36);
$int = bcadd(bcmul($dec, bcpow(36, $i)), $int);
}
return $int;
}
public static function unhash36($num, $len = 5) {
$ceil = pow(36, $len);
$prime = self::$golden_primes[$len];
$dec = ($num * $prime)-floor($num * $prime/$ceil)*$ceil;
$hash = self::base36($dec);
return str_pad($hash, $len, “0″, STR_PAD_LEFT);
}
}
echo "<pre>";
foreach(range(1, 100000) as $n) {
echo $n." - ";
$hash = PseudoCrypt::hash($n, 8);
echo $hash." - ";
echo PseudoCrypt::unhash36($hash)."<br/>";
}
难道你不想在下面的代码,而不是base36(..)
做unbase36(..)
?
public static function unhash36($num, $len = 5) {
$ceil = pow(36, $len);
$prime = self::$golden_primes[$len];
$dec = ($num * $prime)-floor($num * $prime/$ceil)*$ceil;
$hash = self::base36($dec); <=== problem
return str_pad($hash, $len, “0″, STR_PAD_LEFT);
}
为了Ø能够创建一个6个字符,不区分大小写可逆灰我用我发现这里的代码:
Hashes是不可逆的,通过定义。
但是,我无法将散列翻转为原始值,因为带有base64的类的原始代码确实如此。
Base64不是散列,它是a method of encoding arbitrary data。
你想不区分大小写的编码解决什么样的问题?这是否适用于子域名?
编辑 - 回答评论:
我真正想要的,但我的目标是到任何整数从1转换为可以说10.000.000为6或8个字节的唯一字符串。
这种描述听起来危险地接近encrypting URL parameters,这是一个反模式,将不可避免地导致严重的痛苦在未来的一些开发商。
除此之外,该解决方案是非常简单的:
$string = base_convert($integer, 10, 36);
然后做相反:
$integer = base_convert($string, 36, 10);
我开发的解决方案我自己,所以我在这里分享代码。
这个问题在我的问题的代码是在$ golden_primes阵列需要有不同的值,以匹配基于36个字符的素数,而不是62
它可以完美运行生成唯一的字符串(大写字母和数字),用1到99,999,999,999,999(最多9个可逆“散列”字符)进行测试,没有发生任何冲突。
代码:
<?php
class PseudoCrypt {
/* Key: Next prime greater than 36^n/1.618033988749894848 */
/* Value: modular multiplicative inverse */
private static $golden_primes = array(
'1' =>'1',
'23' =>'11',
'809' =>'809',
'28837' => '29485',
'1038073' =>'179017',
'37370153' => '47534873' ,
'1345325473' => '264202849',
'48431716939' => '19727015779',
'1743541808839' =>'1532265214711',
'62767505117101' =>'67935388019749'
);
/* Ascii : 0 9, A Z, a z */
/* $chars = array_merge(range(48,57), range(65,90), range(97,122)) */
private static $chars36 = array(0=>48, 1=>49, 2=>50, 3=>51, 4=>52, 5=>53, 6=>54, 7=>55, 8=>56, 9=>57,10=>65,11=>66,12=>67,13=>68,14=>69,15=>70,16=>71,17=>72,18=>73,19=>74,20=>75,21=>76,22=>77,23=>78,24=>79,25=>80,26=>81,27=>82,28=>83,29=>84,30=>85,31=>86,32=>87,33=>88,34=>89,35=>90);
public static function base36($int) {
$key = "";
while($int > 0) {
$mod = $int-(floor($int/36)*36);
$key .= chr(self::$chars36[$mod]);
$int = floor($int/36);
}
return strrev($key);
}
public static function unbase36($key) {
$int = 0;
foreach(str_split(strrev($key)) as $i => $char) {
$dec = array_search(ord($char), self::$chars36);
$int = bcadd(bcmul($dec, bcpow(36, $i)), $int);
}
return $int;
}
public static function hash($num, $len = 5) {
$ceil = bcpow(36, $len);
$primes = array_keys(self::$golden_primes);
$prime = $primes[$len];
$dec = bcmod(bcmul($num, $prime), $ceil);
$hash = self::base36($dec);
return str_pad($hash, $len, "0", STR_PAD_LEFT);
}
public static function unhash($hash) {
$len = strlen($hash);
$ceil = bcpow(36, $len);
$mmiprimes = array_values(self::$golden_primes);
$mmi = $mmiprimes[$len];
$num = self::unbase36($hash);
$dec = bcmod(bcmul($num, $mmi), $ceil);
return $dec;
}
}
/// Test
echo "<pre>";
foreach(range(99999999990000, 99999999999999) as $n) {
echo $n." - ";
$hash = PseudoCrypt::hash($n, 9);
echo $hash." - Reversed: ";
echo PseudoCrypt::unhash($hash)."<br/>";
}
如果在没有这种情况下没有将编码称为“可逆”散列“,那么这将是一个可选择的答案。这是一种编码。 – zaph
术语挑剔:一个散列不(容易)可逆的。如果你认为你可以很容易地扭转这个“散列”,那么它不是一个散列,而是完全不同。 –
这也不是加密,它是编码。 @BeoWulf如果你想了解它们,这些术语在这里解释(https://paragonie.com/blog/2015/08/you-wouldnt-base64-a-password-cryptography-decoded)。 –
我知道我没有使用正确的术语。我很清楚散列意味着什么,加密是什么,但我只是用它,因为它是如何在我用于此目的的原始代码中呈现的。我没有花时间更好地解释我真正想要的,但是我的目标是将任何从1到1的整数转换成10或000个字节的单个字符串。 – BeoWulf