无法解密

问题描述:

为了Ø能够创建我用我发现这里的代码中的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/>"; 
} 
+1

术语挑剔:一个散列不(容易)可逆的。如果你认为你可以很容易地扭转这个“散列”,那么它不是一个散列,而是完全不同。 –

+1

这也不是加密,它是编码。 @BeoWulf如果你想了解它们,这些术语在这里解释(https://paragonie.com/blog/2015/08/you-wouldnt-base64-a-password-cryptography-decoded)。 –

+0

我知道我没有使用正确的术语。我很清楚散列意味着什么,加密是什么,但我只是用它,因为它是如何在我用于此目的的原始代码中呈现的。我没有花时间更好地解释我真正想要的,但是我的目标是将任何从1到1的整数转换成10或000个字节的单个字符串。 – BeoWulf

难道你不想在下面的代码,而不是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); 
+0

感谢您的反馈。 我想你忘了添加链接到你的第一段。 我知道我没有使用正确的术语。我很清楚散列意味着什么,加密是什么,但我只是用它,因为它是如何在我用于此目的的原始代码中呈现的。我没有花时间更好地解释我真正想要的,但是我的目标是将任何从1到1的整数转换成10或000个字节的单个字符串。 – BeoWulf

+0

@BeoWulf更新回答问题 –

+0

你的更新并没有真正实现我想要做的。不管怎么说,还是要谢谢你。 如果您可以分享您在第一段中提到的解决方案的链接,那么您会说:“创建一个6个字符不区分大小写的可逆灰,我使用了我在此处找到的代码:”。 – BeoWulf

我开发的解决方案我自己,所以我在这里分享代码。

这个问题在我的问题的代码是在$ 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/>"; 
} 
+0

如果在没有这种情况下没有将编码称为“可逆”散列“,那么这将是一个可选择的答案。这是一种编码。 – zaph