Это мой первый вопрос на этом сайте, и у меня есть только базовые математические представления об RSA, так что, пожалуйста, терпите меня! :)
Я пишу веб-приложение на Java для своего последнего учебного года в университете. Это веб-реализация «Pret-a-voter», безопасной системы голосования, для тех, кто слышал о ней.
По сути, моя проблема в том, что я хочу дать кому-то, выполняющему роль аудитора:
- массив байтов source (открытый текст, который нужно зашифровать)
- файл открытого ключа RSA
- байтовый массив «destination», который является результатом моего собственного вычисления шифрованных данных с учетом открытого текста и открытого ключа
Затем я хочу, чтобы аудитор мог выполнить шифрование с использованием первых двух элементов и убедиться, что результатом является третий. Поэтому мне нужно, чтобы шифрование было детерминированным, т. Е. Генерировало одни и те же шифроданные каждый раз, когда шифрование с одним и тем же открытым текстом и открытым ключом повторяется.
(Примечание. В этом проекте я работаю с очень маленькими блоками данных - симметричное шифрование не используется вообще ... Я знаю, что это «интересное» использование RSA!)
В любом случае я обнаружил, что в Java, используя
cipher = Cipher.getInstance("RSA");
использует схему случайного заполнения по умолчанию по цене 11 байтов (поэтому с парой ключей 2048 бит можно зашифровать 2048 / 8-11 = 245 байтов). Повторное шифрование одного и того же открытого текста генерирует разные зашифрованные тексты, что, очевидно, не является тем режимом ECB, который мне нужен.
У меня вопрос: следует ли мне использовать следующее?
cipher = Cipher.getInstance("RSA/ECB/NoPadding");
Я читал во многих местах, что RSA небезопасен без заполнения. Это просто потому, что злоумышленник может создать словарь открытых текстов / зашифрованных текстов? Это побочный эффект детерминированного шифрования, который мне нужен, чтобы позволить аудиторам проверять мое шифрование, а в моей схеме аудиторы доверяют, так что это нормально.
Вторая часть моего вопроса больше связана с Java. Если я действительно использую RSA / ECB / NoPadding, как указано выше, я считаю, что могу предоставить исходный массив байтов (скажем) длиной 128 (для пары ключей RSA 1024 бит) и зашифровать его. чтобы получить еще один массив байтов длиной 128. Если я попытаюсь снова зашифровать этот с другим открытым ключом длиной 1024, я получу
javax.crypto.BadPaddingException: сообщение больше модуля
Кто-нибудь знает почему?
РЕДАКТИРОВАТЬ - шифрование с помощью NoPadding не всегда генерирует это исключение - оно темпераментное. Однако даже если шифрование не генерирует это исключение, дешифрование генерирует следующее:
javax.crypto.BadPaddingException: данные должны начинаться с нуля
Большое спасибо, что прочитали это! Любая помощь будет принята с благодарностью.
ИЗМЕНИТЬ - извините, мой первоначальный вопрос был не очень ясен относительно того, что я хочу сделать, поэтому вот [попытка] объяснения:
- Открытый текст - это голос избирателя на выборах.
- Pret-a-voter стремится к сквозной проверке без ущерба для конфиденциальности избирателя (и т. Д.). После голосования избирателю выдается квитанция, по которой он может проверить, правильно ли записан его голос, и которая позже покажет ему, что его голос не был подделан. Избиратель сравнивает полученную информацию с идентичной копией, размещенной в сети.
- Однако ни один избиратель не должен иметь возможности доказать, как он проголосовал (поскольку это может привести к принуждению), поэтому информация представляет собой не открытый текст, а зашифрованную копию голосования.
- Фактически, открытый текст шифруется четыре раза с четырьмя разными асимметричными ключами, которые хранятся у двух разных кассиров, у каждого из которых есть два ключа. Таким образом, голосование (открытый текст) предоставляется одному кассиру, который шифрует его с помощью открытого ключа # 1, а затем шифрует ЭТО зашифрованный текст своим вторым открытым ключом, передает ЭТО зашифрованный текст второму кассиру, который шифрует его двумя своими ключами одним и тем же способ. Полученный зашифрованный текст (результат четырех последовательных шифрований) - это то, что публикуется в сети (становится общедоступным). Счетчикам доверяют.
- Каждый зашифрованный голос можно представить себе в виде «луковицы», где в центре находится голос и имеется несколько уровней шифрования. Чтобы попасть на голосование, каждый уровень должен быть удален по очереди, то есть соответствующие закрытые ключи (хранимые кассирами) должны применяться в обратной последовательности. Это ключ к безопасности - все счетчики должны работать сообща, чтобы расшифровать голоса.
- Электронную доску объявлений можно представить в виде таблицы с 5 столбцами - первый (слева) содержит полностью зашифрованные голоса (также показанные в квитанции каждого избирателя) и является единственным видимым столбцом на этапе голосования. Второй столбец содержит тот же набор голосов, но с удаленным внешним слоем - кассир 2 заполняет этот столбец и столбец 3, расшифровывая голоса, используя свои закрытые ключи на этапе подсчета голосов. В конце этапа подсчета столбец 5 содержит полностью расшифрованные голоса, которые затем могут быть подсчитаны.
- Каждый избиратель получает квитанцию, которая связывает его с зашифрованным голосом в столбце 1. Это не показывает, как они проголосовали, но позволяет им убедиться, что их голос не был подделан, поскольку на протяжении всего процесса выборов они могут проверять, что их зашифрованный голос все еще находится в столбце 1, нетронутым. Это, конечно, только половина «сквозной проверки», поскольку избиратели не могут проверить, что дешифрование было выполнено правильно, т.е. что в столбце 2 есть запись, которая представляет собой их голос за вычетом внешнего уровня шифрования. . Каждый избиратель несет ответственность только за проверку ДО пункта в графе 1.
- После этого аудиторы обязаны проверить, что записи в столбце 1 расшифровываются до столбца 2 и так далее. Они делают это, полагаясь на детерминированное шифрование, а открытые ключи, используемые для шифрования, являются общедоступными.
- Поскольку открытые ключи являются общедоступными, вы не хотите, чтобы люди просто рисовали линии из столбца 5 в столбец 1, присоединяя чей-то голос, поскольку он многократно зашифровывается - таким образом квитанция, которая привязывает вас к зашифрованному голосованию, фактически связывает вас с незашифрованное, читаемое голосование -> принуждение! Таким образом, только столбцы 1, 3 и 5 являются общедоступными (поэтому каждый кассир выполняет ДВА шифрования), и для каждой записи в столбце 3 аудиторам раскрывается только ОДНА из соответствующих записей в {2,4}. Это не позволяет никому (даже аудиторам) связать зашифрованный голос с незашифрованным.
- Поэтому аудиторам необходимо взять запись в столбце 3, получить соответствующую запись в столбце 2 и открытый ключ и выполнить такое же шифрование, чтобы убедиться, что они действительно получили запись в столбце 2.
- В совокупности это обеспечивает сквозную проверяемость.
Извините, это было так долго - я надеюсь, что это описывает мою потребность в детерминированном шифровании. Я упустил много фундаментальных деталей (я сильно изменил эту схему), но, надеюсь, все основные принципы присутствуют. Большое спасибо за чтение - я очень ценю это.