2011-10-13 13 views
19

Czy istnieje sposób na wyrejestrowanie pliku JAR Java? Mam niektóre podpisane słoiki, których próbuję użyć w moim środowisku programistycznym, ale dostaję wyjątki bezpieczeństwa, więc chcę wyrejestrować te słoiki i mogę je podpisać później, kiedy będę gotowy do wdrożenia.Jak wyrejestrować słoik?

+0

Sprawdziłeś np. to: https://www.chemaxon.com/forum/ftopic65.html? – home

+0

Skąd pochodzą te słoiki? Dlaczego nie możesz zalogować się w swoim środowisku programistycznym? –

+1

Podobno jest sposób. ;-) Dlaczego jednak nie należy po prostu unikać podpisywania JAR podczas programowania? Jeśli to ty kontrolujesz JAR, to powinno być w twojej mocy; jeśli nie jesteś tym, który kontroluje JAR, prawdopodobnie nie zamierzasz nim manipulować (lub pierwotny programista by tego nie podpisał). –

Odpowiedz

25

ja nie znam odpowiedzi, ale tutaj jest to, co chciałbym zrobić:

  1. Rozpakuj plik jar lub pliki o którym mowa (słoje są tylko zamki)
  2. szukać w katalogu META-INF za coś, co nie było MANIFEST-MF.
  3. Usuń to.
  4. Otwórz MANIFEST-MF i usuń elementy, które wyglądały tak, jakby były związane z podpisem.
  5. rejar.
+0

To prawie wszystko, co robisz. – Paul

+1

Idealna odpowiedź .. – Sid

+0

To właśnie musiałem zrobić i nigdy nie znalazłem sposobu na usunięcie podpisu bez rozpakowywania. Chciałbym jednak, jeśli ta odpowiedź byłaby bardziej szczegółowa na temat kroków 2, 3, ponieważ czasami istnieją inne rzeczy niż MANIFEST-MF, które są wymagane, a nie związane z podpisem. Podobnie jak APPLICATION.JNLP! – Jason

0

Jeśli słoiki zostały opracowane przez ciebie, można im zaufać i prawdopodobnie nie musisz ich podpisywać. Jeśli jednak dostałeś je z zewnątrz, powinieneś zbadać, dlaczego wyjątek bezpieczeństwa nadchodzi, zanim je wykorzystasz.

+0

Robię to samo. Pracuję jako wykonawca, aby modyfikować małe części dużej aplikacji, ich serwer budujący automatyzuje podpisywanie. Muszę opracować i zastąpić klasy w dostarczonych słoikach do testowania. Posiadają certyfikaty drogie (to bank), więc muszę pracować z wydajnością ich kompilacji na ich warunkach. – peterk

+0

Słoiki to te, które rozwijam i nie muszę ich podpisywać, zanim zacznę wdrażać ... ale od czasu do czasu chcę użyć słoików do produkcji w moim środowisku programistycznym lub użyć już podpisanego słoika, o którym mi chodzi. rozmieścić. W takim przypadku trudno rozpakować wszystkie słoiki, usunąć sygnaturę i ponownie zipować. Od tego czasu przerobiłem mój system kompilacji, więc to nie pojawia się już często. Mój system kompilacji przechowuje obecnie niepodpisane słoiki i podpisane słoiki w katalogu budowy, dzięki czemu mogę przełączać się między nimi w czasie wolnym. – Jason

1

Pomyślnie zweryfikowałem odpowiedź DwB z małą modyfikacją: Jak stwierdzi Is there a quick way to delete a file from a Jar/war without having to extract the jar and recreate it?, usunięcie tylko z narzędzia słoika nie jest możliwe. Musiałem wprowadzić tylko niewielką zmianę w zastrzeżonym skryptu budowania i nie chciałem odtwarzać całego słoika.

Uświadomiłem sobie, że niepodpisanie było możliwe, gdy zrobiłem tylko ważny plik .RSA o zerowym rozmiarze. Można to osiągnąć jedynie z polecenia jar u:

cd %JAR_DIR% 
jar xvf myapp.jar META-INF/MYAPP.RSA 
type nul > META-INF/MYAPP.RSA 
jar uvf myapp.jar META-INF/MYAPP.RSA 
rmdir /S/Q META-INF 
+0

Nie mam czasu, aby przetestować to rozwiązanie, ale wygląda na to dobre. – Jason

+0

