Difference between revisions of "JAR Signing"

From Eclipsepedia

Jump to: navigation, search
(How is signing done?)
 
(35 intermediate revisions by 9 users not shown)
Line 1: Line 1:
 
== Overview ==
 
== Overview ==
We are working towards signing Eclipse builds for the 3.2 Callisto releaseThe goal of signing is to allow users to verify that the content they obtain from eclipse.org and subsequently execute does indeed come from that source. Signing in a nutshell works as follows:
+
Eclipse project builds after 3.3 M3 are now signedSigning allows users to verify that the content they obtain from eclipse.org and subsequently execute does indeed come from that source. Signing in a nutshell works as follows:
  
 
# Eclipse builds produce content in various forms (zips, update JARS)
 
# Eclipse builds produce content in various forms (zips, update JARS)
Line 9: Line 9:
 
# Verification is performed on the user's machine (signature + public key = hash of content)
 
# Verification is performed on the user's machine (signature + public key = hash of content)
  
== Open problems ==
+
== Signing ==
  
 
=== What gets signed? ===
 
=== What gets signed? ===
  
The two principal outputs from the build process are update site JARs and stand-alone zips.
+
By default, every JAR pushed to an update site will be signedThis includes JARs nested at arbitrary depth within other JARs. Some JARs may be excluded if there are technical or legal reasons why they cannot be signedIn standalone zip distribtions, all JARed plugins will be signed, and un-JARed plugins will not be signed.
 
+
==== Signing stand-alone zips ====
+
''This is a bit of a misnomer.  We really want to sign the Java code jars.  If they happen to be in the zip, so be itSigning of DLLs and EXEs is a separate problem that we are not tackling for stand-alone zips or update site based installs''
+
 
+
The problem with stand-alone zips is that there is no opportunity to perform verification at download time.  The user would need to take a manual step to run verification on the zip before unzipping and using it.  Note that signing only the JARs within the stand-alone zips is not sufficient verification.  For example, the eclipse executable is not within a JAR, and a compromised executable would negate the value of any other signing. Possible approaches for signing stand-alone executables:
+
 
+
* Do nothingIf users want to obtain verifiable content, they must obtain it from an update site
+
* Sign only the JARs within the stand-alone zip.  This has no authentication value in itself, but might be useful raw material for others in the community who want to tackle complete authentication of an Eclipse-based application
+
* Create a signature of the entire zip file, and make the signature available in a separate JAR file.  The user would then have to perform verification manually
+
 
+
==== Signing update site content ====
+
 
+
Signing of content on Eclipse update sites is slightly easier.  All executable content is contained in JAR files, so the traditional Java JAR signing mechanism can be used.
+
  
 
=== How is signing done? ===
 
=== How is signing done? ===
  
There are several ways we could sign update JAR content:
+
Signing is performed using the JDK's [http://java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/jarsigner.html jarsigner]. This tool signs JARs by producing a separate signature for every file in the JAR.  The signatures are put in the MANIFEST.MF file and in a separate signature file in the META-INF directory.  For optimization purposes, the signature of the MANIFEST.MF with all embedded signatures is also computed and placed in the signature file.
  
