2017-08-27 117 views
0

我們知道,我們在我們的代碼生成「隨機」的數字真的是僞隨機的隨機密鑰。在Java的情況下,它們默認使用時間戳作爲隨機種子,並且在此之後生成的每個隨機數都是從該點向前確定性創建的。創建使用音頻信號

如果使用隨機數生成密碼和惡意方知道你生成的內容一天,密碼,他們就只有通過這一天每毫秒進行迭代。那將是1000 * 60 * 60 * 24 = 86.4百萬。對於一個複雜的派對來說,這不是一個大數目的猜測。着名的愛德華斯諾登警告說,「假設你的對手每秒能猜出一萬億次。」

的問題是,我們如何產生真正的隨機數?我想從我的筆記本電腦的麥克風中採樣16位音頻,並使用兩個採樣中最不重要的8位來形成種子。這裏的想法是音頻信號的最不重要的部分是噪聲被攜帶的地方。例如,這裏有從記錄在一個相對安靜的地方一個16位採樣幾兩字節值:

0,19 
0,38 
0,-49 
1,93 
1,-29 
1,-80 

你可以看到,最顯著字節爲0或1,這意味着正在記錄的波幾乎沒有註冊。另一方面,最不重要的字節值在整個地方跳躍。這是隨機種子的肥沃土壤!

這個職位存在的具體問題:我們如何能生產使用producedby我們身邊的真實世界的噪音帶來的干擾信號中的隨機32個字符的密碼。

+0

自我回答問題,應該採取特定_question_的形式,而不是開放式的項目。 – duskwuff

+0

或者乾脆使用'的Math.random()'或者,如果你想 「保護」' 「」 +的Math.random()+的Math.random()+的Math.random()':d –

回答

-1

這是一個陽光明媚的下午的項目!這是一個帶有靜態方法的工具類,可以產生一個隨機整數或任意長度的隨機字符串。

Gist link.

import javax.sound.sampled.*; 

public class RandomFromAudio { 

    public static final String ALLOWED_CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 

    // Demonstrating the methods 
    public static void main(String[] args) { 
     System.out.println(getRandomKey(32)); 
    } 

    public static String getRandomKey(int keyLength) { 
     int [] randomInts = getRandomIntArray(keyLength); 
     StringBuilder stringBuilder = new StringBuilder(); 
     for (int randomInt: randomInts) { 
      char randomChar = ALLOWED_CHARACTERS.charAt(randomInt % ALLOWED_CHARACTERS.length()); 
      stringBuilder.append(randomChar); 
     } 
     return stringBuilder.toString(); 
    } 

    public static int [] getRandomIntArray(int desiredLength) { 
     int [] out = null; 
     AudioFormat format = new AudioFormat(8000.0f, 16, 1, true, true); 
     TargetDataLine microphone; 
     try { 
      out = new int[desiredLength]; 
      byte[] data = new byte[2]; 

      DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); 
      microphone = (TargetDataLine) AudioSystem.getLine(info); 
      microphone.open(format); 
      microphone.start(); 

      // my microphone seems to need to "warm up". 
      // It gets a lot of low signal at the beginning producing a lot of low numbers. 
      // This loop reads signal until it shows that a decently high value can be reached. 
      while (data[1] < 100) { 
       microphone.read(data, 0, data.length); 
      } 
      byte [] leastSig = new byte[2]; 
      for (int i = 0; i < desiredLength * 2; i++) { 
       microphone.read(data, 0, data.length); 
       // saving the least significant byte 
       leastSig[i % 2] = data[1]; 
       if (i % 2 == 1) { 
        // combining the bytes into an int 
        out[(i + 1)/2 - 1] = leastSig[0]<<8 &0xFF00 | leastSig[1]&0xFF; 
       } 
      } 
      microphone.close(); 
     } catch (LineUnavailableException e) { 
      e.printStackTrace(); 
     } 
     return out; 
    } 
} 

運行產生了一些次(對我來說):

hqctXiTiV67iI2JAXrcU0vzGhxEBDN2R 
ViCSGxahmI51mXfBIV7INo9vu3ZuKNDi 
9oTl1Meer59Y69yxNRTa0Dv3pWNywZFY 
zfLrh9ZU8oNLg43M1D1ZzcoSxJ4X1HOQ 
dlhliKxM4tAhr8uoCOtdRsmwARIE6Gjb