Z dokumentacji narzędzia jarsigner robi to: 1) plik .SF (plik podpisu) 2) plik blokowy podpisu oparty na używanym algorytmie (np. .RSA, .DSA, itp.) 3) modyfikacja (lub utworzenie, jeśli jeszcze nie istnieje) pliku MANIFEST.MF Podsumowanie: po prostu usuń pierwsze 2 pliki i usuń plik MANIFEST.MF lub otwórz i usuń wszystkie hashe wymienione dla każdego z wymienionych tam plików) . W przeciwnym razie usuniesz inne potrzebne pliki (np. Pliki właściwości itp.). Referencje: https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html – atom88

8

Aby usunąć podpis z pliku jar, usuń katalog META-INF od niego. Plik jar to plik zip więc na Linuksie można to zrobić:

zip -d file.jar 'META-INF/*.SF' 'META-INF/*.RSA' 

Jeśli masz wiele plików jar aby odpisać następujące wykonuje polecenia to na każdym pliku jar w bieżącym katalogu i poniżej:

find . -name '*.jar' -exec zip -d '{}' 'META-INF/*.SF' 'META-INF/*.RSA' ';' 
+0

Myślę, że musisz również edytować "META-INF/MANIFEST.MF". ? Czy możesz pozostawić podpisy w tym pliku i sprawić, by słoik nadal działał jako niepodpisany? – Jason

+0

Wydaje się działać bez problemów po prostu usuwając pliki. – martinhans

+0

Dzięki za sprawdzenie, przegłosowałem. Nie zweryfikowałem tego na własną rękę i nadal jestem sceptyczny, że działa we wszystkich przypadkach. Mam nadzieję, że nie masz nic przeciwko mojemu sceptycyzmowi :-) Rozwiązanie jest miłe i byłoby bardziej satysfakcjonującą odpowiedzią na moje pytanie, czy działa w moim przypadku ... za każdym razem, gdy natknę się na to ponownie, przetestuję to i zaktualizuję tę odpowiedź. – Jason

4

widzę odpowiedź została już przyjęta, ale myślę, że może to być przydatne w każdym razie:

ja już ugotował coś (częściowo z innych stanowisk) w celu automatyzacji zadań.
Nie ma żadnych gwarancji, ale działa to dla mnie :)
Kopiuje plik Jar podczas usuwania informacji o podpisie.
Uwaga, MANIFEST jest pozostawiony tylko z sekcją GŁÓWNA!

Zastosowanie javac JarUnsigner.java utworzyć plik .class
Użyj java -cp <class dir> JarUnsigner <inJar> <outJar>

import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.util.Enumeration; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipFile; 
import java.util.zip.ZipOutputStream; 

public class JarUnsigner { 

    private static final String MANIFEST = "META-INF/MANIFEST.MF"; 

    public static void main(String[] args){ 

    if (args.length!=2){ 
     System.out.println("Arguments: <infile.jar> <outfile.jar>"); 
     System.exit(1); 
    } 
    String infile = args[0]; 
    String outfile = args[1]; 
    if ((new File(outfile)).exists()){ 
     System.out.println("Output file already exists:" + outfile); 
     System.exit(1); 
    } 
    try{ 
     ZipFile zipFile = new ZipFile(infile); 
     final ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outfile)); 
     for (Enumeration e = zipFile.entries(); e.hasMoreElements();) { 
     ZipEntry entryIn = (ZipEntry) e.nextElement(); 

     if (! exclude_file(entryIn.getName())) { 

      /* copy the entry as-is */ 
      zos.putNextEntry(new ZipEntry(entryIn.getName())); 
      InputStream is = zipFile.getInputStream(entryIn); 
      byte[] buf = new byte[1024]; 
      int len; 
      while ((len = (is.read(buf))) > 0) { 
      zos.write(buf, 0, len); 
      } 
      zos.closeEntry(); 

     } else { 

      if (MANIFEST.equals(entryIn.getName())){ 
      /* if MANIFEST, adjust the entry */ 
      zos.putNextEntry(new ZipEntry(MANIFEST)); 

      // manifest entries until first empty line. i.e. the 'MainAttributes' section 
      // (this method is used so to keep the formatting exactly the same) 
      InputStream mIS = zipFile.getInputStream(entryIn); 
      BufferedReader in = new BufferedReader(new InputStreamReader(mIS)); 
      String line = in.readLine(); 
      byte[] mNL = "\n".getBytes("UTF-8"); 
      while(line != null && !line.trim().isEmpty()) { 
       zos.write(line.getBytes("UTF-8")); 
       zos.write(mNL); 
       line = in.readLine(); 
      } 
      zos.write(mNL); 
      zos.closeEntry(); 

      }else{ 
      /* else: Leave out the Signature files */ 
      } 

     } 

     } 
     zos.close(); 
     System.out.println("Successfully unsigned " + outfile); 

    }catch(IOException ex){ 
     System.err.println("Error for file: " + infile); 
     ex.printStackTrace(); 
     System.exit(1); 
    } 
    } 

    /** 
    * Exclude .SF signature file 
    * Exclude .RSA and DSA (signed version of .SF file) 
    * Exclude SIG- files (unknown sign types for signed .SF file) 
    * Exclude Manifest file 
    * @param filename 
    * @return 
    */ 
    public static boolean exclude_file(String filename){ 
    return filename.equals("META-INF/MANIFEST.MF") || 
      filename.startsWith("META-INF/SIG-") || 
      filename.startsWith("META-INF/") && (filename.endsWith(".SF") || filename.endsWith(".RSA") || filename.endsWith(".DSA")); 
    } 

} 

