Расшифровка «длинного» сообщения, зашифрованное RSA Java
-
27-09-2019 - |
Вопрос
Привет, это тот же вопрос, что было задано два года назад:Java / JCE: расшифровка «длинного» сообщения, зашифрованное RSA
У меня был большой байтовый массив и RSA keypair, инициированный значением 1024. Использование шифрования RSA и указанный размер ключа является сильным требованием, я не могу его изменить. Поэтому я не могу использовать симметричное шифрование с симметричным ключом асимметричного шифрования. Я не могу использовать какие-либо другие ключи. У меня был байтовый массив и нуждается в зашифрованном байтовом массиве, который будет возвращен. Интересно, есть ли какой-нибудь готовый инструмент, который может управлять с этой проблемой?
Извините за такой любимый вопрос, но мне действительно нужна помощь.
Решение
Как указано, ваш вопрос имеет один ответ, и это «нет». Encryption RSA является алгоритмом, который шифрует сообщения до данного размера, который зависит от размера ключа; с 1024-битным ключом RSA и RSA как стандарт Описывает его максимальный размер 117 байт, не более. Нет никакого способа зашифровать более широкое сообщение с RSA, и это определенно, математическая уверенность.
Если вам действительно нужно обработать более длинные сообщения, то вы обязательно должны добавить что-то еще. В этом случае, пожалуйста, пожалуйста, Не пытайтесь сделать что-нибудь признам к своему собственным разрабатывающим с каким-то ОН-Умным расщеплением данных в небольшие блоки и тому подобное. Этот путь приводит к гибели. Вы можете произвести что-то, что появляется Чтобы составить и пробежать, но каким-то образом будет неизменно слабым, вроде почти все другие домашние вариации на криптографию. Это потому, что безопасность не может быть проверена: это не случай «работает» или «не работает».
Хорошо тростный путь асимметричного шифрования идет таким образом:
- Вы выбираете случайную последовательность байтов некоторой подходящей длины, например, 128 битов (это 16 байтов). Давайте назовем это K..
- Вы шифруете K. с открытым ключом RSA; Это урожайность Свидетельствовать.
- Вы шифруете сообщение с K. используя симметричный алгоритм шифрования (
"AES/CBC/PKCS5Padding"
). Поскольку это ключ с одним выстрелом, вы можете использовать All-Zeros IV. Это дает кучу байтов, давайте назовем это F.. - Зашифрованное сообщение - тогда конкатенация Свидетельствовать и F..
Расшифровка выходит в обратном порядке: закрытый ключ RSA используется для восстановления K. от Свидетельствовать, потом K. используется для расшифровки F. в исходное сообщение. Ключ K. никогда не хранится нигде, а Новый ключ К. генерируется каждый раз (даже если вы зашифруете одно и то же сообщение дважды). Это важно, не меняйте, если вы не понимаете, что вы делаете (и если вы сделаете, то вы уже знаете это).
Учитывая то, что вы говорите о вашей проблеме, вы имеют сделать что-то еще, чем «просто RSA». Процедура, которую я опишу выше, это о лучшем «что-то другом», что вы могли бы придумать, Безопасность.
Сборка некоторых криптографических элементов в такой протокол - это процесс, чревающий подводными камнями, поэтому вам может возникнуть удача с использованием уже определенного формата и библиотеки поддержки. Две общие форматы для асимметричного шифрования CMS. и OpenPGP.. Отказ Библиотека, которая поддерживает как и имеет хорошую репутацию, Надувной замок.
Другие советы
Если вам нужно зашифровать / расшифровать длинные строки с использованием RSA, то вы можете нарушить байты в меньших «кусках» и обрабатывать каждый кусок байтов через шифр по одному во время хранения результатов в байтбуфере.
Шифрование:
byte[] encData = null;
try {
// create public key
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(key);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pk = kf.generatePublic(publicKeySpec);
Cipher pkCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
pkCipher.init(Cipher.ENCRYPT_MODE, pk);
int chunkSize = 117; // 1024 / 8 - 11(padding) = 117
int encSize = (int) (Math.ceil(data.length/117.0)*128);
int idx = 0;
ByteBuffer buf = ByteBuffer.allocate(encSize);
while (idx < data.length) {
int len = Math.min(data.length-idx, chunkSize);
byte[] encChunk = pkCipher.doFinal(data, idx, len);
buf.put(encChunk);
idx += len;
}
// fully encrypted data
encData = buf.array();
} catch (Exception e) {
e.printStackTrace();
Дешифрование
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsaCipher.init(Cipher.DECRYPT_MODE, rsaPk);
int chunkSize = 128;
int idx = 0;
ByteBuffer buf = ByteBuffer.allocate(data.length);
while(idx < data.length) {
int len = Math.min(data.length-idx, chunkSize);
byte[] chunk = rsaCipher.doFinal(data, idx, len);
buf.put(chunk);
idx += len;
}
// fully decrypted data
byte[] decryptedData = buf.array();