Безопасен ли этот поток крипто-кода? - PullRequest
1 голос
/ 23 ноября 2010

У меня есть пул вспомогательных объектов неизменяемого шифрования, которые содержат экземпляры java Jip Cipher и MessageDigest:

AlgorithmInstance( Cipher encCipher, Cipher decCipher, MessageDigest digest ) { ... }
private BlockingQueue< AlgorithmInstance > pool = new ArrayBlockingQueue< AlgorithmInstance >(poolSize);

Различные потоки в моем приложении, требующие шифрования или дешифрования, борются за объекты AlgorithmInstance путем доступабассейн.Каждый поток использует их для шифрования или дешифрования, а затем возвращает их в пул по завершении.Потоки не синхронизируются ни с одним из объектов JCA, так как нет одновременного доступа.Расшифровка работает примерно так же.

public byte[] encryptMessage( byte data[] ) { ...
 try {
  AlgorithmInstance inst = pool.take();

  inst.digest.reset(); 
  byte[] digest = inst.digest.digest(message);

  inst.encryptCipher.init( Cipher.ENCRYPT_MODE, m_currentKey, ivParams );
  inst.encryptCipher.doFinal( messageBuffer );
 }
 finally {
  pool.put(inst)
 }
}

Это работает 99,99% времени;и 100% времени в юнит-тестах.Однако, попав в голубую луну, я получаю сообщение, чей вычисленный дайджест не получается правильным - обычно это указывает на фальсификацию сообщений или сетевые ошибки;но отправитель и получатель находятся на одном и том же компьютере (в разных процессах).

Q: Есть ли какое-то внутреннее состояние для шифра или дайджеста, который может страдать от эффектов согласованности памяти - I 'm на 2-х ядерном ящике с окнами, так что я не вижу, как я мог бы даже пострадать от эффектов согласованности памяти.Я заново инициализирую шифр и перевариваю каждый вызов, так что это не должно иметь значения.

Q: Есть ли какой-нибудь способ, которым я мог бы закончить режимом заполнения, который иногда терпит неудачу на основании сообщениядлина?Декриптор и шифратор используют абсолютно одинаковые алгоритмы (AES / CBC / Pkcs5Padding + SHA-256 и размер ключа 128).

Ответы [ 3 ]

3 голосов
/ 11 января 2011

Много ли у вашего приложения потоков? Потому что вместо пула вы можете поместить ваши AlgorithmInstances в объекты ThreadLocal, таким образом удостоверившись, что каждый AlgorithmInstance все время используется только одним и тем же потоком, поэтому проблема должна исчезнуть, и вам также не потребуется синхронизироваться с AlgorithmInstance ( так что вы получите лучшую производительность).

0 голосов
/ 29 ноября 2010

Я изменил код, чтобы синхронизировать его с AlgorithmInstance, когда я использую любой из содержащихся в нем объектов. Я не видел эту проблему с тех пор; однако не понятно почему; поскольку операции queue.put() и queue.take() должны формироваться ТОЧНО, то же самое отношение происходит до , сформированное разблокировкой монитора:

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

Единственная другая возможность, которую я могу придумать, заключается в том, что IVParamSpec изменяется во время вычисления Cipher.init (), а затем восстанавливается в конце. Поскольку предполагается, что ivParams предназначены только для чтения и используются всеми объектами в пуле, при значении true это может привести к несинхронизированному доступу и, возможно, к MCE.

0 голосов
/ 23 ноября 2010

Функция encryptMessage() сама по себе является поточно-ориентированной, поскольку не использует память, разделяемую двумя потоками. Однако вполне вероятно, что код, использующий эту функцию, не является потокобезопасным. Если вы хотите одновременно шифровать / дешифровать данные в пуле или очереди, то вполне вероятно, что «текущий рабочий индекс» не увеличивается или уменьшается потокобезопасным способом. Глобальный индекс, разделяемый между потоками, может быть создан с помощью целого глобального целого, защищенного мьютексом. Прежде чем это значение будет прочитано, а затем изменено, поток должен запросить блокировку этой переменной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...