有關隨機數的一些討論

有關隨機數的一些討論

Hogwarts

關於生成隨機數,有以下幾個可以選擇的方案:

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 IDThread ID以及大量系統信息。當然,CryptGenRandom()RNGCryptoServiceProvider在提供更好的隨機數的同時,不可避免的是速度方面的性能要遜於System.Random

bugfree(八個飛飛)

所謂的僞隨機,是指每次產生的序列一樣。比如你用一個種子,產生的序列是1 9 7 5,再用這個種子產生,還是1 9 7 5,但是1 9 7 5本身是隨機的。還有DateTime.Ticks 此屬性的值爲自 0001 1 1 日午夜 12:00 以來所經過時間以 100 毫微秒爲間隔表示時的數字。可以自己寫隨機數函數,比如比較著名的隨機數生成方法是”高斯隨機數“。

 

happycock(SSWW)

所謂的隨機數就是一堆加在一起滿足某種統計規律的數,而自身是毫無規律的。應該說這是從現實中抽取出來的一個概念,而在計算機中要想模擬是比較困難的。僞隨機是指雖然他滿足某種統計規律,但是對於一個特定的“種子”,他的序列是一定的,也就是說對於1做種子,產生的序列永遠都是xxxx,因此他不滿足“隨機”特點,所以是“僞”的。

 

ckc()

我覺得happycock剛好說反了,真正的隨機數是不應該有統計規律的,而實際的隨機算法因爲算法的限制,是有統計規律的,當然,這個統計規律可能比較複雜,但是,只要有統計規律,就意味着我們可以找到一個方法預測隨機數序列的下一個值,或者說可以以較大的概率猜測下一個值。

內存中的數據如果沒有初始化,它的值是不變的,這個值我們不知道,但是你執行1萬次,它也許有9999次都是0,這個我們沒辦法叫它是隨機數,或者說這個地方的隨機數和我們需要的嚴格意義的隨機數概念不同。這個地方我們叫它隨機數只是強調我們不知道它的值。

 

happycock(SSWW)

大量的隨機過程是符合統計規律的,這是沒有疑問的。這正是“事物都是有規律的”的一個證明,“無規律”只是沒有找到規律。所以無規律的隨機是不存在的。尋找無規律的隨機是徒勞的。還有,rand()是符合平均分佈的隨機,不是正態分佈。

關於內存中數據的初始化,不知你懂不懂什麼叫“時序電路”,可以類比一下,那個數跟很多因素有關,剛上電的時候跟器件的電氣屬性有關,所以當你重複試驗的時候,就能得出是符合規律的。在程序運行中,是上個使用這塊內存的變量的值。這也是有規律的。

 

pengzhenwanli(紫氣日盈)

真正的隨機數應用,其實嚴格來說是要求有一定規律的,對於可控的隨機數,計算機確實沒法產生,但是不可控的隨機數,要它來沒什麼意義。

#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)

關於隨機數的討論及研究有兩點:

1。是否真正隨機

2。是否足夠安全

真正的隨機是很難得到的,代價也很高,而是否有足夠的安全(相對)往往是追求的目標

要得到一個隨機的數,理論上就只有依靠硬件,intel P3以上的cpu應該都有一個

叫什麼來着?你可以察看一下相關資料,好像是根據熱能(量)來確定的。當然,在不要求安全的前提下,可以用僞隨機函數rand(),及time()設定隨機種子。這樣就足夠了。

 

haowh(一個人走在黑黑的夜)

在加密解密的過程中隨機數起着相當重要的作用。所以隨機數的質量受到關注。如何高效產生高質量的隨機數是一個重要課題。

ASCII碼組成的隨機數爲例,隨機數最基本的檢驗:我們知道有256ASCII碼其數值是0255,當一組隨機數個數較多時其平均值應爲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)

這樣的這樣的序列並不是一個好的序列。

通常可複用的序列都不是一個真隨機的序列。通常一個好的隨機的序列有一些衡量的標準。

比如:01大致相等,遊程平均分佈。熵值近似爲0

通常產生一個足夠長的的僞隨機序列的方法是使用用非線性移位器。

 

SweetJerry()

好的隨機數生成需要用到如:()數乘法,對稱加密(解密)算法,哈希算法,反饋控制,置換等.

隨機性有一些簡單的測試方法.

 

BruceZhang()

我是學統計的,在統計學上認爲用計算機計算出來的都是僞隨機數,如果用Round()可以用時間當種子,如果對隨機數要求不高的話,直接就可以用時間做隨機數,方法如下:

1、取出時間,取到百分秒

2、將取出的時間值做運算(+ - * /),具體算法自定,但保證結果爲正值

3、求模(取餘),是要求出一個適合你要求範圍的值

4、重複23即可得到更多的隨機數

 

其它:

隨機數就是不能通過已經得到的數列來推出將要得到的數列。實際應用中還沒有軟件可以生成真正的隨機數。目前的很多的密碼應用都有與之相應的(相配套的)硬件,用硬件來產生隨機數。真正的隨機數可以取機器的物理噪聲方法來做,那種絕對是真正的隨機數。

我又想到一個辦法,現在的CPU大多支持rdtsc指令,通過這個讀取CPU時間戳,不知隨機性如何。

有一個數學命題,一付撲克洗成絕對均勻的時候,就是原來的次序,而且被證明成立了。

C#如何獲取隨機數

下面是我做的一個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));  //510之間生成一個僞隨機數

             

              Console.WriteLine(rand.Next(10));    //生成010之間的僞隨機數

             

              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);

         }

     }

 

}

 

相關鏈接:

讓您的軟件運轉:軟件策略(在缺少硬件的情況下,可以通過軟件設計一個相當安全的隨機數發生器)

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

 

Feedback

# re: 蛙蛙推薦:有關隨機數的一些討論  回覆   

2006-04-18 11:25 by yes_ok
不知道大家有沒有隨機數驗證的程序可以提供呢?本人做了一個硬件的隨機數發生器,迫切需要一個驗證程序來看一下產生隨即數的隨即性。

# re: 蛙蛙推薦:有關隨機數的一些討論  回覆   

2006-05-20 23:28 by frezingsun
請問各位大俠,由Matlab生成的gamma分佈的隨機數可以不叫僞隨機數而是比較隨機的隨機數了嗎?因爲,Matlab生成隨機數,每次得到的序列可能不一樣。比如語句gamrnd(0.375,1.674,227,1),生成了一列共227個隨機數,應該是服從參數爲0.375,1.674的gamma分佈的227個隨機數了吧?
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章