RFC: OpenJDK JarSigner API

Sean Mullan sean.mullan at oracle.com
Fri Aug 14 20:06:39 UTC 2015


This looks good to me.

--Sean

On 08/08/2015 09:56 AM, Weijun Wang wrote:
> Hi All
>
> JDK 9 is more restricted on calling sun.* public methods but we know
> there are users calling sun.security.tools.jarsigner.Main to sign jar
> files. A new API is proposed for this very purpose in OpenJDK. Please
> note it is defined in a jdk.* package therefore not a Java SE API. We
> are also thinking of an API to cover keytool functions. Stay tuned.
>
> The new API does not cover every option of the existing jarsigner tool,
> for example, -altsign, -tsapolicyid, -tsadigestalg, -internalsf,
> -sectionsonly, etc, but we hope it is enough in most use cases.
>
> All suggestions are welcome.
>
> Thanks
> Max
>
> package jdk.security.jarsigner;
>
> /**
>   * An immutable utility class to sign a jar file.
>   * <p>
>   * A caller creates a {@code JarSigner.Builder} object, (optionally)
> sets some
>   * parameters, and then calls the {@link JarSigner.Builder#build build}
> method
>   * to create a {@code JarSigner} object. This {@code JarSigner} object
> can then
>   * be used to sign a jar file.
>   * <p>
>   * Unless otherwise stated, calling a method of {@code JarSigner} or
>   * {@code JarSigner.Builder} with a null argument will throw
>   * a {@link NullPointerException}.
>   * <p>
>   * Example:
>   * <pre>
>   * JarSigner signer = new JarSigner.Builder(key, certPath)
>   *         .digestAlg("SHA-1")
>   *         .sigAlg("SHA1withDSA")
>   *         .build();
>   * try (ZipFile in = new ZipFile(inputFile);
>   *         FileOutputStream out = new FileOutputStream(outFile)) {
>   *     signer.sign(in, out);
>   * }
>   * </pre>
>   *
>   * @since 1.9
>   */
> @jdk.Exported
> public final class JarSigner {
>
>      /**
>       * A mutable builder class that can create an immutable {@code
> JarSigner}
>       * from various signing-related parameters.
>       *
>       * @since 1.9
>       */
>      @jdk.Exported
>      public static class Builder {
>
>          /**
>           * Creates a {@code JarSigner.Builder} object with
>           * a {@link KeyStore.PrivateKeyEntry} object.
>           *
>           * @param entry the {@link KeyStore.PrivateKeyEntry} of the
> signer.
>           */
>          public Builder(KeyStore.PrivateKeyEntry entry);
>
>          /**
>           * Creates a {@code JarSigner.Builder} object with a private
> key and
>           * a certification path.
>           *
>           * @param privateKey the private key of the signer.
>           * @param certPath the certification path of the signer.
>           * @throws IllegalArgumentException if {@code certPath} is
> empty, or
>           *      the {@code privateKey} algorithm does not match the
> algorithm
>           *      of the {@code PublicKey} in the end entity certificate
>           *      (the first certificate in {@code certPath}).
>           */
>          public Builder(PrivateKey privateKey, CertPath certPath);
>
>          /**
>           * Sets the digest algorithm. If no digest algorithm is specified,
>           * the default algorithm returned by {@link #getDefaultDigestAlg}
>           * will be used.
>           *
>           * @param algorithm the standard name of the algorithm. See
>           *      the MessageDigest section in the <a href=
>           *
> "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">
>           *      Java Cryptography Architecture Standard Algorithm Name
>           *      Documentation</a> for information about standard
> algorithm names.
>           * @return the {@code JarSigner.Builder} itself.
>           * @throws NoSuchAlgorithmException if {@code algorithm} is not
> available.
>           */
>          public Builder digestAlg(String algorithm) throws
> NoSuchAlgorithmException;
>
>          /**
>           * Sets the digest algorithm from the specified provider.
>           * If no digest algorithm is specified, the default algorithm
>           * returned by {@link #getDefaultDigestAlg} will be used.
>           *
>           * @param algorithm the standard name of the algorithm. See
>           *      the MessageDigest section in the <a href=
>           *
> "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">
>           *      Java Cryptography Architecture Standard Algorithm Name
>           *      Documentation</a> for information about standard
> algorithm names.
>           * @param provider  the provider.
>           * @return the {@code JarSigner.Builder} itself.
>           * @throws NoSuchAlgorithmException if {@code algorithm} is not
> available
>           *                                  in the specified provider.
>           */
>          public Builder digestAlg(String algorithm, Provider provider)
>                  throws NoSuchAlgorithmException;
>
>          /**
>           * Sets the signature algorithm. If no signature algorithm
>           * is specified, the default signature algorithm returned by
>           * {@link #getDefaultSigAlg} for the private key algorithm will
> be used.
>           *
>           * @param algorithm the standard name of the algorithm. See
>           *      the Signature section in the <a href=
>           *
> "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature">
>           *      Java Cryptography Architecture Standard Algorithm Name
>           *      Documentation</a> for information about standard
> algorithm names.
>           * @return the {@code JarSigner.Builder} itself.
>           * @throws NoSuchAlgorithmException if {@code algorithm} is not
> available.
>           * @throws IllegalArgumentException if {@code algorithm} is not
> compatible
>           *      with the algorithm of the signer's private key.
>           */
>          public Builder sigAlg(String algorithm) throws
> NoSuchAlgorithmException;
>
>          /**
>           * Sets the signature algorithm from the specified provider.
>           * If no signature algorithm is specified, the default
> signature algorithm
>           * returned by {@link #getDefaultSigAlg} for the private key
> algorithm
>           * will be used.
>           *
>           * @param algorithm the standard name of the algorithm. See
>           *      the Signature section in the <a href=
>           *
> "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature">
>           *      Java Cryptography Architecture Standard Algorithm Name
>           *      Documentation</a> for information about standard
> algorithm names.
>           * @param provider  the provider.
>           * @return the {@code JarSigner.Builder} itself.
>           * @throws NoSuchAlgorithmException if {@code algorithm} is not
> available
>           *      in the specified provider.
>           * @throws IllegalArgumentException if {@code algorithm} is not
> compatible
>           *      with the algorithm of the signer's private key.
>           */
>          public Builder sigAlg(String algorithm, Provider provider)
>                  throws NoSuchAlgorithmException;
>
>          /**
>           * Sets the URI of the Time Stamping Authority (TSA).
>           *
>           * @param uri the URI.
>           * @return the {@code JarSigner.Builder} itself.
>           */
>          public Builder tsa(URI uri);
>
>          /**
>           * Sets the signer name. The name will be used as the base name
> for
>           * the signature files. All lowercase characters will be
> converted to
>           * uppercase for signature file names. If a signer name is not
>           * specified, the string "SIGNER" will be used.
>           *
>           * @param name the signer name.
>           * @return the {@code JarSigner.Builder} itself.
>           * @throws IllegalArgumentException if {@code name} is empty or
> has a size
>           *      bigger than 8, or it contains characters not from the set
>           *      "a-zA-Z0-9_-".
>           */
>          public Builder signerName(String name);
>
>          /**
>           * Gets the default digest algorithm.
>           *
>           * @implNote This implementation returns "SHA-256". The value may
>           * change in the future.
>           *
>           * @return the default digest algorithm.
>           */
>          public static String getDefaultDigestAlg();
>
>          /**
>           * Gets the default signature algorithm for a private key
> algorithm.
>           * For example, SHA256withRSA for RSA, and SHA256withDSA for DSA.
>           *
>           * @implNote This implementation returns "SHA256withDSA" for
> the "DSA"
>           * key algorithm, "SHA256withRSA" for "RSA", "SHA256withECDSA"
> for "EC",
>           * and {@code null} otherwise. The value(s) may change in the
> future.
>           *
>           * @param keyAlg the key algorithm.
>           * @return the default signature algorithm. Returns null if a
> default
>           * signature algorithm cannot be found. In this case, {@link
> #sigAlg}
>           * must be called to specify a signature algorithm. Otherwise,
>           * the {@link #build} method will throw an {@link
> IllegalArgumentException}.
>           * @throws IllegalArgumentException if {@code keyAlg} is empty.
>           */
>          public static String getDefaultSigAlg(String keyAlg);
>
>          /**
>           * Builds a {@code JarSigner} object from the parameters set by
> the
>           * setter methods.
>           * <p>
>           * This method does not modify internal state of this {@code
> Builder}
>           * object and can be called multiple times to generate multiple
>           * {@code JarSigner} objects. After a {@code JarSigner} object is
>           * built, calling any setter method on this {@code Builder}
> will have
>           * no effect on it.
>           *
>           * @return the {@code JarSigner} object.
>           * @throws IllegalArgumentException if a signature algorithm is
> not
>           *      set and cannot be derived from the private key using the
>           *      {@link #getDefaultSigAlg} method.
>           */
>          public JarSigner build();
>      }
>
>      /**
>       * Signs a file into an {@link OutputStream}. This method will not
> close
>       * {@code file} or {@code os}.
>       *
>       * @param file the file to sign.
>       * @param os the output stream.
>       * @throws JarSignerException if the signing fails.
>       */
>      public void sign(ZipFile file, OutputStream os);
>
>      /**
>       * Returns the digest algorithm for this {@code JarSigner}.
>       * @return the digest algorithm. The return value is never null.
>       */
>      public String getDigestAlg();
>
>      /**
>       * Returns the signature algorithm for this {@code JarSigner}.
>       * @return the signature algorithm. The return value is never null.
>       */
>      public String getSigAlg();
>
>      /**
>       * Returns the URI of the Time Stamping Authority (TSA).
>       * @return the URI of the TSA.
>       */
>      public URI getTsa();
>
>      /**
>       * Returns the signer name of this {@code JarSigner}.
>       * @return the signer name. The return value is never null.
>       */
>      public String getSignerName();
> }
>
> /**
>   * This exception is thrown when {@link JarSigner#sign} fails.
>   *
>   * @since 1.9
>   */
> @jdk.Exported
> public class JarSignerException extends RuntimeException {
>
>      private static final long serialVersionUID = -4732217075689309530L;
>
>      /**
>       * Constructs a new {@code JarSignerException} with the specified
> detail
>       * message and cause.  <p>Note that the detail message associated with
>       * {@code cause} is <i>not</i> automatically incorporated in
>       * this {@code JarSignerException}'s detail message.
>       *
>       * @param  message the detail message (which is saved for later
> retrieval
>       *         by the {@link #getMessage()} method).
>       * @param  cause the cause (which is saved for later retrieval by the
>       *         {@link #getCause()} method).  (A <tt>null</tt> value is
>       *         permitted, and indicates that the cause is nonexistent or
>       *         unknown.)
>       */
>      public JarSignerException(String message, Throwable cause);
> }



More information about the security-dev mailing list