Pergunta

Estou querendo assinar um jar usando jarsigner, em seguida, verifique-o usando um aplicativo Java que não tem o jar assinados como parte de seu classpath (i.e.apenas utilizando um sistema de arquivos local do frasco)

Agora o meu problema é conseguir o arquivo de assinatura de fora da jarra, há uma maneira simples de fazer isso?

Eu tive um jogo com o Inflater e Jar InputStreams sem sorte.

Ou isso é algo que pode ser feito de uma maneira melhor?

Obrigado

Foi útil?

Solução

O Fornecedor de segurança do guia de implementação descreve o processo de verificação de Frascos.Embora estas instruções são para um JCA provedor de serviços de criptografia para verificar si, eles devem ser aplicáveis ao seu problema.

Especificamente, confira o verify(X509Certificate targetCert) método no código de exemplo, "MyJCE.java".

Outras dicas

Você pode simplesmente abrir o frasco com java.util.jar.jarfile e pedir para verificar o arquivo jar. Se o frasco for assinado, o Jarfile terá a opção de verificá -lo (que está ligado por padrão). No entanto, o Jarfile também abrirá os frascos não assinados felizes; portanto, você também deve verificar se o arquivo está ou não assinado. Você pode fazer isso verificando o manifesto do frasco para os atributos mais dignos: elementos com esse atributo atributo são assinados.

Exemplo:

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

Você pode usar o Entry.getCodesigners () para obter os assinantes para uma entrada específica no frasco.

Certifique -se de abrir o jarfile com verify = true e ler totalmente a entrada do jar antes de ligar para a entrada.getCodesigners ().

Algo assim poderia ser usado para verificar cada entrada que não é um arquivo de assinatura:

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

Você pode usar o aplicativo Jarsigner para fazer isso. No ProcessBuilder (ou Runtime.exec), você pode executar o comando com esses argumentos

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

e se a saída contians verificada, o frasco será assinado

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

Há coisas mais complicadas que você pode fazer quando tiver a saída do código Jarsigner.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top