Zastosowanie w ANT aby odpisać kilka słoików następująco:

<apply executable="java" dest="${output-dir}"> 
    <arg value="-cp" /> 
    <arg value="${dev-dir}" /> 
    <arg value="JarUnsigner" /> 
    <srcfile/> 
    <targetfile/> 
    <fileset dir="${input-dir}" includes="*.jar"/> 
    <mapper type="glob" from="*.jar" to="*.jar"/> <!-- uses "dest"--> 
</apply> 
+0

Świetny pomysł! Nie testowałem tego, ale staram się zwrócić na siebie uwagę i zobaczyć, czy ktoś ma czas, aby przetestować to rozwiązanie. To byłoby dokładnie to, czego bym chciał. – Jason

+0

Dzięki. używamy go już od jakiegoś czasu. działa ładnie – Houtman

0

Jeśli spojrzeć na narzędzia i jarsigner co robi, generuje 3 rzeczy: 1) plik .SF (plik podpisu) 2) plik blokowy podpisu oparty na używanym algorytmie (np. .RSA, .DSA itp.) 3) modyfikacja lub tworzenie MANIFESTU.Plik MF

Podsumowanie: Aby "wyrejestrować słoik", wystarczy usunąć pierwsze 2 pliki (.sf i .dsa/rsa PLIK). Usuń plik MANIFEST.MF lub otwórz go i usuń wszystkie hashe wymienione dla każdej klasy .class i innego tam wymienionego pliku).

Po usunięciu WSZYSTKIEGO w katalogu META-INF istnieje ryzyko usunięcia innych zasobów słoika, które mogą być potrzebne (np. Pliki właściwości itp.). To "podejście do strzelania" polegające na usunięciu wszystkiego, co "wygląda na powiązane z podpisami", jest szkodliwe i nie jest zgodne z zasadą: 1. nie wyrządzaj szkody (do .jar).

zobaczyć tutaj: https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html

https://docs.oracle.com/javase/tutorial/deployment/jar/intro.html

Zrozumienie podpisywania i weryfikacji

”... Po zarejestrowaniu JAR złożyć swój klucz publiczny jest umieszczony wewnątrz archiwum wraz z towarzyszącym świadectwie tak że jest łatwo dostępny dla każdego, kto chce zweryfikować twój podpis ... Digesty i plik podpisu

Po podpisaniu pliku JAR każdy plik w archiwum otrzymuje pozycję digest w manifeście archiwum. Oto przykład tego, co taki wpis może wyglądać tak:

Nazwa: testów/klas/ClassOne.class SHA1-Digest: TD1GZt8G11dXY2p4olSZPc5Rj64 =

Gdy plik JAR jest podpisane, plik podpis jest generowany automatycznie i umieszczone w katalogu META-INF pliku JAR, tym samym katalogu, który zawiera manifest pliku archiwum. Pliki sygnatur mają nazwy plików z rozszerzeniem .SF.

Signature File Block

Oprócz pliku podpisu, plik blok podpis jest automatycznie umieszczany w katalogu META-INF, gdy plik JAR jest podpisane. W przeciwieństwie do pliku manifestu lub pliku sygnatury pliki bloków sygnatur nie są czytelne dla człowieka.

Plik blok podpis zawiera dwa elementy niezbędne do weryfikacji:

Podpis cyfrowy dla pliku JAR, który został wygenerowany z podpisującego klucz prywatny certyfikat zawierający klucz publiczny podpisującego, które mają być wykorzystywane przez każdy chce sprawdź podpisany plik JAR Nazwy plików bloków sygnatur zwykle mają rozszerzenie .DSA wskazujące, że zostały utworzone domyślnym algorytmem podpisu cyfrowego. Inne rozszerzenia nazw plików są możliwe, jeśli do podpisu są używane klucze powiązane z innym standardowym algorytmem.

Powiązane problemy