簡體   English   中英

比 md5 更短的 php 密碼?

[英]shorter php cipher than md5?

由於各種愚蠢的原因,我們發布到外部服務器的給定表單變量的最大長度為 12 個字符。

我想用 md5 來掩蓋這個值,但顯然 12 個字符是行不通的。 是否有一個帶有已經生成的 PHP 函數的密碼會導致 12 個字符或更少?

密碼的安全性和完整性在這里並不重要。 我最后的辦法是編寫一個函數,將每個字母向上或向下移動一個 ascii 值 x。 所以我們的目標不是讓密碼學專家掩蓋它,而是不要以純文本形式發布它,這樣非技術人員看着它就不會知道它是什么。

感謝您的任何建議。

也許這會幫助您生成一個 12 個字符的字符串,您可以將其傳入 URL,而不會增加沖突的風險

substr(base_convert(md5($string), 16,32), 0, 12);

這是這個答案的補充。

答案建議從 md5 的 32 個字符表示中取出前 12 個字符。 因此,信息的20個字符將會丟失-這將導致更多的方式可能的沖突。

您可以通過采用 16 個字符表示(原始形式)的前 12 個字符來減少信息丟失:

substr(md5($string, true), 0, 12);

這將保留 75% 的數據,而使用 32 字符形式僅保留 37.5% 的數據。

試試 crc32() 也許?

如果您只需要一個散列,您仍然可以使用 md5 散列中的前 12 個字符。

substr(md5($yourString), 0, 12);

所有的答案都建議丟失一些數據(更高的碰撞可能性),但看起來使用基礎轉換是一種更好的方法:例如這里描述的http://proger.i-forge.net/Short_MD5/OMF

您也可以生成任何隨機字符串並將其插入數據庫,在保存之前檢查是否已經存在。 這將允許您擁有較短的哈希值,並確保沒有沖突。

我必須提出這個建議,因為我必須假設你控制着你的加密值被發送到的腳本......

我還必須假設您可以創建許多表單字段,但每個字段的長度不能超過 12 個字符。

如果是這種情況,您是否不能簡單地創建多個表單字段並將 md5 字符串分布在多個隱藏字段中?

您可以將 md5 字符串拆分為 8 個塊,然后在隱藏的表單字段中提交每個塊,然后在另一端將它們連接在一起。

只是一個念頭...

您可以使用更大的字母表並使散列更短,但仍可恢復為原始值。

在這里實現了它 - 例如,哈希ee45187ab28b4814cf03b2b4224eb974變成7fBKxltZiQd7TFsUkOp26w - 它從 32 到 22 個字符。 如果您使用更大的字母表,它會變得更少。 如果您使用 unicode,您甚至可以使用表情符號對哈希進行編碼...

這可能對 OP 沒有用,因為他們正在尋找 2 路函數,但可能會幫助尋找比 md5 更短的哈希值的人。 這是我根據我的需要提出的(感謝https://rolandeckert.com/notes/md5突出顯示 base64_encode 函數)。 將 md5 哈希編碼為 base(64) 並刪除任何不需要的 base(64) 字符。 我正在刪除元音 + 和/,因此將有效基數從 64 減少到 52。

請注意,如果您在 c 個字符之后截斷 base(b) 編碼的散列,它將允許 b ^ c 唯一散列。 這是否足以避免碰撞? 這取決於您要散列的項目數 (k)。 碰撞的概率大約是 (k * k) / (b ^ c) / 2,所以如果你使用下面的函數散列 k = 100 萬個項目,基數 b = 52 編碼在 c = 12 個字符后被截斷,碰撞概率小於 7.5 億分之一。 與在 c = 12 個字符后截斷十六進制編碼 (b = 16) 哈希相比。 碰撞的概率大約是 500 分之一! 只需對截斷十六進制編碼的哈希說不。 :)

我會大膽地說下面的函數(長度為 12)對於 1000 萬個項目是相當安全的(在 750 萬個碰撞概率中小於 1),但是如果你想更加安全,請使用 base(64) 編碼(注釋掉 $remove 數組)和/或截斷更少的字符。

// convert md5 to base64, remove undesirable characters and truncate to $length
function tinymd5($str, $length) { // $length 20-22 not advised unless $remove = '';
    // remove vowels to prevent undesirable words and + / which may be problematic
    $remove = array('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U', '+', '/');
    $salt = $str;
    do { // re-salt and loop if rebase removes too many characters
        $salt = $base64 = base64_encode(md5($salt, TRUE));
        $rebase = substr(str_replace($remove, '', $base64), 0, $length);
    } while ($length < 20 && substr($rebase, -1) == '=');
    return str_pad($rebase, min($length, 22), '='); // 22 is max possible length
}

