Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 这个密码是线程安全的吗?_Java_Encryption_Thread Safety - Fatal编程技术网

Java 这个密码是线程安全的吗?

Java 这个密码是线程安全的吗?,java,encryption,thread-safety,Java,Encryption,Thread Safety,我有一个不可变的encryption helper对象池,其中包含java JCA Cipher和MessageDigest对象的实例: AlgorithmInstance( Cipher encCipher, Cipher decCipher, MessageDigest digest ) { ... } private BlockingQueue< AlgorithmInstance > pool = new ArrayBlockingQueue< AlgorithmIns

我有一个不可变的encryption helper对象池,其中包含java JCA Cipher和MessageDigest对象的实例:

AlgorithmInstance( Cipher encCipher, Cipher decCipher, MessageDigest digest ) { ... }
private BlockingQueue< AlgorithmInstance > pool = new ArrayBlockingQueue< AlgorithmInstance >(poolSize);
这在99.99%的时间内有效;100%的时间都在单元测试中。然而,偶尔,我会收到一条消息,它的计算摘要显示不正确——通常这表示消息被篡改或网络错误;但是发送方和接收方在同一台机器上(在不同的进程中)

Q:密码或摘要是否存在可能受到内存一致性影响的内部状态——我使用的是双核windows机箱,因此我甚至不知道如何受到内存一致性影响。我重新初始化密码,并对每个调用进行摘要处理,因此这不重要


Q:有没有任何方法可以让我最终使用填充模式,根据消息长度,这种填充模式有时会失败?解密程序和加密程序使用完全相同的算法(AES/CBC/Pkcs5Padding+SHA-256,密钥大小为128)。

函数本身是线程安全的,因为它不使用两个线程共享的内存。但是,使用此函数的代码可能不是线程安全的。如果您想同时加密/解密池或que中的数据,那么“当前工作索引”可能不会以线程安全的方式递增或递减。线程之间共享的全局索引可以通过使用互斥锁保护全局整数来创建。在读取并更改此值之前,线程必须请求锁定此变量

我更改了代码,以便在使用AlgorithmInstance中包含的任何对象时在AlgorithmInstance上同步。从那以后,我再也没有看到过这个问题;但原因不明;由于
queue.put()
queue.take()
操作应形成与监视器解锁形成的关系之前完全相同的形式:

synchronized (inst) {
 ...
 // do crypto opperations
}

我唯一能想到的另一种可能性是在Cipher.init()计算过程中修改IVParamSpec,然后在最后恢复。由于ivParams假定为只读,并在池中的所有对象之间共享,如果为true,则可能会导致不同步访问,并可能导致MCE。

您的应用程序是否有大量线程?因为不需要池,您可以将AlgorithmInstance放在ThreadLocal对象中,从而确保每个AlgorithmInstance始终仅由同一线程使用,因此问题应该消失,您也不需要在AlgorithmInstance上进行同步(这样您将获得更好的性能).

从我最初的帖子中看不清楚,但池是一个ArrayBlockingQueue。你是说游泳池是个问题吗?任何BlockingQue都应该是线程安全的:从javadoc
内存一致性效果来看:与其他并发集合一样,在将对象放入BlockingQueue之前,线程中的操作发生在另一个线程的BlockingQueue中访问或移除该元素之后的操作之前@Justin Crypto不是魔法,它只是对字符串的一些二进制操作。这个问题就像问is
.substring()
线程安全吗?那么你是说池是问题所在吗?顺便说一句,大多数密码分配了大量的内部表,因此有可能出现MCE。@Justin我以前没有使用过这个池,所以我不确定。您的尝试可能会抑制一个真正的异常。有一个全面捕获的错误做法,代码可能是例外,然后尝试
pool.put(inst)
,即使代码失败。没有全面捕获,它是try/finally。回答1:我看不出来。回答2:没有。我觉得这是GC类的一些副作用或密码/摘要中的一些共享缓冲区;或者正如@Rook所说,我用错了。它又发生了,而且这些摘要完全不同,而不仅仅是几点不同。绝对不知道。你有什么理由把它们放在一起吗?它真的会给性能带来好处吗?我猜创建cyper对象不会那么昂贵。我也从JDK 1.6_21->1.6_22Hi Justin开始!你深入研究了吗?我将要编写与您的原始版本几乎相同的代码,并希望避免任何陷阱。据我所知,你第一次发布的代码应该可以正常工作。即使
ivParams
是可变的,在
inst
上同步也不会有任何区别,对吧?我无法区分JVM升级和同步块。两者都做了之后,就没有问题了。遗憾的是,我找不到根本原因。
synchronized (inst) {
 ...
 // do crypto opperations
}