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 ответ
Вы делаете это неправильно. Когда вам нужно получить данные, вы должны:
- Получите из вашего приложения приемный буфер.
- Если это пусто, попробуйте
unwrap().
- Если это дает вам переполнение буфера, прочитайте канал.
Точно так же, когда вам нужно поместить данные, вы должны:
- Поместите в ваше приложение буфер отправки.
- Если это заполняет,
wrap().
- Напишите, если это дает вам переполнение буфера.
Или делайте все это, когда вам нужно промыть.
Ваш основной интерфейс должен быть с механизмом, и только с каналом, в результате чего механизм сообщает вам о переполнении буфера и переполнении.
Точно так же вы должны позволить движку определять рукопожатие (NEED_WRAP/NEED_UNWRAP), а не пытаться диктовать его.
SSLEngine
это очень трудно понять. Многие пытались: немногие преуспели. Для одного рабочего успеха, который является основой для коммерческого продукта, см. SSLEngineManager
класс в исходном коде для моей книги " Фундаментальные сети в Java, Springer 2006", здесь.