将修改后的清单文件转换回JarEntry

时间:2014-03-10 16:11:33

标签: java maven jar manifest.mf

在工作中,我们使用了许多已签名的第三方库。其中一些不再维护,但我们仍然需要使用它们。由于最近的Java安全更新,需要更新这些jar中的清单文件以包含额外的安全属性。鉴于jar文件如何工作,我需要在每个jar上执行unpack-edit-repack过程。

这涉及解压缩jar,向清单添加额外属性,同时删除已存在的SHA1签名字符串,重新打包并使用我们自己的签名重新签名jar。这是我到目前为止打开jar包的代码:

public static void unpackJarFile(File srcJarFile) throws IOException{
    File tmpJarFile = File.createTempFile("tempJar", ".tmp");
    JarFile jarFile = new JarFile(srcJarFile);
    JarOutputStream tempJarOutputStream = new JarOutputStream(new FileOutputStream(tmpJarFile));

    //Copy original jar file to the temporary one.
    Enumeration<JarEntry> jarEntries = jarFile.entries();
    while(jarEntries.hasMoreElements()) {
        JarEntry temp = jarEntries.nextElement();

        //if file is manifest then unsign else carry on
        JarEntry entry = isManifestFile(temp) ? unsignManifest(temp, jarFile) : temp;
        // ingore files ending in .SF and .RSA
        if (fileIsNotSignature(entry)){
            InputStream entryInputStream = jarFile.getInputStream(entry);
            tempJarOutputStream.putNextEntry(entry);
            byte[] buffer = new byte[1024];
            int bytesRead = 0;
            while ((bytesRead = entryInputStream.read(buffer)) != -1) {
                tempJarOutputStream.write(buffer, 0, bytesRead);
            }
        }
    }
    tempJarOutputStream.close();
    jarFile.close();
    srcJarFile.delete();
    tmpJarFile.renameTo(srcJarFile);
}

  private static JarEntry unsignManifest(JarEntry signed, JarFile jarFile) throws IOException {

    //extract signed manifest contents into a temp text file
    File tmpManifestFile = File.createTempFile("tempManifest", ".tmp");
    tmpManifestFile.deleteOnExit();
    Manifest manifest = jarFile.getManifest();
    OutputStream fos = new FileOutputStream(tmpManifestFile);

    //write out manifest contents to an actual file on disk for later editing
    manifest.write(fos);
    fos.close();

    //read the physical file back in line by line so that SHA1 strings 
    //can be ignored when creating a new manifest file.
    Path path = Paths.get(tmpManifestFile.getPath());
    List<String> lines = Files.readAllLines(path, Charset.defaultCharset());

    // some logic here. Something like
    // for each line : lines
    // if !line.contains("SHA1-Digest: SWDa1ic/T+le1N+UvrAYf89lY4E=")
    // write it out to the new manifest file
    // append extra security attributes
    //convert new manifest file to new JarEntry unsigned
    // return JarEntry

    return unsigned;

}

鉴于Java的JarEntry和Manifest类的单向性,看起来我必须做所有繁重的工作。我可以把价值拿出去,但是我认为选择性地把它们放进去是很痛苦的。到目前为止,我可以解压并重新包装罐子。正如您在代码末尾所看到的那样,我无法弄清楚如何有选择地将内容放回清单文件并将其转换为JarEntry,以便unpackJarFile()方法认为新创建的清单文件来自原始jar

提前致谢。

0 个答案:

没有答案