Загрузчик Java удаляет цифровой сертификат из подписанного исполняемого файла

Я работаю над загрузчиком java, который извлекает файлы с удаленного сервера и сохраняет их локально.

Вот код, который я использую:

try {

    BufferedInputStream in = new java.io.BufferedInputStream(new URL(link).openStream());
    FileOutputStream fos = new FileOutputStream(destination);
    BufferedOutputStream bout = new BufferedOutputStream(fos,1024);

    byte data[] = new byte[1024];
    int count;

        while( (count = in.read(data,0,1024)) != -1){
        bout.write(data,0,count);
        }

    fos.flush();
    fos.close();
    fos.close();


    } catch(Throwable t){
    t.printStackTrace();
} 

Первое, что я заметил, файл на сервере и загруженный файл имеют разный размер --> http://puu.sh/jGpEj/abbe832796.png (загруженный файл на несколько байт меньше). Обратите внимание, что «размер на диске» выглядит одинаково.

Следующее, что я заметил, если я попытаюсь запустить .exe, загруженный java «от имени администратора», он скажет «Издатель: неизвестен», что неверно, потому что .exe имеет цифровую подпись. Нет вкладки «Цифровые подписи».

Любая подсказка, в чем может быть проблема?

P.S. Я открыл оба файла в шестнадцатеричном редакторе. Они оба имеют одинаковое содержимое, за исключением того, что в файле, загруженном с помощью java, отсутствуют последние 94 байта.


person user2976389    schedule 19.08.2015    source источник


Ответы (1)


Вы пишете в BufferedOutputStream, но сбрасываете один из нисходящих потоков. Другими словами, вы вызываете flush() не в том потоке.

Вместо этого сбросить BufferedOutputStream bout:

try {
  BufferedInputStream in = new java.io.BufferedInputStream(new URL(link).openStream());
  FileOutputStream fos = new FileOutputStream(destination);
  BufferedOutputStream bout = new BufferedOutputStream(fos,1024);

  byte data[] = new byte[1024];
  int count;

  while( (count = in.read(data,0,1024)) != -1){
    bout.write(data,0,count);
  }

  bout.flush();
  bout.close();

  in.close();

} catch(Throwable t){
  t.printStackTrace();
} 

Вы также должны close BufferedOutputStream, и он автоматически распространит закрытие нижележащих потоков. Другими словами, вы не закрываете FileOutputStream напрямую.

Наконец, на самом деле нет необходимости вызывать flush() перед close(), так как выполнение close() в любом случае автоматически вызовет flush().

Кроме того, если вы используете try-with-resources блок, вы можете попросить компилятор вставить закрытие для вас.

person Greg Kopff    schedule 19.08.2015