2016-09-30 55 views
2

我們正在將一些加密技術加入到我們的URL生成器中,並且在測試過程中我注意到以下步驟會使程序在相當一段時間內掛起。密碼加密明顯緩慢

cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV.getBytes("UTF-8"))); 

這裏是在其中它被調用時,一旦它到達該行它將簡單地掛起,並可以採取超過2分鐘,最後傳遞函數的一部分。想知道是否有人知道原因或解決方案。

public static String encrypt(String toEncrypt) throws Exception 
    { 

     SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES"); 

     Security.addProvider(new BouncyCastleProvider()); 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); 

     cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV.getBytes("UTF-8"))); 

     byte[] encrypted = cipher.doFinal(toEncrypt.getBytes()); 
     byte[] encryptedValue = Base64.encodeBase64(encrypted); 

     return new String(encryptedValue); 
    } 

感謝,

+1

你加密的數據有多大? –

+0

@ArtjomB。只有像60個字符的字符串。此外,這是實際加密之前,因爲我們只是設置它。 – Psychosupreme

+0

你怎麼知道它在這條線上阻塞?你在調試嗎?如果是這樣,這可能是罪魁禍首(是的,調試本身)。你是否嘗試在沒有調試器的情況下運行它? – Antoniossss

回答

3
​​

所以對於要加密的每個字符串,創建一個新的安全提供者。你會爲每個Web請求啓動一個新的Web服務器嗎?當你想編輯一個文件時,你會購買一臺新電腦嗎?

我並沒有聲稱這條線是罪魁禍首,但是每次做所有的初始化都是不對的。

拖放靜態(*),使用單例,理想情況下來自Guice或類似的,初始化一次。您的加密應該看起來像

根據@apangin和@IlmariKaronen的評論修復。

static { 
    // This really should be done just once. 
    // Moreover, you most probably don't need it. 
    Security.addProvider(new BouncyCastleProvider()); 
} 

Encryptor() { 
    SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES"); 
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); 
    cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IVBytes)); 
} 

public synchronized String encrypt(String toEncrypt) throws Exception { 
    byte[] encrypted = cipher.doFinal(toEncrypt.getBytes("UTF-8")); 
    byte[] encryptedValue = Base64.encodeBase64(encrypted); 
    return new String(encryptedValue); 
} 

由於加密本身是非常快的,你正在使用​​應該工作以及加密只是短暫的字符串。或者,也可以選擇線程本地cipher或類似的。

請注意,重複使用IV會使其不安全。但這是另一回事。

(*)這與表現無關,但是一件好事。

+1

你說每次做初始化都是不對的,但同時你在每次加密操作時調用'cipher.init'!密碼初始化可能比加密本身長10倍,請參見[相關問題](http:// stackoverflow。COM /問題/ 35778606/JAVA-GET-RID-的-密初始化開銷/)。 – apangin

+0

@apangin我知道,但它仍然比初始化所有內容要快得多,*可能足夠快*。並沒有合適的「重置」方法,因此除了使用不安全的ECB外,沒有簡單的解決方案。 – maaartinus

+1

['doFinal'](http://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html#doFinal-byte:A-)**確實將**密碼重置爲狀態在'init'調用之後。 – apangin