我有一個腳本可以轉換爲基礎62(A-Za-z0-9),但是如何從MD5中獲取數字?將MD5轉換爲base62的URL
我讀過很多地方,因爲從MD5的數字大於PHP可以作爲一個整數處理它將是不準確的......因爲我想要一個簡短的URL,並沒有計劃使用整個散列,也許只是8個字符...
所以我的問題是如何獲得一部分MD5哈希的數量?
也只是使用部分MD5散列是一個壞主意?
我有一個腳本可以轉換爲基礎62(A-Za-z0-9),但是如何從MD5中獲取數字?將MD5轉換爲base62的URL
我讀過很多地方,因爲從MD5的數字大於PHP可以作爲一個整數處理它將是不準確的......因爲我想要一個簡短的URL,並沒有計劃使用整個散列,也許只是8個字符...
所以我的問題是如何獲得一部分MD5哈希的數量?
也只是使用部分MD5散列是一個壞主意?
我要在這裏建議一個不同的東西..既然你只是在使用md5散列的小數部分感興趣,爲什麼不使用任何其他的短數字散列如CRC32或Adler?這裏是一個例子:
$hash = sprintf('%u', crc32('your string here'));
這將產生一個8位數的字符串散列。
編輯:我想我誤解了你,here are some functions that provide conversions to and from bases up to 62。
EDIT(再次):要使用任意長度的數字工作,你必須使用bc_math或GMP擴展,here is a function that uses the bc_math extension and can also convert from base 2 up to base 62。你應該使用這樣的:
echo bc_base_convert(md5('your url here'), 16, 62); // public base 62 hash
和逆:
echo bc_base_convert('base 62 encoded value here', 62, 16); // private md5 hash
希望它能幫助。 =)
是否可以計算出什麼進入散列?只是我在想,如果我只展示過散列的一部分,它就會讓它更難以鍛鍊它是如何產生的......對嗎? – Mark 2009-12-10 11:32:35
沒錯,但它不會是真正意義上的散列,也可能發生碰撞。 – 2009-12-10 11:50:15
你可以做到這一點是這樣的:(並非所有的步驟都在PHP中,它一直是我已經使用了很長一段時間)
像這樣創建腳本的MD5哈希:
$ hash = md5(script,raw_output = true);
轉換,這個數字將基座62
截斷字符串你喜歡的長度。
只使用md5的幾個位沒有風險。所有這些變化都是碰撞的危險。
不錯的鏈接,謝謝。 – 2009-12-10 11:23:34
你可以使用一個稍加修改基地64 -
和_
,而不是+
和/
:
function base64_url_encode($str) {
return strtr(base64_encode($str), array('+'=>'-', '/'=>'_'));
}
function base64_url_decode($str) {
return base64_decode(strtr($str, array('-'=>'+', '_'=>'/')));
}
此外,你可以刪除尾隨填充=
字符。
而獲得的原始MD5值(二進制字符串),設置第二個參數(手冊中提及$raw_output
)至真:
$raw_md5 = md5($str, true);
檢查此問題http://stackoverflow.com/questions/352434/base-conversion-of-arbitrary-sized-numbers-php/1743486#1743486 – 2009-12-10 11:47:22
有什麼問題?爲什麼倒票? – Gumbo 2009-12-10 14:09:32
如果有可能,我建議不使用哈希值爲您的網址。最終你會遇到碰撞...特別是如果你截斷散列。如果你繼續實施一個基於ID的系統,每個項目都有一個唯一的ID,那麼頭痛就會少得多。第一項是1
,第二項是2
等---如果你使用的是MySQL,只需要輸入一個自動增量列。
作一個簡短的ID:
//the basic example
$sid = base_convert($id, 10, 36);
//if you're going to be needing 64 bit numbers converted
//on a 32 bit machine, use this instead
$sid = gmp_strval(gmp_init($id, 10), 36);
作一個簡短的ID回基地10 ID:
//the basic example
$id = base_convert($id, 36, 10);
//if you're going to be needing 64 bit numbers
//on a 32 bit machine, use this instead
$id = gmp_strval(gmp_init($shortid, 36));
希望這有助於!
如果你想真正基地62(不能用gmp
或base_convert
來完成),檢查了這一點: http://snipplr.com/view/22246/base62-encode--decode/
GMP,不錯! =) – 2009-12-10 11:22:46
對不起,也許我沒有讓自己清楚,md5沒有發揮作爲一個id ...只是作爲一種方法來阻止用戶猜測下一個url ...所以url是id = 1&md5 = dsf213sfe。無論如何謝謝 – Mark 2009-12-10 11:29:54
夠公平!我的錯。別介意我:) – brianreavis 2009-12-10 11:43:22
你可以做這樣的事情,
$hash = md5("The data to be hashed", true);
$ints = unpack("L*num", $hash);
$hash_str = base62($ints['num1']) . base62($ints['num2']) . base62($ints['num3']) . base62($ints['num4'])
有實際上是一個你可能會提取的Java實現。這是一個名爲Pulse的開源CMS解決方案。
這裏尋找代碼toBase62()
和fromBase62()
。
http://pulse.torweg.org/javadoc/src-html/org/torweg/pulse/util/StringUtils.java.html
唯一依賴於StringUtils
是生命週期類,它提供一種方式來獲得一個鹽醃哈希值,你甚至可以忽略一起或剛剛超過複製方法,以您的副本StringUtils
的字符串。瞧。
從PHP 5.3.2起,GMP支持的基數可達62(以前只有36),所以brianreavis的建議非常接近。我認爲你的問題最簡單的答案是這樣的:
function base62hash($source, $chars = 22) {
return substr(gmp_strval(gmp_init(md5($source), 16), 62), 0, $chars);
}
從base-16轉換爲base-62顯然有空間的好處。正常的128位MD5哈希是十六進制的32個字符,但是在基數爲62的情況下它只有22個。如果將哈希存儲在數據庫中,則可以將它們轉換爲原始二進制,並節省更多空間(16字節MD5)。
由於生成的哈希值只是一個字符串表示形式,所以如果您只需要一小部分(如函數那樣)就可以使用substr。
你可以嘗試base62x以獲得安全和兼容的編碼表示。
Here is for more information about base62x,或簡單-base62x
在-NatureDNS
。
shell> ./base62x -n 16 -enc 16AF
1Ql
shell> ./base62x -n 16 -dec 1Ql
16AF
shell> ./base62x
Usage: ./base62x [-v] [-n <2|8|10|16|32>] <-enc|dec> string
Version: 0.60
md5散列不是一個數字,那麼「部分數字」是什麼意思? – 2009-12-10 10:51:28
md5是一個以base36編碼表示的數字,我認爲... – Mark 2009-12-10 10:53:37
你是一半的權利,md5散列是以16爲底的數字(a-f0-9)表示的十六進制數。 – 2009-12-10 10:57:22