2016-09-30 57 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