2010-11-08 129 views
2

基本上,我正在尋找一個函數來執行以下如何生成一個128位長的字符串?

generateToken(128) 

將返回一個128位由整數或字母字符。

說明:從評論中,我不得不改變這個問題。顯然,如果需要128位,我正在查找一個長度爲16個字符的字符串。

+0

什麼是有128位?字符串表示的數量? – Artefacto 2010-11-08 01:36:09

+0

Axsuul位的長度 – axsuul 2010-11-08 01:37:55

+0

,你的迴應沒有任何意義。 – Artefacto 2010-11-08 01:43:31

回答

3

是否有理由限制字符串爲整數?這實際上使問題變得更加困難,因爲每個數字都會給出3.3位(因爲2^3.3〜= 10)。以這種方式生成正好128位的令牌是非常棘手的。

更容易的是允許十六進制編碼(每個字符4位)。然後,您可以生成128個真正的隨機位,然後將它們編碼爲十六進制,以便在應用程序中使用。 Base64編碼(每個字符6位)對於這種事情也很有用。

openssl_random_pseudo_bytes會給你一串隨機字節,你可以使用bin2hex進行編碼,否則你可以在你自己的令牌生成例程中使用mt_rand

編輯:在閱讀問題的更新之後,似乎您想要生成一個表示128位數據的標記,而實際的字符串長度(以字符表示)並不那麼重要。如果我正確地猜測你的意圖(這是一個唯一的ID,可能用於識別/認證),那麼我建議你使用openssl_random_pseudo_bytes來爲你的問題產生正確的位數,在這種情況下是128(16字節)。然後你可以用你認爲合適的方式對這些位進行編碼:hex和base64是兩種可能性。

請注意,由於每個字符只能編碼4位(128/4 = 32),所以十六進制編碼將使用32個字符來編碼128位數據。 Base64將使用22個字符(128/6 = 21.3)。每個字符佔用8位存儲,但僅編碼4或6位信息

要非常小心,不要將編碼的字符串長度與原始數據長度混淆。如果您選擇使用字母數字字符(az,AZ,0-9)的16個字符的字符串,那麼每個字符只能獲得6位信息(62的對數基數2接近6),因此您的16個字符的字符串將僅進行編碼96位信息。你應該將你的令牌想象成一個不透明的字節數組,並且只有當你試圖通過網絡發送它或者把它放入一個cookie或其他東西時,纔會擔心它會變成/從一個字符串中。

+0

'openssl_random_pseudo_bytes'不給出十六進制編碼表示。無論如何,這是一個很好的解決方案。之後,這只是一個使用例如bcmath構建基數爲10的字符串表示形式的數字。 – Artefacto 2010-11-08 01:50:36

+0

是的,你是對的。我誤讀了這個例子,並且省略了'bin2hex'位:) – 2010-11-08 01:51:16

+0

相關:請參閱http://stackoverflow.com/questions/2982112/encoding-arbitrary-data-into-numbers/3402951#3402951瞭解如何將任意數據轉換爲數字以10爲底數。 – Artefacto 2010-11-08 01:55:05

0

你的目的是什麼?

如果你只是想要一個唯一的ID,然後使用uniqid:

http://www.php.net/manual/en/function.uniqid.php

它不是隨機的,它本質上是一個十六進制字符串基於microtime中。如果你使用uniqid('',true),那麼它將返回一個基於microtime的十六進制字符串,並在id末尾添加一堆隨機數(即使兩個調用在同一微秒內進入,他們不太可能共享一個唯一的ID)。

如果您確切需要16個字符的字符串,那麼目的是什麼?你是在醃製密碼嗎?字符串應該如何隨機?總而言之,你總是可以這樣做:

$toShow = array(); 
for($i = 0; $i<16; $i++){ 
    $toShow[] = chr(mt_rand(ord('a'), ord('z'))); 
} 
return $toShow 

現在,這將創建一個介於'a'和'z'之間的字符串。您可以將「ord('a')」更改爲0,將「ord('z')」更改爲255,以獲得完全隨機的二進制字符串...或您需要的任何其他範圍。

1

由於PHP 5.3:

$rand128 = bin2hex(openssl_random_pseudo_bytes(16)); 
相關問題