2010-11-08 126 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)); 
相关问题