3659N/A * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 2362N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 2362N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2362N/A * or visit www.oracle.com if you need additional information or have any 0N/A * <p>The jarsigner utility. 1026N/A * The exit codes for the main method are: 1026N/A * 1: any error that the jar cannot be signed or verified, including: 1026N/A * jarsigner command line error... 1026N/A * otherwise: error codes from -strict 0N/A * @author Roland Schemers 0N/A (
"sun.security.tools.JarSignerResources");
0N/A // this is for case insensitive string comparisions 0N/A // prefix for new signature-related files in META-INF directory 0N/A private static final long SIX_MONTHS =
180*
24*
60*
60*
1000L;
//milliseconds 0N/A // This is the entry that get launched by the security tool jarsigner. 1026N/A // signer is not in alias list 1026N/A // or the default keystore, never null 0N/A boolean token =
false;
// token-based keystore 1026N/A // arguments for provider constructors 0N/A boolean externalSF =
true;
// leave the .SF out of the PKCS7 block 0N/A // read zip entry raw bytes 0N/A // Try to load and install the specified providers 3050N/A (
"provName.not.a.provider"));
0N/A SignatureFileVerifier.setDebug(true); 0N/A ManifestEntryVerifier.setDebug(true); 0N/A // load the alternative signing mechanism 0N/A // zero-out private key password 0N/A // zero-out keystore password 0N/A * Parse command line arguments. 1026N/A // -certs must always be specified with -verbose 3050N/A (
"If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified"));
3050N/A (
"If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified"));
3050N/A (
"Usage.jarsigner.options.jar.file.alias"));
3050N/A (
".jarsigner.verify.options.jar.file.alias."));
3050N/A (
".keystore.url.keystore.location"));
3050N/A (
".storepass.password.password.for.keystore.integrity"));
3050N/A (
".storetype.type.keystore.type"));
3050N/A (
".certchain.file.name.of.alternative.certchain.file"));
3050N/A (
".sigfile.file.name.of.SF.DSA.file"));
3050N/A (
".signedjar.file.name.of.signed.JAR.file"));
3050N/A (
".digestalg.algorithm.name.of.digest.algorithm"));
3050N/A (
".sigalg.algorithm.name.of.signature.algorithm"));
3050N/A (
".verify.verify.a.signed.JAR.file"));
3050N/A (
".verbose.suboptions.verbose.output.when.signing.verifying."));
3050N/A (
".suboptions.can.be.all.grouped.or.summary"));
3050N/A (
".certs.display.certificates.when.verbose.and.verifying"));
3050N/A (
".tsa.url.location.of.the.Timestamping.Authority"));
3050N/A (
".tsacert.alias.public.key.certificate.for.Timestamping.Authority"));
3050N/A (
".altsigner.class.class.name.of.an.alternative.signing.mechanism"));
3050N/A (
".altsignerpath.pathlist.location.of.an.alternative.signing.mechanism"));
3050N/A (
".internalsf.include.the.SF.file.inside.the.signature.block"));
3050N/A (
".sectionsonly.don.t.compute.hash.of.entire.manifest"));
3050N/A (
".protected.keystore.has.protected.authentication.path"));
3050N/A (
".providerName.name.provider.name"));
3050N/A (
".providerClass.class.name.of.cryptographic.service.provider.s"));
3050N/A (
".providerArg.arg.master.class.file.and.constructor.argument"));
3050N/A (
".strict.treat.warnings.as.errors"));
0N/A // we just read. this will throw a SecurityException 1026N/A // The map to record display info, only used when -verbose provided 1026N/A // value: the list of files with common key 1026N/A // Only used when -verbose provided 1026N/A // When -certs provided, display info has extra empty 1026N/A // lines at the beginning and end. 1026N/A // signerInfo() must be called even if -verbose 1026N/A // not provided. The method updates various 1026N/A // Print no info for unsigned entries when -verbose:all, 1026N/A // to be consistent with old behavior. 3050N/A ".Signature.related.entries.") +
"\n\n");
3050N/A ".Unsigned.entries.") +
"\n\n");
1026N/A // Entries inside META-INF and other unsigned 1026N/A // entries are grouped separately. 1026N/A // The label finally contains 2 parts separated by '|': 1026N/A // The legend displayed before the entry names, and 1026N/A // the cert info (if -certs specfied). 3050N/A ".s.signature.was.verified."));
3050N/A ".m.entry.is.listed.in.manifest"));
3050N/A ".k.at.least.one.certificate.was.found.in.keystore"));
3050N/A ".i.at.least.one.certificate.was.found.in.identity.scope"));
3050N/A ".X.not.signed.by.specified.alias.es."));
3050N/A "jar.is.unsigned.signatures.missing.or.not.parsable."));
3050N/A rb.
getString(
"This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
3050N/A rb.
getString(
"This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."));
3050N/A rb.
getString(
"This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."));
3050N/A "This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked."));
3050N/A "This.jar.contains.entries.whose.signer.certificate.has.expired."));
3050N/A "This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months."));
3050N/A "This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid."));
3050N/A rb.
getString(
"This.jar.contains.entries.whose.certificate.chain.is.not.validated."));
3050N/A rb.
getString(
"This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es."));
3050N/A "Re.run.with.the.verbose.and.certs.options.for.more.details."));
0N/A }
finally {
// close the resource 0N/A * Display some details about a certificate: 0N/A * [<tab>] <cert-type> [", " <subject-DN>] [" (" <keystore-entry-alias> ")"] 0N/A * [<validity-period> | <expiry-warning>] 1026N/A * Note: no newline character at the end 5663N/A // test if cert will expire within six months 3210N/A x = x +
"ExtendedKeyUsage";
3210N/A x = x +
"NetscapeCertType";
3050N/A ".{0}.extension.does.not.support.code.signing."), x));
1026N/A // never happens, because keystore has been loaded 0N/A ((c>=
'A' && c<=
'Z') ||
0N/A (c>=
'0' && c<=
'9') ||
0N/A // convert illegal characters from the alias to be _'s 3050N/A (
"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or."));
0N/A // Open the jar (zip) file 0N/A /* First guess at what they might be - we don't xclude RSA ones. */ 0N/A // The Attributes of manifest before updating 0N/A // Check if manifest exists 0N/A // Manifest exists. Read its raw bytes. 0N/A // Create new manifest 0N/A * For each entry in jar 0N/A * (except for signature-related META-INF entries), 0N/A * - if entry is not contained in manifest, add it to manifest; 0N/A * - if entry is contained in manifest, calculate its hash and 0N/A * compare it with the one in the manifest; if they are 0N/A * different, replace the hash in the manifest with the newly 0N/A * generated one. (This may invalidate existing signatures!) 0N/A // Store META-INF files in vector, so they can be written 0N/A // ignore signature-related and manifest files 0N/A // jar entry is contained in manifest, check and 0N/A // possibly update its digest attributes 0N/A // Add entry to manifest 0N/A // Recalculate the manifest raw bytes if necessary 2345N/A * The Attributes object is based on HashMap and can handle 2345N/A * continuation columns. Therefore, even if the contents are 2345N/A * not changed (in a Map view), the bytes that it write() 2345N/A * may be different from the original bytes that it read() 2345N/A * from. Since the signature on the main attributes is based 2345N/A * on raw bytes, we must retain the exact bytes. 2345N/A // cat oldHead newTail > newBytes 0N/A // Write out the manifest 0N/A // manifest file has new length 0N/A // Calculate SignatureFile (".SF") and SignatureBlockFile 0N/A // Provide a helpful message when TSA is beyond a firewall 3868N/A "\n -J-Dhttp.proxyHost=<hostname>" +
3868N/A "\n -J-Dhttp.proxyPort=<portnumber>\n" +
3868N/A "\n -J-Dhttps.proxyHost=<hostname> " +
3868N/A "\n -J-Dhttps.proxyPort=<portnumber> ", e);
0N/A // signature block file 0N/A // Write out all other META-INF files that we stored in the 0N/A // Write out all other files 0N/A // close the resouces 0N/A // no IOException thrown in the follow try clause, so disable 0N/A // attempt an atomic rename. If that fails, 0N/A // rename the original jar file, then the signed 0N/A // one, then delete the original. 3050N/A (
"attempt.to.rename.signedJarFile.to.jarFile.failed"));
3050N/A (
"attempt.to.rename.jarFile.to.origJar.failed"));
3050N/A rb.
getString(
"The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
3050N/A rb.
getString(
"The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."));
3050N/A rb.
getString(
"The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."));
0N/A // no IOException thrown in the above try clause, so disable 0N/A // the catch clause. 0N/A // } catch(IOException ioe) { 3050N/A // error(rb.getString("unable.to.sign.jar.")+ioe, ioe); 2345N/A * Find the length of header inside bs. The header is a multiple (>=0) 2345N/A * lines of attributes plus an empty line. The empty line is included 2345N/A // Initial state true to deal with empty header 2345N/A // If header end is not found, it means the MANIFEST.MF has only 2345N/A // the main attributes section and it does not end with 2 newlines. 2345N/A // Returns the whole length so that it can be completely replaced. 0N/A * signature-related files include: 1786N/A // .SF/.DSA/.RSA/.EC files in META-INF subdirs 0N/A // are not considered signature-related 1026N/A * Returns a string of singer info, with a newline at the end 1026N/A // display the signature timestamp, if present 5663N/A // display the certificate(s). The first one is end-entity cert and 3210N/A // its KeyUsage should be checked. 5663N/A // No more warning, we alreay have hasExpiredCert or notYetValidCert 0N/A * Writes all the bytes for a given entry to the specified output stream. 4411N/A // ignore, when a SecretkeyEntry does not include a cert 4411N/A // Ignore, if cacerts cannot be loaded 0N/A // XXX need to disable echo; on UNIX, call getpass(char *prompt)Z 0N/A // and on NT call ?? 1026N/A // Only add TrustedCertificateEntry and self-signed 1026N/A // ignore, when a SecretkeyEntry does not include a cert 0N/A // this never happens, because keystore has been loaded 3050N/A (
"Certificate.not.found.for.alias.alias.must.reference.a.valid.KeyStore.entry.containing.an.X.509.public.key.certificate.for.the"));
0N/A * Check if userCert is designed to be a code signer 0N/A * @param userCert the certificate to be examined 0N/A * @param bad 3 booleans to show if the KeyUsage, ExtendedKeyUsage, 0N/A * NetscapeCertType has codeSigning flag turned on. 0N/A * If null, the class field badKeyUsage, badExtendedKeyUsage, 0N/A * badNetscapeCertType will be set. 0N/A // Can act as a signer? 1026N/A // 1. if KeyUsage, then [0:digitalSignature] or 1026N/A // [1:nonRepudiation] should be true 0N/A // 2. if ExtendedKeyUsage, then should contains ANY or CODE_SIGNING 0N/A // 3. if NetscapeCertType, then should contains OBJECT_SIGNING 0N/A // 1,2,3 must be true 0N/A // OID_NETSCAPE_CERT_TYPE 0N/A (
"2.16.840.1.113730.1.1");
1026N/A // this never happens, because keystore has been loaded 3050N/A (
"Certificate.chain.not.found.in.the.file.specified."));
3050N/A (
"Certificate.chain.not.found.for.alias.alias.must.reference.a.valid.KeyStore.key.entry.containing.a.private.key.and"));
3050N/A (
"found.non.X.509.certificate.in.signer.s.chain"));
1026N/A // We don't meant to print anything, the next call 1026N/A // checks validity and keyUsage etc 5663N/A // No more warning, we alreay have hasExpiredCert or notYetValidCert 0N/A // Did not work out, so prompt user for key password 3050N/A (
"Enter.key.password.for.alias."));
0N/A // this never happens, because keystore has been loaded 3050N/A (
"key.associated.with.alias.not.a.private.key"));
0N/A // this shouldn't happen 0N/A * Reads all the bytes for a given zip entry. 0N/A * Returns manifest entry from given jar file, or null if given jar file 0N/A * does not have a manifest entry. 0N/A // Check all entries for matching name 0N/A * Computes the digests of a zip entry, and returns them as an array 0N/A * of base64-encoded strings. 0N/A // complete the digests 0N/A * Computes the digests of a zip entry, and returns them as a list of 0N/A * Updates the digest attributes of a manifest entry, by adding or 0N/A * replacing digest values. 0N/A * A digest value is added if the manifest entry does not contain a digest 0N/A * for that particular algorithm. 0N/A * A digest value is replaced if it is obsolete. 0N/A * Returns true if the manifest entry has been changed, and false 1604N/A // The entry name to be written into attrs 1604N/A // Find if the digest already exists 1604N/A // Ignored. Writing new digest entry. 0N/A // compare digests, and replace the one in the manifest 0N/A // if they are different 0N/A * Try to load the specified signing mechanism. 0N/A * The URL class loader is used. 0N/A // construct class loader 0N/A // do prepends to get correct ordering 0N/A // attempt to find signer 0N/A // Check that it implements ContentSigner 0N/A * This is a BASE64Encoder that does not insert a default newline at the end of 0N/A * every output line. This is necessary because java.util.jar does its own 0N/A * line management (see Manifest.make72Safe()). Inserting additional new lines 0N/A * can cause line-wrapping problems (see CR 6219522). 0N/A * Encode the suffix that ends every output line. 0N/A /** SignatureFile */ 0N/A /** .SF base name */ 0N/A // sign the whole manifest 0N/A // create digest of the manifest main attributes 0N/A (
"ManifestDigester failed to create " +
0N/A "Manifest-Main-Attribute entry");
0N/A /* go through the manifest entries and create the digests */ 0N/A * Writes the SignatureFile to the specified OutputStream. 0N/A * @param out the output stream 0N/A * @exception IOException if an I/O error has occurred 0N/A * get base file name 0N/A * Generate a signed data block. 0N/A * If a URL or a certificate (containing a URL) for a Timestamping 0N/A * Authority is supplied then a signature timestamp is generated and 0N/A * inserted into the signed data block. 0N/A * @param sigalg signature algorithm to use, or null to use default 0N/A * @param tsaUrl The location of the Timestamping Authority. If null 0N/A * then no timestamp is requested. 0N/A * @param tsaCert The certificate for the Timestamping Authority. If null 0N/A * then no timestamp is requested. 0N/A * @param signingMechanism The signing mechanism to use. 0N/A * @param args The command-line arguments to jarsigner. 0N/A * @param zipFile The original source Zip file. 0N/A * Construct a new signature block. 0N/A // must extract the original encoded form of DN for subsequent 0N/A // name comparison checks (converting to a String and back to 0N/A // an encoded DN could cause the types of String attribute 0N/A // values to be changed) 0N/A * If no signature algorithm was specified, we choose a 0N/A * default that is compatible with the private key algorithm. 0N/A (
"private key algorithm is not compatible with signature algorithm");
0N/A // Timestamp the signature and generate the signature block file 0N/A // Assemble parameters for the signing mechanism 0N/A // Generate the signature block 0N/A * get block file name. 0N/A * Writes the block file to the specified OutputStream. 0N/A * @param out the output stream 0N/A * @exception IOException if an I/O error has occurred 0N/A * This object encapsulates the parameters used to perform content signing. 0N/A * Create a new object. 0N/A * Retrieves the command-line arguments. 0N/A * @return The command-line arguments. May be null. 0N/A * Retrieves the identifier for a Timestamping Authority (TSA). 0N/A * @return The TSA identifier. May be null. 0N/A * Retrieves the certificate for a Timestamping Authority (TSA). 0N/A * @return The TSA certificate. May be null. 0N/A * Retrieves the signature. 0N/A * @return The non-null signature bytes. 0N/A * Retrieves the name of the signature algorithm. 0N/A * @return The non-null string name of the signature algorithm. 0N/A * Retrieves the signer's X.509 certificate chain. 0N/A * @return The non-null array of X.509 public-key certificates. 0N/A * Retrieves the content that was signed. 0N/A * @return The content bytes. May be null. 0N/A * Retrieves the original source ZIP file before it was signed. 0N/A * @return The original ZIP file. May be null.