2009-09-03 15 views
22

Chcę podpisać słoik za pomocą jarsigner, a następnie zweryfikować go za pomocą aplikacji Java, która nie ma podpisanego słoika jako części ścieżki klasy (tj. Po prostu używając lokalizacji systemu plików słoik)Jak zweryfikować słoik podpisany programem Jarsigner programowo

Teraz mój problem polega na usunięciu pliku sygnatury ze słoika, czy istnieje prosty sposób na zrobienie tego?

Odtworzyłem grę z Inflater i Jar InputStreams bez powodzenia.

Czy jest to coś, co można osiągnąć w lepszy sposób?

Dzięki

Odpowiedz

10

security Provider implementation guide przedstawia proces weryfikacji słoikach. Mimo że instrukcje te są przeznaczone dla dostawcy usług kryptograficznych JCA do zweryfikowania, powinny być odpowiednie dla twojego problemu.

W szczególności sprawdź metodę verify(X509Certificate targetCert) w przykładowym kodzie, "MyJCE.java".

+1

Zamiast sugerując kod, mogliby równie dobrze pod warunkiem metoda verifyAllContent() ;-) – lapo

-2

Do tego celu można użyć aplikacji jarsigner. W processbuilder (lub Runtime.exec) można uruchomić polecenie z tych argumentów

ProcessBulider pb = new ProcessBuilder("/usr/bin/jarsigner", "-verify", "-certs", f.getAbsolutePath()); 

i jeśli contians wyjściowe weryfikowane następnie słoik jest podpisanych

Process p = pb.start(); 
p.waitFor(); 
InputStream is = p.getInputStream(); 
InputStreamReader isr = new InputStreamReader(is); 
BufferedReader br = new BufferedReader(isr); 
String line; 
while ((line = br.readLine()) != null) 
{ 
if(line.contains("verified"); 
... 

Są bardziej skomplikowane rzeczy, które możesz zrobić, gdy masz wyjście kodu jarsignera.

+0

Przykład jest specyficzna dla platformy i dodatkowo narzędzie Jarsigner zwykle występuje tylko z JDK. – Robert

+0

jarsigner nie weryfikuje certyfikatu osoby podpisującej (tak, aby zrobił to niezaufany podpis), nie sprawdza zaufanych znaczników czasu (nie może obsłużyć ważnych podpisów od osób podpisujących, których certyfikaty wygasły), a jego wynik jest bezużyteczny (zwana "zweryfikowaną" jest zwracana nawet w przypadku błędów , więcej informacji można uzyskać, analizując komunikaty o błędach i ostrzeżeniach - ale to wciąż nie wystarczy, aby zdecydować, czy certyfikat jest ważny). –

14

Możesz po prostu otworzyć plik JAR za pomocą pliku java.util.jar.JarFile i powiedzieć, aby zweryfikować plik JAR. Jeśli JAR jest podpisany, to JarFile ma opcję jego weryfikacji (domyślnie jest włączona). Jednak JarFile będzie również poprawnie otwierać niepodpisane pliki JAR, dlatego musisz także sprawdzić, czy plik jest podpisany. Możesz to zrobić, zaznaczając manifest JAR dla atrybutów * -Digest: Elementy z takim atrybutem atrybutu są podpisane.

Przykład:

JarFile jar = new JarFile(new File("path/to/your/jar-file")); 

// This call will throw a java.lang.SecurityException if someone has tampered 
// with the signature of _any_ element of the JAR file. 
// Alas, it will proceed without a problem if the JAR file is not signed at all 
InputStream is = jar.getInputStream(jar.getEntry("META-INF/MANIFEST.MF")); 
Manifest man = new Manifest(is); 
is.close(); 

Set<String> signed = new HashSet(); 
for(Map.Entry<String, Attributes> entry: man.getEntries().entrySet()) { 
    for(Object attrkey: entry.getValue().keySet()) { 
     if (attrkey instanceof Attributes.Name && 
      ((Attributes.Name)attrkey).toString().indexOf("-Digest") != -1) 
      signed.add(entry.getKey()); 
    } 
} 

Set<String> entries = new HashSet<String>(); 
for(Enumeration<JarEntry> entry = jar.entries(); entry.hasMoreElements();) { 
    JarEntry je = entry.nextElement(); 
    if (!je.isDirectory()) 
     entries.add(je.getName()); 
} 

// contains all entries in the Manifest that are not signed. 
// Ususally, this contains: 
// * MANIFEST.MF itself 
// * *.SF files containing the signature of MANIFEST.MF 
// * *.DSA files containing public keys of the signer 

Set<String> unsigned = new HashSet<String>(entries); 
unsigned.removeAll(signed); 

// contains all the entries with a signature that are not present in the JAR 
Set<String> missing = new HashSet<String>(signed); 
missing.removeAll(entries); 
+7

Otwarcie słoika za pomocą JarFile (fileName) nie weryfikuje klas w JAR, umożliwia jedynie weryfikację, która ma miejsce przy dostępie. Dlatego do weryfikacji wszystkich wpisów w Jar należy wywołać jar.getInputStream (..) dla każdego wpisu - to uruchamia weryfikację. – Robert

+0

zobacz http://stackoverflow.com/a/5589898/3934807 dla kodu, który implementuje sugestię Roberta – ingenue

2

Można użyć entry.getCodeSigners(), aby uzyskać podpisujących dla danego wpisu w słoiku.

Należy otworzyć plik JarFile za pomocą funkcji verify = true i w pełni odczytać wpis JAR przed wywołaniem entry.getCodeSigners().

Coś takiego może być użyty do sprawdzenia każdy wpis, który nie jest plikiem podpis:

boolean verify = true; 
JarFile jar = new JarFile(signedFile, verify); 

// Need each entry so that future calls to entry.getCodeSigners will return anything 
Enumeration<JarEntry> entries = jar.entries(); 
while (entries.hasMoreElements()) { 
    JarEntry entry = entries.nextElement(); 
    IOUtils.copy(jar.getInputStream(entry), new NullOutputStream()); 
} 

// Now check each entry that is not a signature file 
entries = jar.entries(); 
while (entries.hasMoreElements()) { 
    JarEntry entry = entries.nextElement(); 
    String fileName = entry.getName().toUpperCase(Locale.ENGLISH); 
    if (!fileName.endsWith(".SF") 
     && !fileName.endsWith(".DSA") 
     && !fileName.endsWith(".EC") 
     && !fileName.endsWith(".RSA")) { 

     // Now get code signers, inspect certificates etc here... 
     // entry.getCodeSigners(); 
    } 
} 
Powiązane problemy