java code-signing signature jarsigner

java - jarsigner download



Cómo verificar un tarro firmado con jarsigner programáticamente (4)

Quiero firmar un jar con jarsigner, luego verificarlo con una aplicación Java que no tenga el jar firmado como parte de su classpath (es decir, solo usando una ubicación del jar del sistema de archivos)

Ahora mi problema es sacar el archivo de la firma del frasco, ¿hay alguna forma sencilla de hacerlo?

He jugado con Inflater y Jar InputStreams sin suerte.

¿O es esto algo que se puede lograr de una mejor manera?

Gracias


La guía de implementación del proveedor de seguridad describe el proceso de verificación de los JAR. Aunque estas instrucciones son para que un proveedor de servicios criptográficos JCA se verifique a sí mismo, deben ser aplicables a su problema.

Específicamente, verifique el método de verify(X509Certificate targetCert) en el código de ejemplo, "MyJCE.java" .


Puede usar entry.getCodeSigners () para obtener los firmantes de una entrada particular en el JAR.

Asegúrese de abrir el JarFile con verify = true y de leer completamente la entrada JAR antes de llamar a entry.getCodeSigners ().

Algo como esto podría usarse para verificar cada entrada que no sea un archivo de firma:

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(); } }


Puedes usar la aplicación jarsigner para hacer esto. En processbuilder (o Runtime.exec) puede ejecutar el comando con estos argumentos

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

Y si se verifica la salida contians entonces se firma el tarro.

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"); ...

Hay cosas más complicadas que puedes hacer cuando tienes la salida del código jarsigner.


Simplemente puede abrir el archivo JAR con java.util.jar.JarFile y decirle que verifique el archivo JAR. Si el JAR está firmado, entonces JarFile tiene la opción de verificarlo (que está activado de forma predeterminada). Sin embargo, JarFile también abrirá JAR sin firmar, por lo que también debe verificar si el archivo está firmado o no. Puede hacerlo revisando el manifiesto JAR para los atributos * -Digest: los elementos con dicho atributo están firmados.

Ejemplo:

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);