2

在我的基於Java的web應用程序中,我想先加密一些數據,然後再將數據寫入數據庫並將其解密後再加載回內存。要做到這一點我用bouncycastle API並創建了一個類,看起來像這樣:Java加密器的密鑰處理

public class BlowfishEnrypter implements IEncrypter { 

    /*--- Members ---*/ 

    private BufferedBlockCipher cipher; 
    private KeyParameter key; 

    /*--- Constructors ---*/ 

    /** 
    * Initialize the cryptographic engine. The key array should be at least 8 
    * bytes long. 
    * 
    * @param key 
    */ 
    public BlowfishEnrypter(byte[] key) { 
    cipher = new BufferedBlockCipher(new CBCBlockCipher(new BlowfishEngine())); 
    this.key = new KeyParameter(key); 
    } 

    /** 
    * Initialize the cryptographic engine. The key array should be at least 8 
    * bytes long. 
    * 
    * @param key 
    */ 
    public BlowfishEnrypter(String key) { 
    this(key.getBytes()); 
    } 

    /*--- Public ---*/ 

    /** 
    * {@inheritDoc} 
    */ 
    public String encrypt(String input) throws EncryptionException { 
    if (StringUtils.hasText(input)) { 
     byte[] bytes = Hex.decode(input); 
     try { 
     return new String(encrypt(bytes)); 
     } catch (CryptoException e) { 
     throw new EncryptionException("Error occured while trying to encrypt", e); 
     } 
    } else { 
     throw new EncryptionException("Illegal argument for encryption: " + input); 
    } 
    } 

    /** 
    * {@inheritDoc} 
    */ 
    public String decrypt(String input) throws EncryptionException { 
    if (StringUtils.hasText(input)) { 
     byte[] bytes = Hex.decode(input); 
     try { 
     return new String(decrypt(bytes)); 
     } catch (CryptoException e) { 
     throw new EncryptionException("Error occured while trying to decrypt", e); 
     } 
    } else { 
     throw new EncryptionException("Illegal argument for decryption: " + input); 
    } 
    } 

    /*--- Private ---*/ 

    /** 
    * Encrypt arbitrary byte array, returning the encrypted data in a different 
    * byte array. 
    * 
    * @param data 
    * @return Encrypted byte array 
    * @throws CryptoException 
    */ 
    private synchronized byte[] encrypt(byte[] data) throws CryptoException { 
    if (data == null || data.length == 0) { 
     return new byte[0]; 
    } 

    cipher.init(true, key); 
    return callCipher(data); 
    } 

    /** 
    * Decrypts arbitrary data 
    * 
    * @param data 
    *   To decrypts 
    * @return Decrypted byte array 
    * @throws CryptoException 
    */ 
    private synchronized byte[] decrypt(byte[] data) throws CryptoException { 
    if (data == null || data.length == 0) { 
     return new byte[0]; 
    } 

    cipher.init(false, key); 
    return callCipher(data); 
    } 

    /** 
    * Private routine that does the gritty work. 
    * 
    * @param data 
    *   Data to operate on 
    * @return Processed byte array 
    * @throws CryptoException 
    */ 
    private byte[] callCipher(byte[] data) throws CryptoException { 
    int size = cipher.getOutputSize(data.length); 
    byte[] result = new byte[size]; 
    int olen = cipher.processBytes(data, 0, data.length, result, 0); 
    olen += cipher.doFinal(result, olen); 

    if (olen < size) { 
     byte[] tmp = new byte[olen]; 
     System.arraycopy(result, 0, tmp, 0, olen); 
     result = tmp; 
    } 

    return result; 
    } 
} 

到目前爲止好(我是這麼認爲的,如果你有這個類的任何意見,請繼續)。要初始化這個類,我應該提供一個密鑰。我的問題是 - 我應該如何管理這個密鑰?

更具體:

  • 我應該創建它使用特定的技術?
  • 我應該在哪裏存放它?在屬性文件中?在數據庫中?在我的代碼中的某處?
  • 該密鑰(我們在這裏談論的是一個字符串,對不對?)被加密,然後在加載或使用時解密?如果是這樣,我應該怎麼做?
+0

加密和解密是很容易的部分。保護關鍵是最難的部分。 –

回答

1

取決於很多事情:

  1. 存儲在不能被視爲/被別人訪問的安全位置代碼?如果是這樣,我只是把它放在代碼中。
  2. 您是否設想不時更換鑰匙(這種方式更安全)?如果是這樣,點1仍然是真的,然後將其粘貼在屬性文件中。
  3. 否則把它放在數據庫中,並保持數據庫的用戶名/密碼的祕密!

不知道你爲什麼要加密實際的密鑰,但是你會把密鑰放在哪裏以保護原來的密鑰?

要做的更好的事情是看看Java SE security,看看Java密鑰存儲庫可以爲您做些什麼。此外,您還可以閱讀bouncy castle's網站上的資源,這可能會有所幫助。

+0

謝謝。我的代碼是安全的。我認爲生病只是把我的鑰匙放在財產檔案中。關於加密實際的密鑰 - 你是對的,一個壞主意:)關於Java密鑰庫,實際上我使用bouncycastle來避免java密鑰庫,因爲它遠不是一個簡單的API(據我所知)。 – forhas

+0

加密密鑰是常見的做法。所有的HSM盒都可以做到。 –

1

我們對許多網絡應用都使用了類似的加密技術。通常這些密鑰在源代碼中作爲字符串保存在屬性文件中。密鑰沒有加密,它是一個帶有特殊字符和其他字符串組合的字符串,只是爲了使它變得強大(數字,大寫等)。一旦生活密鑰通常會在6個月內由商業用戶改變一次。

+0

你的鑰匙不應該由字符組成。如果要將其存儲在字符串/文本文件中,則應該生成一個隨機密鑰,並使用十六進制或base64對其進行編碼。 –