$str = 'Lorem ipsum dolor sit amet 557726776';
echo '<br />' . md5($str);         // 565a0bf7e0ba474fdaaec57b82e6504a
$x = md5($str, TRUE);
echo '<br />' . base64_encode($x); // VloL9+C6R0/arsV7guZQSg==
echo '<br />' . tinymd5($str, 12); // VlL9C6R0rsV7
echo '<br />' . tinymd5($str, 17); // VlL9C6R0rsV7gZQSg
$x = md5(base64_encode($x), TRUE); // re-salt triggered < 20
echo '<br />' . base64_encode($x); // fmkPW/OQLqp7PTex0nK3NQ==
echo '<br />' . tinymd5($str, 18); // fmkPWQLqp7PTx0nK3N
echo '<br />' . tinymd5($str, 19); // fmkPWQLqp7PTx0nK3NQ
echo '<br />' . tinymd5($str, 20); // fmkPWQLqp7PTx0nK3NQ=
echo '<br />' . tinymd5($str, 22); // fmkPWQLqp7PTx0nK3NQ===

$hashlen = 4;
$cxstrong = 真;
$sslk = openssl_random_pseudo_bytes($hashlen, $cxtrong);
$rand = bin2hex($sslk);

回聲 $rand;

您可以通過更改變量 $hashlen 的值來更改哈希長度(以 2 的倍數表示)

我想出了以 90 為基數,用於將 md5 減少到 20 個多字節字符(我測試它是否適合 mysql 的 varchar(20) 列)。 不幸的是,這實際上使字符串可能比 php 的 md5 中的 32 個字節還要大,唯一的優點是它們可以存儲在 varchar(20) 列中。 當然,如果您擔心存儲,您可以用單字節字母替換字母表......

如果您的想法是在 mysql 和其他類型的處理中使用這個簡化的哈希作為查找鍵,則需要牢記一些重要的規則:

  1. 默認情況下,MySQL 不會在典型的 where 子句中區分大寫和小寫,該子句從可能的目標字母表中取出大量字符。 這不僅包括英文字符,還包括幾乎所有其他語言的字符。

  2. 重要的是,您的散列可以透明地大寫和小寫,因為許多系統將這些鍵大寫,因此為了在這個意義上保持它與 md5 一致,在使用可區分大小寫的字符時應該只使用小寫。

這是我使用的字母表(我精心挑選了每個字符以使哈希值盡可能好):

define('NICIESTCHARS', [
    "0","1","2","3","4","5","6","7","8","9",
    "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",
    "¢","£","¥","§","¶","ø","œ","ƒ","α","δ","ε","η","θ","ι","λ","μ","ν","π","σ","τ","φ","ψ","ω","ћ","џ","ѓ","ѝ","й","ќ","ў","ф","э","ѣ","ѷ","ѻ","ѿ","ҁ","∂","∆","∑","√","∫",
    "!","#","$","%","&","*","+","=","@","~","¤","±"
]);

這是 PHP 中的代碼(我想它不是最好的代碼,但可以完成工作)。 請記住,它僅適用於長度為 8 的倍數的六進制 (0-F) 字符串,例如 php 中的 md5,即 32 個 0-f 字節:

function mbStringToArray ($string) {
    $strlen = mb_strlen($string);
    while ($strlen) {
        $array[] = mb_substr($string,0,1,"UTF-8");
        $string = mb_substr($string,1,$strlen,"UTF-8");
        $strlen = mb_strlen($string);
    }
    return $array;
} 

class Base90{ 
    static function toHex5($s){
        // Converts a base 90 number with a multiple of 5 digits to hex (compatible with "hexdec").
        $chars = preg_split('//u', $s, null, PREG_SPLIT_NO_EMPTY);
        $map = array_flip(NICIESTCHARS);
        $rt = '';
        $part = [];
        $b90part = '';
        foreach($chars as $c){
            $b90part .= $c;
            $part[] = $map[$c];
            if(count($part) == 5){
                $int = base90toInt($part);
                $rt .= str_pad(dechex($int), 8, "0", STR_PAD_LEFT);
                $part = [];
                $b90part = '';
            }
        }
        return $rt;
    }
    
    static function fromHex8($m){
        // Converts an hexadecimal number compatible with "hexdec" to base 90
        $parts = [];
        $part = '';
        foreach(str_split($m) as $i => $c){
            $part.= $c;
            if(strlen($part) === 8){
                $parts[] = intToBase90(hexdec($part));
                $part = '';
            }
        }
        return implode('', $parts);
    }
}



function intToBase90($int){
    $residue = $int;
    $result = [];
    while($residue){
        $digit = $residue % 90;
        $residue -= $digit;
        $residue = $residue / 90;
        array_unshift($result,  NICIESTCHARS[$digit]);
    }
    $result = implode('', $result);
    return $result;
}

function base90toInt($digits){
    $weight = 1;
    $rt = 0;
    while(count($digits)){
        $rt += array_pop($digits)*$weight;
        $weight *= 90;
    }
    return $rt;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM