/** * Hash the string completely. * * @param content String to be hashed. * @return the hash. */ private String hash(String content) { return hash(content.getBytes()); }
byte[] sigFileContent = getExistingSignatureFile(jf); boolean signed = (sigFileContent != null); Manifest manifest = retrieveManifest(jf); StringBuilder manifestHeader = new StringBuilder(); appendAttributes(manifestHeader, manifest, null); appendLine(me, currentLine); currentLine.setLength(0); me.append(digestAlgorithm).append("-Digest: ").append(hash(jf, je)).append("\r\n"); appendAttributes(me, manifest, name); appendLine(sigFileEntries, currentLine); currentLine.setLength(0); sigFileEntries.append(digestAlgorithm).append("-Digest: ").append(hash(me.toString())).append("\r\n\r\n"); manifestEntries.append(me); StringBuilder sigFile = new StringBuilder("Signature-Version: 1.0\r\n").append(digestAlgorithm).append("-Digest-Manifest-Main-Attributes: ").append(hash(manifestHeader.toString())).append("\r\n").append("Created-By: ").append(System.getProperty("java.version")).append(" (").append(System.getProperty("java.vendor")).append(")\r\n"); sigFile.append(digestAlgorithm).append("-Digest-Manifest: ").append(hash(manifestHeader.toString())).append("\r\n\r\n"); sigFileContent = sigFile.toString().getBytes(); } else { manifestContent = readJarEntry(jf, jf.getJarEntry(JarFile.MANIFEST_NAME)); new FileOutputStream(output)); zout.putNextEntry((signed) ? getZipEntry(jf.getJarEntry(JarFile.MANIFEST_NAME))
byte[] sigFileContent = getExistingSignatureFile(jf); boolean signed = (sigFileContent != null); Manifest manifest = retrieveManifest(jf); StringBuilder manifestHeader = new StringBuilder(); Attributes mfAttrs = manifest.getMainAttributes(); appendAttributes(manifestHeader, mfAttrs); processMetadataForEntry(manifest, manifestEntries, sigFileEntries, name, readJarEntry(jf, je)); processMetadataForEntry(manifest, manifestEntries, sigFileEntries, entry.getKey(), entry.getValue()); StringBuilder sigFile = new StringBuilder("Signature-Version: 1.0\r\n").append(digestAlgorithm).append("-Digest-Manifest-Main-Attributes: ").append(hash(manifestHeader.toString())).append("\r\n").append("Created-By: ").append(System.getProperty("java.version")).append(" (").append(System.getProperty("java.vendor")).append(")\r\n"); sigFile.append(digestAlgorithm).append("-Digest-Manifest: ").append(hash(manifestHeader.toString())).append("\r\n\r\n"); sigFileContent = sigFile.toString().getBytes(); } else { manifestContent = readJarEntry(jf, jf.getJarEntry(JarFile.MANIFEST_NAME)); ? getZipEntry(jf.getJarEntry(JarFile.MANIFEST_NAME)) : new ZipEntry(JarFile.MANIFEST_NAME)); zout.write(manifestContent); String name = je.getName(); if (!name.equals(JarFile.MANIFEST_NAME)) { zout.putNextEntry(getZipEntry(je));
private void processMetadataForEntry(final Manifest manifest, final StringBuilder manifestEntries, final StringBuilder sigFileEntries, final String name, final byte[] content) { StringBuilder me = new StringBuilder(); StringBuilder currentLine = new StringBuilder(); // Create digest lines in MANIFEST.MF currentLine.append("Name: ").append(name); appendLine(me, currentLine); currentLine.setLength(0); me.append(digestAlgorithm).append("-Digest: ").append(hash(content)).append("\r\n"); appendAttributes(me, manifest, name); // Create digest lines in ME.SF currentLine.append("Name: ").append(name); appendLine(sigFileEntries, currentLine); currentLine.setLength(0); sigFileEntries.append(digestAlgorithm).append("-Digest: ").append(hash(me.toString())).append("\r\n\r\n"); manifestEntries.append(me); }
/** * Hash the JarEntry completely. * * @param jf the JarFile * @param je the JarEntry * @throws IOException * @return resulting hash */ private String hash(JarFile jf, JarEntry je) throws IOException { byte[] data = readJarEntry(jf, je); return b64encoder.encodeBuffer(md.digest(data)).trim(); }
/** * Signs a jar. * * @param input input jar file * @param output output jar file * @param alias signing alias in the keystore */ public void signJar(File input, File output, String alias) throws IOException, KeyStoreException, NoSuchAlgorithmException, InvalidKeyException, UnrecoverableKeyException, SignatureException { signJar(input, output, alias, null); }
private static StringBuilder appendAttributes(StringBuilder manifestEntry, Attributes attributes) { StringBuilder line = new StringBuilder(); if (attributes != null) { for (Map.Entry attr : attributes.entrySet()) { line.append(attr.getKey().toString()).append(": ").append((String) attr.getValue()); appendLine(manifestEntry, line); line.setLength(0); } } return manifestEntry.append("\r\n"); }
/** * Add attributes for the current entry. * * @param manifestEntry - The StringBuilder to which the attributes are to be added. * @param manifest - The Jar Manifest Entry * @param entry - The named entry in the manifest. null means the Main Attribute section. * @return manifestEntry with attributes added. */ private static StringBuilder appendAttributes(StringBuilder manifestEntry, Manifest manifest, String entry) { return appendAttributes(manifestEntry, (entry == null) ? manifest.getMainAttributes() : manifest.getAttributes(entry)); }
/** * If jar is signed, return existing Signature file, else return null. * * @param jf The jar file * @return Signature file * @throws IOException */ private static byte[] getExistingSignatureFile(JarFile jf) throws IOException { Enumeration<JarEntry> entries = jf.entries(); JarEntry je = null; while (entries.hasMoreElements()) { JarEntry cje = entries.nextElement(); if (cje.getName().startsWith("META-INF/") && cje.getName().endsWith(".SF")) { je = cje; break; } } return readJarEntry(jf, je); }
/** * Signs a JAR, adding caller-specified attributes to the manifest's main attrs. * * @param input input JAR file * @param output output JAR file * @param alias signing alias in the keystore * @param additionalAttrs additional attributes to add to the manifest's main attrs (null if none) */ public void signJar(File input, File output, String alias, final Attributes additionalAttrs) throws IOException, KeyStoreException, NoSuchAlgorithmException, InvalidKeyException, UnrecoverableKeyException, SignatureException { final ZipOutputStream zout = new ZipOutputStream( new FileOutputStream(output)); try { signJar(input, zout, alias, additionalAttrs, Collections.EMPTY_MAP); } finally { zout.close(); } }
/** * Add attributes for the current entry. * * @param manifestEntry - The StringBuilder to which the attributes are to be added. * @param manifest - The Jar Manifest Entry * @param entry - The named entry in the manifest. null means the Main Attribute section. * @return manifestEntry with attributes added. */ private static StringBuilder appendAttributes(StringBuilder manifestEntry, Manifest manifest, String entry) { Attributes attributes = (entry == null) ? manifest.getMainAttributes() : manifest.getAttributes(entry); StringBuilder line = new StringBuilder(); if (attributes != null) { for (Map.Entry attr : attributes.entrySet()) { line.append(attr.getKey().toString()).append(": ").append((String) attr.getValue()); appendLine(manifestEntry, line); line.setLength(0); } } return manifestEntry.append("\r\n"); }
/** * If jar is signed, return existing Signature file, else return null. * * @param jf The jar file * @return Signature file * @throws IOException */ private static byte[] getExistingSignatureFile(JarFile jf) throws IOException { Enumeration<JarEntry> entries = jf.entries(); JarEntry je = null; while (entries.hasMoreElements()) { JarEntry cje = entries.nextElement(); if (cje.getName().startsWith("META-INF/") && cje.getName().endsWith(".SF")) { je = cje; break; } } return readJarEntry(jf, je); }