* Traditional Java JAR signing.  The JDK comes with a tool called [http://java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/jarsigner.html jarsigner]. This tool signs JARs by producing a separate signature for every file in the JAR.  The signatures are put in the MANIFEST.MF file and in a separate signature file in the META-INF directory.  For optimization purposes, the signature of the MANIFEST.MF with all embedded signatures is also computed and placed in the signature file.  The pros of using this approach are that the jarsigner tool is already available, and the signed JAR can also be used for runtime verification. The cons are that producing signatures for every file adds bulk to the download (about 3MB for the Eclipse SDK), and it is very slow to run (about an hour for the Eclipse SDK).
+
If you're an Eclipse.org project and you'd like to sign your bundles, please see this document: http://wiki.eclipse.org/IT_Infrastructure_Doc#Sign_my_plugins.2FZIP_files.3F
* Compute a single signature per JAR file.  This should be much faster and have negligible size, but would require a custom signing tool. The signature would be placed in a separate JAR signed using jarsigner (either one signature JAR per update JAR, or one signature JAR per update site).
+
* Nested JARs.  A sneaky way to get a single signature per JAR is to put each JAR in a wrapper JAR, and sign the wrapper.  This would allow using the jarsigner tool, but would require significant changes to the structure of update site content, and changes to the update code to remove the signed wrappers
+
 
+
''The main challenge in doing it the non-standard way is that the jars are not usable as signed by normal classloaders (e.g., when running with JNLP and the org.eclipse.osgi bundle which is loaded by a standard URL classloader)''
+
  
 
=== Where is signing done? ===
 
=== Where is signing done? ===
  
A critical part of the security behind signing is that the private keys used to produce the signatures are held in a secure location and never transmitted or accessible via a network. To accomplish this, the signing needs to be done on a secure machine that has access to the private key.  The Eclipse Foundation has set up a machine with a signing script.  The build will upload content to be signed to this machine, and a script is run to perform the signing.  Access to this machine will be given to trusted parties that want to perform signing.
+
A critical part of the security behind signing is that the private keys used to produce the signatures are held in a secure location and never transmitted or accessible via a network. To accomplish this, the signing must be done on a secure machine that has access to the private key.  The Eclipse Foundation has set up a machine with a signing script.  The build will upload content to be signed to this machine, and a script is run to perform the signing.  Access to this machine will be given to trusted parties that want to perform signing.
 +
 
 +
At the time of writing, persons who want to get jar signing privilege need to be committers, and apply for that privilege with the Webmaster. Project leads are required to authorize the request. Special permissions will be granted to the committer's UNIX login on the jar signing machine.
  
 
=== When is signing done? ===
 
=== When is signing done? ===
  
Signing will be done as part of the build process.  Because this adds a significant amount of time to the build process, the releng team is investigating streamlining the build process.  The process of producing a signed build is:
+
Signing can either be done manually or as part of an automated build process.  The Eclipse project build scripts create signed builds using the following steps:
  
# Checkout source from eclipse.org CVS repositories to build machine
+
# Checkout source from eclipse.org CVS repositories to build machine
# Run build and produce build output
+
# Run build and produce a single ZIP of all plugins in update site form (all plugins in JARs)
# Send build output to eclipse.org for signing
+
# Send build output to eclipse.org for signing
# Send signed build to download server, and to test machines for automated testing
+
# Copy zip of signed JARs back to the build machine
 +
# Prepare compressed pack200.gz JARs to optimize update site
 +
# Send signed and packed build to update site
 +
# Package standalone zips for downloads page
 +
# Copy standalone zips to test machines for automated testing
 +
 
 +
See [[Platform-releng-signedbuild]] for details on how the Eclipse release engineering scripts accomplish this.
  
 
Currently the Eclipse project build machine is located remote from the Eclipse Foundation servers.  This means the Eclipse source has to be transferred across the Internet, and the build output needs to be transferred back to Foundation machines for signing.  These two major network bottlenecks could be removed by also using Eclipse Foundation machines for building.
 
Currently the Eclipse project build machine is located remote from the Eclipse Foundation servers.  This means the Eclipse source has to be transferred across the Internet, and the build output needs to be transferred back to Foundation machines for signing.  These two major network bottlenecks could be removed by also using Eclipse Foundation machines for building.
Line 55: Line 46:
 
=== What public key (certificate) do we use? ===
 
=== What public key (certificate) do we use? ===
  
The Eclipse Foundation should purchase a certificate from a secure certificate provider, such as verisign.  Content made available on Eclipse.org will be signed with the foundation certificate.  Note this doesn't preclude other parties from later signing the JARs with their own certificates.
+
The Eclipse Foundation [https://bugs.eclipse.org/bugs/show_bug.cgi?id=130943 has purchased] a signing certificate from Verisign.  Content made available on Eclipse.org will be signed with the foundation certificate.  Note this doesn't preclude other parties from later signing the JARs with their own certificates.
  
 
=== Where are the signatures stored? ===
 
=== Where are the signatures stored? ===
  
Using traditional JDK signing, the signatures are stored in the JAR file, both in the MANIFEST.MF, and in a separate signature file (currently Eclipse_.sf).
+
The signatures are stored in the JAR file, both in the MANIFEST.MF, and in a separate signature file (currently Eclipse_.sf).
 +
 
 +
=== What effect does signing have on runtime behaviour? ===
 +
 
 +
There are some side-effects of signing that can impact runtime behaviour:
 +
 
 +
# Class loaders may perform verification when they encounter signed content.  Since verification is potentially expensive, this can impact performance. In particular, URLClassLoader and any subclasses will '''always''' verify any JAR from which classes are loaded if they contain a signature. By contrast, the class loaders used by OSGi will '''not''' perform verification by default. Therefore this does not impact most typical Eclipse/OSGi code, but may affect code that uses custom class loaders. If you are using custom class loaders and JAR verification isn't important to you, you can use [[JarProcessor_Options]] to flag your JAR as not requiring signing.
 +
# java.util.jar.JarFile will verify jars unless explicitly configured not to. The JarFile constructors have an optional boolean parameter to configure whether verification should be performed. The simple constructors, such as JarFile(File) and JarFile(String), '''will''' perform verification.  This can have a performance impact when dealing with signed jars.
 +
# Since signatures are stored in the manifest of a JAR file, any code that parses and otherwise manipulates JAR manifests can have a performance impact. For example, anyone calling java.util.JarFile#getManifest() will cause the entire manifest file to be parsed.  Most clients reading manifest are only interested in the manifest's main attributes (Manifest#getMainAttributes()). If so, they can write their own parser that reads these attributes much more quickly.  The main attributes are separated from the per-entry attributes by the first blank line.  See the [http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html Jar file specification] for details.
 +
 
 +
=== Should third party JARs be signed? ===
 +
 
 +
A signature on a JAR file simply allows a user who downloads content from eclipse.org to verify that the content they receive matches the content on the server. Therefore, it makes sense to sign all content made available on eclipse.org, including JAR files originally obtained from third parties.  However, with third party JARs there are two additional considerations:
 +
# You need to ensure that signing the JAR is permitted by the license of the third party content
 +
# If the third party JAR makes use of custom class loaders, there may be performance implications to signing the JAR.  See the section on [[#What effect does signing have on runtime behaviour%3F|the effect of signing on runtime behaviour]] for more details.
 +
 
 +
=== Can the signing process fail? ===
 +
 
 +
Yes. One common way it can fail, even when every one has done every thing correctly, is that due to network or server problems the Eclipse process can not communicate with the Timestamping Authority process. When this, or other failures, happen, there is no easy way to detect it automatically, at the time of the failure (see {{bug|321795}}). Such failures might just miss one jar out of hundreds, or might cause a whole set of jars to go unsigned. So, the point is, build distributions should ALWAYS be checked to make sure all jars are signed as expected, before being the jars are distributed (especially for releases, but even milestones and weekly builds, if expected to be picked up by others). While release engineers can write scripts or Java code to automate the checking, in its simplest form, it can be done by simply calling 'jarsigner' with the -verify option, such as
 +
 
 +
  ${JAVA_HOME}/bin/jarsigner -verify ${pathAndNameOfJarFile}
 +
 
 +
This prints out a short message, such as "verified" or "No signature found in MANIFEST.MF" or similar.
 +
 
 +
== Verification ==
  
 
=== When does verification happen? ===
 
=== When does verification happen? ===
Line 70: Line 85:
 
== Miscellaneous links ==
 
== Miscellaneous links ==
  
* [https://bugs.eclipse.org/bugs/show_bug.cgi?id=43889 OSGi Bundle signing bug report]
+
=== Eclipse Bugzilla reports ===
* [https://bugs.eclipse.org/bugs/show_bug.cgi?id=78208 Bug for runtime signing support]
+
 
* [https://bugs.eclipse.org/bugs/show_bug.cgi?id=94461 Bug for signing indicator in About dialog]
+
{|
* [https://bugs.eclipse.org/bugs/show_bug.cgi?id=130943 Bug for purchasing signing certificates]
+
|-
* [https://bugs.eclipse.org/bugs/show_bug.cgi?id=132046 Bug for signing script to signal completion]
+
! Done || Description
* [https://bugs.eclipse.org/bugs/show_bug.cgi?id=132048 Bug for starting signing immediately after signing script is called]
+
|-
* [https://www.verisign.com/products-services/security-services/code-signing/digital-ids-code-signing/index.html Verisign code signing * [http://java.sun.com/j2se/1.5.0/docs/guide/security/time-of-signing.html Sun docs on timestamps in signatures]
+
|
 +
| [https://bugs.eclipse.org/bugs/show_bug.cgi?id=174475 Don't resign bundles that have already been signed by eclipse.org cert]
 +
|-
 +
|
 +
| [https://bugs.eclipse.org/bugs/show_bug.cgi?id=43889 OSGi Bundle signing bug report]
 +
|-
 +
| [[Image:check.gif]]
 +
| [https://bugs.eclipse.org/bugs/show_bug.cgi?id=78208 Runtime signing support]
 +
|-
 +
| [[Image:check.gif]]
 +
| [https://bugs.eclipse.org/bugs/show_bug.cgi?id=94461 Signing indicator in About dialog]
 +
|-
 +
| [[Image:check.gif]]
 +
| [https://bugs.eclipse.org/bugs/show_bug.cgi?id=130943 Purchasing signing certificates]
 +
|-
 +
| [[Image:check.gif]]
 +
| [https://bugs.eclipse.org/bugs/show_bug.cgi?id=132046 Signing script to signal completion]
 +
|-
 +
| [[Image:check.gif]]
 +
| [https://bugs.eclipse.org/bugs/show_bug.cgi?id=132048 Starting signing immediately after signing script is called]
 +
|-
 +
| [[Image:check.gif]]
 +
| [https://bugs.eclipse.org/bugs/show_bug.cgi?id=134264 Bug for installing Java 1.5 on signing server]
 +
|-
 +
| [[Image:check.gif]]
 +
| [https://bugs.eclipse.org/bugs/show_bug.cgi?id=135044 Bug for installing Improved signing/packing application on signing server]
 +
|-
 +
| [[Image:check.gif]]
 +
| [https://bugs.eclipse.org/bugs/show_bug.cgi?id=130383 Bug for using OSGi verification during update]
 +
|-
 +
| [[Image:check.gif]]
 +
| [https://bugs.eclipse.org/bugs/show_bug.cgi?id=263708 Bug for using Timestamp Authority in signatures]
 +
|}
 +
 
 +
=== Other signing links ===
 +
 
 +
* [[Pack200#Jar_Processor]] documents the JarProcessor tool that performs JAR signing
 +
* [[JarProcessor_Options]] documents the options available for configuring the behaviour of JarProcessor
 +
* [https://www.verisign.com/products-services/security-services/code-signing/digital-ids-code-signing/index.html Verisign code signing products]
 +
* [http://java.sun.com/j2se/1.5.0/docs/guide/security/time-of-signing.html Sun docs on timestamps in signatures]
 +
* [http://opentsa.org/ Web site of open source time stamp protocol implementation]
 +
* [http://www.digistamp.com/ Time stamping service]
  
products]
+
[[Category:Equinox]]
 +
[[Category:Security|JAR Signing]]
 +
[[Category:Eclipse_Platform_Releng| ]]

Latest revision as of 15:10, 11 September 2012

Contents

[edit] Overview

Eclipse project builds after 3.3 M3 are now signed. Signing allows users to verify that the content they obtain from eclipse.org and subsequently execute does indeed come from that source. Signing in a nutshell works as follows:

  1. Eclipse builds produce content in various forms (zips, update JARS)
  2. The Eclipse Foundation produces a signature of the build content using its private key (signature = private key + content)
  3. User downloads build content and signatures from eclipse.org or from mirrors
  4. The Eclipse Foundation makes available a public key for verifying signatures
  5. User consults some trusted authority to verify that the public key does indeed belong to the Eclipse Foundation
  6. Verification is performed on the user's machine (signature + public key = hash of content)

[edit] Signing

[edit] What gets signed?

By default, every JAR pushed to an update site will be signed. This includes JARs nested at arbitrary depth within other JARs. Some JARs may be excluded if there are technical or legal reasons why they cannot be signed. In standalone zip distribtions, all JARed plugins will be signed, and un-JARed plugins will not be signed.

[edit] How is signing done?

Signing is performed using the JDK's jarsigner. This tool signs JARs by producing a separate signature for every file in the JAR. The signatures are put in the MANIFEST.MF file and in a separate signature file in the META-INF directory. For optimization purposes, the signature of the MANIFEST.MF with all embedded signatures is also computed and placed in the signature file.

If you're an Eclipse.org project and you'd like to sign your bundles, please see this document: http://wiki.eclipse.org/IT_Infrastructure_Doc#Sign_my_plugins.2FZIP_files.3F

[edit] Where is signing done?

A critical part of the security behind signing is that the private keys used to produce the signatures are held in a secure location and never transmitted or accessible via a network. To accomplish this, the signing must be done on a secure machine that has access to the private key. The Eclipse Foundation has set up a machine with a signing script. The build will upload content to be signed to this machine, and a script is run to perform the signing. Access to this machine will be given to trusted parties that want to perform signing.

At the time of writing, persons who want to get jar signing privilege need to be committers, and apply for that privilege with the Webmaster. Project leads are required to authorize the request. Special permissions will be granted to the committer's UNIX login on the jar signing machine.

[edit] When is signing done?

Signing can either be done manually or as part of an automated build process. The Eclipse project build scripts create signed builds using the following steps:

  1. Checkout source from eclipse.org CVS repositories to build machine
  2. Run build and produce a single ZIP of all plugins in update site form (all plugins in JARs)
  3. Send build output to eclipse.org for signing
  4. Copy zip of signed JARs back to the build machine
  5. Prepare compressed pack200.gz JARs to optimize update site
  6. Send signed and packed build to update site
  7. Package standalone zips for downloads page
  8. Copy standalone zips to test machines for automated testing

See Platform-releng-signedbuild for details on how the Eclipse release engineering scripts accomplish this.

Currently the Eclipse project build machine is located remote from the Eclipse Foundation servers. This means the Eclipse source has to be transferred across the Internet, and the build output needs to be transferred back to Foundation machines for signing. These two major network bottlenecks could be removed by also using Eclipse Foundation machines for building.

[edit] What public key (certificate) do we use?

The Eclipse Foundation has purchased a signing certificate from Verisign. Content made available on Eclipse.org will be signed with the foundation certificate. Note this doesn't preclude other parties from later signing the JARs with their own certificates.

[edit] Where are the signatures stored?

The signatures are stored in the JAR file, both in the MANIFEST.MF, and in a separate signature file (currently Eclipse_.sf).

[edit] What effect does signing have on runtime behaviour?

There are some side-effects of signing that can impact runtime behaviour:

  1. Class loaders may perform verification when they encounter signed content. Since verification is potentially expensive, this can impact performance. In particular, URLClassLoader and any subclasses will always verify any JAR from which classes are loaded if they contain a signature. By contrast, the class loaders used by OSGi will not perform verification by default. Therefore this does not impact most typical Eclipse/OSGi code, but may affect code that uses custom class loaders. If you are using custom class loaders and JAR verification isn't important to you, you can use JarProcessor_Options to flag your JAR as not requiring signing.
  2. java.util.jar.JarFile will verify jars unless explicitly configured not to. The JarFile constructors have an optional boolean parameter to configure whether verification should be performed. The simple constructors, such as JarFile(File) and JarFile(String), will perform verification. This can have a performance impact when dealing with signed jars.
  3. Since signatures are stored in the manifest of a JAR file, any code that parses and otherwise manipulates JAR manifests can have a performance impact. For example, anyone calling java.util.JarFile#getManifest() will cause the entire manifest file to be parsed. Most clients reading manifest are only interested in the manifest's main attributes (Manifest#getMainAttributes()). If so, they can write their own parser that reads these attributes much more quickly. The main attributes are separated from the per-entry attributes by the first blank line. See the Jar file specification for details.

[edit] Should third party JARs be signed?

A signature on a JAR file simply allows a user who downloads content from eclipse.org to verify that the content they receive matches the content on the server. Therefore, it makes sense to sign all content made available on eclipse.org, including JAR files originally obtained from third parties. However, with third party JARs there are two additional considerations:

  1. You need to ensure that signing the JAR is permitted by the license of the third party content
  2. If the third party JAR makes use of custom class loaders, there may be performance implications to signing the JAR. See the section on the effect of signing on runtime behaviour for more details.

[edit] Can the signing process fail?

Yes. One common way it can fail, even when every one has done every thing correctly, is that due to network or server problems the Eclipse process can not communicate with the Timestamping Authority process. When this, or other failures, happen, there is no easy way to detect it automatically, at the time of the failure (see bug 321795). Such failures might just miss one jar out of hundreds, or might cause a whole set of jars to go unsigned. So, the point is, build distributions should ALWAYS be checked to make sure all jars are signed as expected, before being the jars are distributed (especially for releases, but even milestones and weekly builds, if expected to be picked up by others). While release engineers can write scripts or Java code to automate the checking, in its simplest form, it can be done by simply calling 'jarsigner' with the -verify option, such as

 ${JAVA_HOME}/bin/jarsigner -verify ${pathAndNameOfJarFile}

This prints out a short message, such as "verified" or "No signature found in MANIFEST.MF" or similar.

[edit] Verification

[edit] When does verification happen?

Verification can happen any time. The common times to perform verification are:

  • During update. Minimally, verification happens at the time the client obtains the signed content. The Eclipse update mechanism will perform verification of any update JARs that are signed, and will prompt the user for confirmation if the certificate used for signing is not trusted.
  • At load-time. It is sometimes desirable to perform verification at load time when classes are loaded from a JAR. The default Java class loader performs this verification automatically for any signed JAR on the classpath. The Eclipse class loader can also be configured to perform load-time verification, but it is optional.
  • Manual user verification. The Eclipse about dialog will be augmented to show what plugins are signed. From this dialog the user should be able to manually perform verification of signed content if desired.

[edit] Miscellaneous links

[edit] Eclipse Bugzilla reports

Done Description
Don't resign bundles that have already been signed by eclipse.org cert
OSGi Bundle signing bug report
Check.gif Runtime signing support
Check.gif Signing indicator in About dialog
Check.gif Purchasing signing certificates
Check.gif Signing script to signal completion
Check.gif Starting signing immediately after signing script is called
Check.gif Bug for installing Java 1.5 on signing server
Check.gif Bug for installing Improved signing/packing application on signing server
Check.gif Bug for using OSGi verification during update
Check.gif Bug for using Timestamp Authority in signatures

[edit] Other signing links