2016-05-15 193 views
1

如何使用SecureRandom生成密鑰。 getInstanceStrong()如何使用SecureRandom.getInstanceStrong()生成密鑰?

使用此代碼,我可以接收具有隨機值的字節數組。有沒有簡單的方法來生成給定長度的密鑰(例如,位),類型(int,字符串)和格式(十六進制,bin,dec)?

package com.company; 

import java.security.NoSuchAlgorithmException; 
import java.security.SecureRandom; 

public class KeyGen { 

    public void generate() throws NoSuchAlgorithmException { 

     SecureRandom random = SecureRandom.getInstanceStrong(); 
     byte[] values = new byte[32]; // 256 bit 
     random.nextBytes(values); 

     StringBuilder sb = new StringBuilder(); 
     for (byte b : values) { 
      sb.append(String.format("%02x", b)); 
     } 
     System.out.print("Key: "); 
     System.out.println(sb.toString()); 
    } 
} 

輸出:

Key: 8fcea84897f48f575c22441ece4e7ddb43ac08cd2c1a83fca46c080768468059

+0

你真的應該命名你的軟件包'com.pany'當然:) –

+0

@MaartenBodewes只是IntelliJ IDEA中的默認模板。 –

+0

啊,好吧,默認情況下使用Eclipse,不知道。對於你自己的密碼,你的當前代碼似乎沒有太大的錯誤。不過你可能會考慮關鍵管理。也許將隨機密鑰放在某種容器中將是一個好主意,或者使用老師的公共PGP密鑰(例如使用Bouncy Castle功能)對其進行加密。 –

回答

0

鍵應該是一個特定的類型,例如AES。它們應該最好保存在一個SecretKey實例或類似的Key派生類中。

現代對稱密碼鍵由比特組成。通常你不需要他們的人/字符串表示(這實際上可能會損害安全性)。將它們存儲在KeyStore中,或者從密碼中派生出來。如果您確實對它們進行了編碼,則只要您在轉換過程中不丟失數據,表示格式就無關緊要。

這可能是產生一個強大的AES密鑰的最佳途徑:

public class GenerateStrongAESKey { 

    public static SecretKey generateStrongAESKey(final int keysize) { 
     final KeyGenerator kgen; 
     try { 
      kgen = KeyGenerator.getInstance("AES"); 
     } catch (final NoSuchAlgorithmException e) { 
      throw new RuntimeException("AES key generator should always be available in a Java runtime", e); 
     } 
     final SecureRandom rng; 
     try { 
      rng = SecureRandom.getInstanceStrong(); 
     } catch (final NoSuchAlgorithmException e) { 
      throw new RuntimeException("No strong secure random available to generate strong AES key", e); 
     } 
     // already throws IllegalParameterException for wrong key sizes 
     kgen.init(keysize, rng); 

     return kgen.generateKey(); 
    } 

    public static void main(String[] args) { 
     SecretKey strongAESKey = generateStrongAESKey(256); 
     // well, if you must have a human readable string, here it is 
     // but you've been warned 
     System.out.println(toHex(strongAESKey.getEncoded())); 
    } 

    private static String toHex(final byte[] data) { 
     final StringBuilder sb = new StringBuilder(data.length * 2); 
     for (byte b : data) { 
      sb.append(String.format("%02X", b)); 
     } 
     return sb.toString(); 
    } 
} 

注:這需要鑰匙> 128位的Oracle運行時環境中的無限強度管轄的文件。

+0

我需要'人類可讀的字符串'爲我的GOST /岩漿塊密碼實現。就我而言,我需要向老師展示加密密鑰。或以某種方式拯救他。 –

+0

但是我不完全理解你的代碼和我的代碼之間的根本區別,如果我們得到相同的結果。 –

+0

區別在於你的代碼只使用一個字節數組,而我的使用JCE。輸出值可能是相同的(或者至少是相同種類的隨機),但是上述代碼可以例如保護密鑰或在可用時使用硬件設備。當然,如果你想爲自制密碼生成密鑰,這不是很有用。在這種情況下,你的代碼沒有什麼問題。如上所述,幸運的是,Java不會輸出十六進制或其他人類可讀的字符串作爲(不安全)默認值。 –