您的位置:首页 > 其它

蛙蛙推荐:有关随机数的一些讨论

2005-07-28 11:53 393 查看
蛙蛙推荐:有关随机数的一些讨论[/b]

Hogwarts[/b]

关于生成随机数,有以下几个可以选择的方案:

1) System.Random

2) xdev所提到的System.Security.Cryptography.RNGCryptoServiceProvider

3) 直接调用Platform SDK中的CryptGenRandom()函数。

其中,和1)相比,2)和3)可以被作为真正的随机数来使用。

System.Random是最简单最常用的随机数发生器,如果用系统当前时间做种子,基本上可以做到“伪”随机。但是用System.Random得到的随机数的安全性是不高的,用户完全可以用一些方法根据已经生成的随机数序列预测出下一个随机数的值。在一些用到加密的场合,随机数序列可被预测会导致很严重的漏洞,例如曾经有扑克牌游戏网站由于使用了可以被预测的随机数发生器来实现随机发牌而导致的安全漏洞(参见http://www.cigital.com/news/gambling.html)。

如果需要更“随机”的随机数,应该使用System.Security.Cryptography.RNGCryptoServiceProvider或者Platform SDK中的CryptGenRandom()函数。System.Security.Cryptography.RNGCryptoServiceProvider是对System.Security.Cryptography.RandomNumberGenerator接口的一个实现,提供了获得可用于加密的随机数序列(cryptographically strong random values)的方法。

Platform SDK中的CryptGenRandom()函数也是一个非常好的随机数发生器,他在生成随机数的时候不单单用到了系统时间,还用到了Process ID、Thread ID以及大量系统信息。当然,CryptGenRandom()和RNGCryptoServiceProvider在提供更好的随机数的同时,不可避免的是速度方面的性能要逊于System.Random。

bugfree([/b]八个飞飞)[/b]

所谓的伪随机,是指每次产生的序列一样。比如你用一个种子,产生的序列是1, 9, 7, 5,再用这个种子产生,还是1, 9, 7, 5,但是1, 9, 7, 5本身是随机的。还有DateTime.Ticks 此属性的值为自 0001 年 1 月 1 日午夜 12:00 以来所经过时间以 100 毫微秒为间隔表示时的数字。可以自己写随机数函数,比如比较著名的随机数生成方法是”高斯随机数“。

happycock(SSWW)[/b]

所谓的随机数就是一堆加在一起满足某种统计规律的数,而自身是毫无规律的。应该说这是从现实中抽取出来的一个概念,而在计算机中要想模拟是比较困难的。伪随机是指虽然他满足某种统计规律,但是对于一个特定的“种子”,他的序列是一定的,也就是说对于1做种子,产生的序列永远都是xxxx,因此他不满足“随机”特点,所以是“伪”的。

ckc([/b]火)[/b]

我觉得happycock刚好说反了,真正的随机数是不应该有统计规律的,而实际的随机算法因为算法的限制,是有统计规律的,当然,这个统计规律可能比较复杂,但是,只要有统计规律,就意味着我们可以找到一个方法预测随机数序列的下一个值,或者说可以以较大的概率猜测下一个值。

内存中的数据如果没有初始化,它的值是不变的,这个值我们不知道,但是你执行1万次,它也许有9999次都是0,这个我们没办法叫它是随机数,或者说这个地方的随机数和我们需要的严格意义的随机数概念不同。这个地方我们叫它随机数只是强调我们不知道它的值。

[/b]

happycock(SSWW)[/b]

大量的随机过程是符合统计规律的,这是没有疑问的。这正是“事物都是有规律的”的一个证明,“无规律”只是没有找到规律。所以无规律的随机是不存在的。寻找无规律的随机是徒劳的。还有,rand()是符合平均分布的随机,不是正态分布。

关于内存中数据的初始化,不知你懂不懂什么叫“时序电路”,可以类比一下,那个数跟很多因素有关,刚上电的时候跟器件的电气属性有关,所以当你重复试验的时候,就能得出是符合规律的。在程序运行中,是上个使用这块内存的变量的值。这也是有规律的。

pengzhenwanli([/b]紫气日盈)[/b]

真正的随机数应用,其实严格来说是要求有一定规律的,对于可控的随机数,计算机确实没法产生,但是不可控的随机数,要它来没什么意义。

#include <stdio.h>

#include <stdlib.h>

#include <string.h>
#include <assert.h>

#include <time.h>

int main()

{

int i;

srand( (unsigned int)time(NULL) );

for( i = 0; i<100;i++)

{

if( i %10 == 0 && i!= 0 )

printf("\n" );

printf("%d ",rand() %100);

}

}

如果没有种子,每次产生出来的数一样的。不信,你删去srand这句试试

maxcai(cailin)[/b]

关于随机数的讨论及研究有两点:

1。是否真正随机

2。是否足够安全

真正的随机是很难得到的,代价也很高,而是否有足够的安全(相对)往往是追求的目标

要得到一个随机的数,理论上就只有依靠硬件,intel P3以上的cpu应该都有一个

叫什么来着?你可以察看一下相关资料,好像是根据热能(量)来确定的。当然,在不要求安全的前提下,可以用伪随机函数rand(),及time()设定随机种子。这样就足够了。

haowh([/b]一个人走在黑黑的夜) [/b]

在加密解密的过程中随机数起着相当重要的作用。所以随机数的质量受到关注。如何高效产生高质量的随机数是一个重要课题。

以ASCII码组成的随机数为例,随机数最基本的检验:我们知道有256个ASCII码其数值是0到255,当一组随机数个数较多时其平均值应为127.5。两组组元相同的随机数其重码率约为1/256=0.00390625。如果偏离此 2 数较远则不是好的随机数。

随机数发生的方法:

有用 C 语言中的随机数发生器产生的随机数一般还可以。如果想用高质量的随机数。可参考以下方法:《序列数改造方法》

先造一个序列仍以ASCII码组成的随机数为例,例如想造一个有2560个元素的随机数列:

1. 先造一个数值由零到255的循环数列长度为2560

2. 随机抽取两的序号使它们的数值交换

3. 使 2 进行足够多次取其一部分检测其效果,直到满意。

这里基于一个原理:如果我们随机的去变化一个数的集合,它只能是越来越无序化。就象在一个盘子里放着大小一样但颜色不同的几小堆沙子,我们去搅和这些沙子只能使它们融合的越来越好,而不可能相反。

所以尽管上面“随机抽取两的序号使它们的数值交换”是用伪随机数来完成的。但也不可能产生向有序化发展的趋势。在实际操作中,可以加一些“倒序”、“取反”之类的操作以加快进程。

基本上采用平台自己提供的随机数方法,很容易破解。现在好象听说unix 下的 yarrow 还可以。windows 自带的就一点都不敢用。

netscape 的 ssl 就是因为随机数的算法很烂,已经被人破解了!算法如下::

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

global variable seed;

RNG_CreateContext()

(seconds, microseconds) = time of day; /* Time elapsed since 1970 */

pid = process ID; ppid = parent process ID;

a = mklcpr(microseconds);

b = mklcpr(pid + seconds + (ppid << 12));

seed = MD5(a, b);

mklcpr(x) /* not cryptographically significant; shown for completeness */

return ((0xDEECE66D * x + 0x2BBB62DC) >> 1);

MD5() /* a very good standard mixing function, source omitted */

再看看它的密钥算法

〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉

shows the key-generation algorithm, also reverse-engineered from Netscape's browser. An attacker who can guess the PRNG seed value can easily determine the encryption keys used in Netscape's secure transactions.

RNG_GenerateRandomBytes()

x = MD5(seed);

seed = seed + 1;

return x;

global variable challenge, secret_key;

create_key()

RNG_CreateContext();

tmp = RNG_GenerateRandomBytes();

tmp = RNG_GenerateRandomBytes();

challenge = RNG_GenerateRandomBytes();

secret_key = RNG_GenerateRandomBytes();

mgphuang(tony)[/b]

这样的这样的序列并不是一个好的序列。

通常可复用的序列都不是一个真随机的序列。通常一个好的随机的序列有一些衡量的标准。

比如:0和1大致相等,游程平均分布。熵值近似为0。

通常产生一个足够长的的伪随机序列的方法是使用用非线性移位器。

SweetJerry()[/b]

好的随机数生成需要用到如:大(素)数乘法,对称加密(解密)算法,哈希算法,反馈控制,置换等.

随机性有一些简单的测试方法.

BruceZhang([/b]瓷)[/b]

我是学统计的,在统计学上认为用计算机计算出来的都是伪随机数,如果用Round()可以用时间当种子,如果对随机数要求不高的话,直接就可以用时间做随机数,方法如下:

1、取出时间,取到百分秒

2、将取出的时间值做运算(+ - * /),具体算法自定,但保证结果为正值

3、求模(取余),是要求出一个适合你要求范围的值

4、重复2、3即可得到更多的随机数

[/b]

其它:[/b]

随机数就是不能通过已经得到的数列来推出将要得到的数列。实际应用中还没有软件可以生成真正的随机数。目前的很多的密码应用都有与之相应的(相配套的)硬件,用硬件来产生随机数。真正的随机数可以取机器的物理噪声方法来做,那种绝对是真正的随机数。

我又想到一个办法,现在的CPU大多支持rdtsc指令,通过这个读取CPU时间戳,不知随机性如何。

有一个数学命题,一付扑克洗成绝对均匀的时候,就是原来的次序,而且被证明成立了。

C#[/b]如何获取随机数[/b]

下面是我做的一个c#里使用随机数的一个演示,微软专家提到的第一种和第二种都演示了,还演示了如何得到比较随机的种子,最后一种CryptGenRandom()的需要调用com+,限于时间关系,没有做演示。

using System;

using System.Security.Cryptography;

namespace ConsoleApplication1

{

public class RandomTest

{

public RandomTest()

{

}

public static void Main()

{

Random rand = new Random();//如果这里指定种子的话,每次随机出的数都是一样的

for(int i =0;i<2;i++)

Console.WriteLine(rand.Next().ToString()+"\n");//输出2个伪随机数

Console.WriteLine(rand.Next(5,10)); //在5到10之间生成一个伪随机数

Console.WriteLine(rand.Next(10)); //生成0到10之间的伪随机数

rand=new Random(Guid.NewGuid().GetHashCode()); //根据GUID生成一个种子

Console.WriteLine(rand.Next());

rand = new Random(~unchecked(unchecked((int)DateTime.Now.Ticks) << 1)); //根据时间随机生成一个种子

Console.WriteLine(rand.Next(1,10));

Console.WriteLine(RandomStr.GetRndStrOfAll()); //用所有可打印字符随机生成一个串,默认是8个长度

Console.WriteLine(RandomStr.GetRndStrOfAll(10)); //获取指定长度的所有可打印字符组成的随即串

Console.WriteLine(RandomStr.GetRndStrOnlyFor()); //获取默认长度的随机字母数字组合

Console.WriteLine(RandomStr.GetRndStrOnlyFor(20)); //获取指定长度的随机字母数字组合

Console.WriteLine(RandomStr.GetRndStrOnlyFor(true,true));//指定是否使用大写字母和数字

Console.WriteLine(RandomStr.GetRndStrOnlyFor(10,false,false));//指定是否使用大写字母和数字,以及指定长度

Console.ReadLine();

}

}

public sealed class RandomStr

{

public const string myVersion = "1.2";

/********

* Const and Function

* ********/

private static readonly int defaultLength = 8;

private static int GetNewSeed()

{

byte[] rndBytes = new byte[4];

RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

rng.GetBytes(rndBytes);

return BitConverter.ToInt32(rndBytes,0);

}

/********

* getRndCode of all char .

* ********/

private static string BuildRndCodeAll(int strLen)

{

System.Random RandomObj = new System.Random(GetNewSeed());

string buildRndCodeReturn = null;

for(int i=0; i<strLen; i++)

{

buildRndCodeReturn += (char)RandomObj.Next(33,125);

}

return buildRndCodeReturn;

}

public static string GetRndStrOfAll()

{

return BuildRndCodeAll(defaultLength);

}

public static string GetRndStrOfAll(int LenOf)

{

return BuildRndCodeAll(LenOf);

}

/********

* getRndCode of only .

* ********/

private static string sCharLow = "abcdefghijklmnopqrstuvwxyz";

private static string sCharUpp = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

private static string sNumber = "0123456789";

private static string BuildRndCodeOnly(string StrOf,int strLen)

{

System.Random RandomObj = new System.Random(GetNewSeed());

string buildRndCodeReturn = null;

for(int i=0; i<strLen; i++)

{

buildRndCodeReturn += StrOf.Substring(RandomObj.Next(0,StrOf.Length-1),1);

}

return buildRndCodeReturn;

}

public static string GetRndStrOnlyFor()

{

return BuildRndCodeOnly(sCharLow + sNumber,defaultLength);

}

public static string GetRndStrOnlyFor(int LenOf)

{

return BuildRndCodeOnly(sCharLow + sNumber,LenOf);

}

public static string GetRndStrOnlyFor(bool bUseUpper,bool bUseNumber)

{

string strTmp = sCharLow;

if (bUseUpper) strTmp += sCharUpp;

if (bUseNumber) strTmp += sNumber;

return BuildRndCodeOnly(strTmp,defaultLength);

}

public static string GetRndStrOnlyFor(int LenOf,bool bUseUpper,bool bUseNumber)

{

string strTmp = sCharLow;

if (bUseUpper) strTmp += sCharUpp;

if (bUseNumber) strTmp += sNumber;

return BuildRndCodeOnly(strTmp,LenOf);

}

}

}

相关链接:[/b]

让您的软件运转:软件策略(在缺少硬件的情况下,可以通过软件设计一个相当安全的随机数发生器)

http://www-128.ibm.com/developerworks/cn/security/randomsoft/index.html

使您的软件运行起来: 摆弄数字(真正安全的软件需要精确的随机数生成器)
http://www-128.ibm.com/developerworks/cn/security/playing/index.html

使您的软件运行起来:消除偏差(如何通过硬件真正实现随机数生成)

http://www-128.ibm.com/developerworks/cn/security/beating/index.html

话说伪随机数也来搅局之后乾坤大乱……

http://61.186.252.131/Expert/topic/2152/2152754.xml?temp=.126034
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: