SSLEngine unwrap() javax.crypto.BadPaddingException: плохая запись MAC

Это сводит меня с ума уже несколько дней. Я создал клиента, используя Java NIO с SSL-шифрованием с использованием SSLEngine. Рукопожатие работает отлично, и я пишу запрос GET на веб-сайт, и он отлично работает (я получаю заголовок с 200 кода). Проблема в том, что когда веб-сайт отправляет пакеты обратно, на втором пакете я получаю исключение BadPaddingException. Вот мой метод чтения:

    public void read(SelectionKey key,ByteBuffer readBuffer) throws IOException, BadPaddingException {

    SocketChannel socketChannel = (SocketChannel) key.channel();

    ByteBuffer clientSSLData = ByteBuffer.allocate(getPacketBufferSize());
    System.out.println("Reading data. PacketBufferSize: "+(getPacketBufferSize()));
    int length = socketChannel.read(clientSSLData);

    System.out.println("read "+length+" bytes");
    if (length == -1){
        System.out.println("Length is -1 which means nothing was read from the channel  ");
        socketChannel.close();
        return;
    }
    clientSSLData.flip();
    readBuffer.clear();
    SSLEngineResult res = sslEngine.unwrap(clientSSLData, readBuffer);
    System.out.println(res.toString());
}

Мой запрос get выглядит примерно так: "GET \r\nHost: www.google.com\r\n\r\n"

В основном, если это небольшой веб-сайт, такой как https://www.example.com/, у меня нет проблем с получением, потому что он отправляет его в одно чтение. Но если я сделаю что-то вроде https://www.google.com/, я получу исключение BadPaddingException. Есть идеи? Спасибо!

РЕДАКТИРОВАТЬ: Исключение...

javax.net.ssl.SSLException: плохая запись MAC в sun.security.ssl.Alerts.getSSLException(неизвестный источник) в sun.security.ssl.SSLEngineImpl.fatal(неизвестный источник) в sun.security.ssl.SSLEngineImpl.readRecord(Неизвестный источник) на sun.security.ssl.SSLEngineImpl.readNetRecord(неизвестный источник) на sun.security.ssl.SSLEngineImpl.unwrap(неизвестный источник) на javax.net.ssl.SSLEngine.unwrap(неизвестный источник) на ssl.engine.impl.SecureIO.read(SecureIO.java:244) на ssl.engine.impl.ChannelHandler.read(ChannelHandler.java:144) на ssl.engine.impl.ChannelHandler.run(ChannelHandler.java:69) на java.lang.Thread.run(Неизвестный источник) Причина: javax.crypto.BadPaddingException: плохая запись MAC в sun.security.ssl.EngineInputRecord.decrypt(Неизвестный источник) ... еще 8Закрытие вниз

1 ответ

Решение

Вы делаете это неправильно. Когда вам нужно получить данные, вы должны:

  1. Получите из вашего приложения приемный буфер.
  2. Если это пусто, попробуйте unwrap().
  3. Если это дает вам переполнение буфера, прочитайте канал.

Точно так же, когда вам нужно поместить данные, вы должны:

  1. Поместите в ваше приложение буфер отправки.
  2. Если это заполняет, wrap().
  3. Напишите, если это дает вам переполнение буфера.

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

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

Точно так же вы должны позволить движку определять рукопожатие (NEED_WRAP/NEED_UNWRAP), а не пытаться диктовать его.

SSLEngine это очень трудно понять. Многие пытались: немногие преуспели. Для одного рабочего успеха, который является основой для коммерческого продукта, см. SSLEngineManager класс в исходном коде для моей книги " Фундаментальные сети в Java, Springer 2006", здесь.

Другие вопросы по тегам