Расшифровка «длинного» сообщения, зашифрованного с помощью RSA Java - PullRequest
4 голосов
/ 16 апреля 2010

Привет, это тот же вопрос, который был задан два года назад: Java / JCE: расшифровка «длинного» сообщения, зашифрованного с помощью RSA

У меня был большой байтовый массив и пара ключей rsa, инициированные значением 1024. Использование шифрования rsa и указанного размера ключа является строгим требованием, я не могу его изменить. Поэтому я не могу использовать симметричное шифрование с симметричным ключом асимметричного шифрования. Я не могу использовать другие ключи. У меня был байтовый массив, и мне нужно возвращать зашифрованный байтовый массив. Интересно, есть ли готовый инструмент, который может справиться с этой проблемой?

Извините за такой дилетантский вопрос, но мне действительно нужна помощь.

Ответы [ 2 ]

12 голосов
/ 16 апреля 2010

Как уже говорилось, на ваш вопрос есть один ответ, и это "нет". RSA-шифрование - это алгоритм, который шифрует сообщения до заданного размера, который зависит от размера ключа; с 1024-битным ключом RSA и RSA как стандарт описывает это , максимальный размер составляет 117 байт, не более. Невозможно зашифровать сообщение большего размера только с помощью RSA, и это определенная математическая уверенность.

Если вам действительно нужно обрабатывать более длинные сообщения, то обязательно необходимо добавить что-то еще. В этом случае, пожалуйста, , пожалуйста, , не пытайтесь делать что-то свое, придуманное, с каким-то очень умным разбиением данных на маленькие блоки и тому подобное. Этот путь ведет к гибели. Вы можете создать что-то, что выглядит как для компиляции и запуска, но что-то неизменно будет слабым, как почти любая другая самодельная вариация в криптографии. Это потому, что безопасность не может быть проверена: это не случай «работает» или «не работает».

Проложенный путь асимметричного шифрования идет так:

  1. Вы выбираете случайную последовательность байтов некоторой подходящей длины, например, 128 бит (это 16 байтов). Давайте назовем это K .
  2. Вы шифруете K открытым ключом RSA; это дает E .
  3. Вы шифруете сообщение с помощью K , используя алгоритм симметричного шифрования ("AES/CBC/PKCS5Padding"). Так как это однократный ключ, вы можете использовать все нули IV. Это дает кучу байтов, давайте назовем это F .
  4. Зашифрованное сообщение является тогда объединением E и F .

Расшифровка происходит в обратном порядке: закрытый ключ RSA используется для восстановления K из E , затем K используется для расшифровки F в исходное сообщение. Ключ K никогда нигде не сохраняется, и каждый раз генерируется новый ключ K (даже если вы шифруете одно и то же сообщение дважды). Это важно, не меняйте это, пока не поймете, что делаете (а если и поймете, то уже знаете).

Учитывая то, что вы заявляете о своей проблеме, у вас есть , чтобы сделать что-то еще, кроме "просто RSA". Процедура, которую я описал выше, касается лучшего "чего-то еще", которое вы могли бы придумать, с точки зрения безопасности.

Сборка некоторых криптографических элементов в такой протокол является процессом, чреватым подводными камнями, поэтому вам может повезти с использованием уже определенного формата и библиотеки поддержки. Два распространенных формата для асимметричного шифрования: CMS и OpenPGP . Библиотека, которая поддерживает оба и имеет хорошую репутацию: Bouncy Castle .

1 голос
/ 18 мая 2014

Если вам нужно зашифровать / расшифровать длинные строки с использованием RSA, то вы можете разбить байты на более мелкие «порции» и обрабатывать каждый кусок байта по одному зашифрованному файлу за раз, сохраняя результаты в ByteBuffer.

Шифрование:

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();
...