Monday Nov 11, 2013

Self-signed certificates for a known community

Recently announced changes scheduled for Java 7 update 51 (January 2014) have established that the default security slider will require code signatures and the Permissions Manifest attribute. Code signatures are a common practice recommended in the industry because they help determine that the code your computer will run is the same code that the publisher created.

This post is written to help users that need to use self-signed certificates without involving a public Certificate Authority.

The role of self-signed certificates within a known community

You may still use self-signed certificates within a known community. The difference between self-signed and purchased-from-CA is that your users must import your self-signed certificate to indicate that it is valid, whereas Certificate Authorities are already trusted by default.

This works for known communities where people will trust that my certificate is mine, but does not scale widely where I cannot actually contact or know the systems that will need to trust my certificate. Public Certificate Authorities are widely trusted already because they abide by many different requirements and frequent checks.

An example would be students in a university class sharing their public certificates on a mailing list or web page, employees publishing on the intranet, or a system administrator rolling certificates out to end-users. Managed machines help this because you can automate the rollout, but they are not required -- the major point simply that people will trust and import your certificate.

How to distribute self-signed certificates for a known community

There are several steps required to distribute a self-signed certificate to users so that they will properly trust it. These steps are:

  1. Creating a public/private key pair for signing.
  2. Exporting your public certificate for others
  3. Importing your certificate onto machines that should trust you
  4. Verify work on a different machine

Creating a public/private key pair for signing

Having a public/private key pair will give you the ability both to sign items yourself and issue a Certificate Signing Request (CSR) to a certificate authority.

Create your public/private key pair by following the instructions for creating key pairs.
Every Certificate Authority that I looked at provided similar instructions, but for the sake of cohesiveness I will include the commands that I used here:

  1. Generate the key pair.
    keytool -genkeypair -alias erikcostlow -keyalg EC -keysize 571 -validity 730 -keystore javakeystore_keepsecret.jks
    • Provide a good password for this file.
    • The alias "erikcostlow" is my name and therefore easy to remember. Substitute your name of something like "mykey."
    • The sigalg of EC (Elliptical Curve) and keysize of 571 will give your key a good strong lifetime.
    • All keys are set to expire. Two years or 730 days is a reasonable compromise between not-long-enough and too-long. Most public Certificate Authorities will sign something for one to five years.
    • You will be placing your keys in javakeystore_keepsecret.jks -- this file will contain private keys and therefore should not be shared. If someone else gets these private keys, they can impersonate your signature. Please be cautious about automated cloud backup systems and private key stores.
  2. Answer all the questions. It is important to provide good answers because you will stick with them for the "-validity" days that you specified above.
    What is your first and last name?
      [Unknown]:  First Last
    What is the name of your organizational unit?
      [Unknown]:  Line of Business
    What is the name of your organization?
      [Unknown]:  MyCompany
    What is the name of your City or Locality?
      [Unknown]:  City Name
    What is the name of your State or Province?
      [Unknown]:  CA
    What is the two-letter country code for this unit?
      [Unknown]:  US
    Is CN=First Last, OU=Line of Business, O=MyCompany, L=City, ST=CA, C=US correct?
      [no]:  yes
    Enter key password for <erikcostlow>
            (RETURN if same as keystore password):
  3. Verify your work:
    keytool -list -keystore javakeystore_keepsecret.jks
    You should see your new key pair.

Exporting your public certificate for others

Public Key Infrastructure relies on two simple concepts: the public key may be made public and the private key must be private. By exporting your public certificate, you are able to share it with others who can then import the certificate to trust you.

keytool -exportcert -keystore javakeystore_keepsecret.jks -alias erikcostlow -file erikcostlow.cer

To verify this, you can open the .cer file by double-clicking it on most operating systems. It should show the information that you entered during the creation prompts.

This is the file that you will share with others. They will use this certificate to prove that artifacts signed by this certificate came from you. If you do not manage machines directly, place the certificate file on an area that people within the known community should trust, such as an intranet page.

Import the certificate onto machines that should trust you

In order to trust the certificate, people within your known network must import your certificate into their keystores. The first step is to verify that the certificate is actually yours, which can be done through any band: email, phone, in-person, etc. Known networks can usually do this

Determine the right keystore:

  • For an individual user looking to trust another, the correct file is within that user’s directory.
    e.g. USER_HOME\AppData\LocalLow\Sun\Java\Deployment\security\trusted.certs
    The default password for trusted.certs is an empty string.
  • For system-wide installations, Java’s Certificate Authorities are in JAVA_HOME
    e.g. C:\Program Files\Java\jre8\lib\security\cacerts
    The default password for cacerts is "changeit" as described in the keytool documentation.

File paths for Mac and Linux are included in the link above.

Follow the instructions to import the certificate into the keystore.

keytool -importcert -keystore THEKEYSTOREFROMABOVE -alias erikcostlow -file erikcostlow.cer

In this case, I am still using my name for the alias because it’s easy for me to remember. You may also use an alias of your company name.

Scaling distribution of the import

The easiest way to apply your certificate across many machines is to just push the .certs or cacerts file onto them. When doing this, watch out for any changes that people would have made to this file on their machines.

Trusted.certs: When publishing into user directories, your file will overwrite any keys that the user has added since last update.

CACerts: It is best to re-run the import command with each installation rather than just overwriting the file. If you just keep the same cacerts file between upgrades, you will overwrite any CAs that have been added or removed. By re-importing, you stay up to date with changes.

There is a -storepass argument for specifying the password on the command-line. On secure systems, admins typically hide passwords through redirection operators but that's outside the scope of this post.

Verify work on a different machine

Verification is a way of checking on the client machine to ensure that it properly trusts signed artifacts after you have added your signing certificate. Many people have started using deployment rule sets. You can validate the deployment rule set by:

  1. Create and sign the deployment rule set on the computer that holds the private key.
  2. Copy the deployment rule set on to the different machine where you have imported the signing certificate.
  3. Verify that the Java Control Panel’s security tab shows your deployment rule set.

Verifying an individual JAR file or multiple JAR files

You can test a certificate chain by using the jarsigner command.

jarsigner -verify filename.jar

If the output does not say "jar verified" then run the following command to see why:

jarsigner -verify -verbose -certs filename.jar

Check the output for the term “CertPath not validated.”

Thursday Oct 10, 2013

Signing code for the long-haul

With recent code-signature requirements for Rich Internet Applications, I have received a few good questions from different types of developers

  • What is the role of code signing?
  • How do I prevent my signature from expiring? 

What is the role of code signing?

Code signatures allow people who will receive and use your code to determine that you are, in fact, the publisher and that no one else has intentionally or accidentally modified your deliverable. Code signatures protect against these modifications within your supply chain, when moving across a network, or when appearing through 3rd party distribution channels. Code signatures offer a level of repudiation: even though an imposter tries to look like your app, both you and your customers can prove that it isn’t.

There are two concepts for this level of trust:

  1. Identity, the application providing a claim as to who wrote it.
  2. Authentication, the JRE automatically validating this claim against a set of known trust stores.

The way that this information is provided and checked is through industry standard Certificates, which tie together information about the signers (their identity) with the ability to mathematically verify it (through a key).

For a description on why code signatures are taking a more prominent role within the Java Platform, please see our previous entry, Code Signing – Understanding Who and When.

How do I prevent my signature from expiring?

Trusted Timestamping, introduced in Java 5 (2004), allows your customers to validate your signature even after the certificate has expired. When you sign a JAR file, the Timestamp Authority uses their clock to act as a notary and cryptographically write the date and time into your file.

Without this timestamp, users would only be able to validate your signature based on their current date and time. This could be problematic for long-running or embedded systems because the standard X.509 Certificates contain a NotAfter date that typically ranges from one to four years.

You interact with timestamp authorities when signing code with jarsigner’s TSA argument:

jarsigner -tsa http://timestamp.verisign.com …

When your signed file provides a timestamp, Java is able to use that information within the PKIXParameters and determine:

  1. Do I trust this timestamp authority to act as a notary?
  2. Is the signature date before the certificate’s time of expiration?
  3. Based on Certificate Revocation Lists, was this certificate valid on or before the signature date?

If the answer to all questions is yes, then the signature is deemed valid even if the certificate has expired. Therefore, signed code on embedded devices will continue to operate beyond the Certificate’s lifetime.

Several trusted timestamp authorities are listed in the previous post, “Code signing: Understanding who and when.”

A note about Certificate Authorities and revocation lists

Part of the acceptance criteria for being included in Java’s root certificate authority program is allowing back-dating of certificate revocation in the event that a private key is lost or stolen and continuing to publish revocation information even after a Certificate’s public expiration.

Tuesday Sep 17, 2013

Signing applet code does not grant all-permissions (since 7u25)

There are two levels of authorization for Java applets and web start applications: sandboxed, where the application is limited in terms of actions it can take on users' computers, and all-permissions, where applications operate as though they were native, with full access to the system and its resources.

In the old days of Java 6 and early days of Java 7, the rule was that only applications that required all-permissions needed to be signed. Since Java 7 update 21 (April 2013), you are able to (and encouraged) to sign all types of applications: sandbox and all-permissions. The intent of this is that code signatures from trusted certificate authorities provide a means of authentication for end users, so that they can know who actually wrote the application.

Java 7 update 25 also introduced two new attributes within a jar's Manifest file aimed at Preventing RIAs from Being Repurposed. By having these attributes within the signed jar, attackers cannot make any adjustments to the permissions level without invalidating the signature. An example of the META-INF/MANIFEST.MF file with these attributes would be:

Manifest-Version: 1.0
Created-By: 1.7.0_25
Permissions: sandbox
Codebase: https://example.com

Name: Clazz.class SHA1-Digest: HASHSTUFF=

Beginning January 2014, code signatures and use of the Permissions attribute will be mandatory for all Applets and Web Start applications. The Codebase attribute will remain optional, as ISVs may not know this information beforehand.

These changes create a separation between three areas of trust:

  1. Identification: provided by the application, stating its publisher.
  2. Authentication: automatic by the JRE, the code signatures within JARs is verified against public certificate authorities and dynamically updated revocation lists.
  3. Authorization: once authentication has occurred, allow the application to ask the user for a specific set of permissions.

For additional information about the role of code signatures, sandboxed or not, see our previous blog entry, Code signing: Understanding who and when.

Tuesday Sep 03, 2013

Code signing: Understanding who and when

Code signatures have become more commonplace for applications in recent years and especially so in Java 7 update 21 (April 16, 2013). The security notifications for Java help provide your users with an understanding of who wrote the application so that they can decide whether to run it or not. Through the default settings of the Java security slider, end-users are blocked from running unsigned or self-signed applets and prompted for running signed applets.

These cryptographic signatures are designed to provide a means of authentication, proving to users that they are indeed running the same application that you wrote and that it has not been modified in any way. Within information security threat modeling terms, this is a means of repudiation.

Developers must sign any browser applet or Web Start application that they produce. Signatures on other application types (such as back-end server applications) are optional.

System Administrators may be impacted and have a choice for what to do:

  1. For managed users, the system administrator can add a Deployment Rule Set to client systems and indicate which applets may run.
  2. For unmanaged or bring-your-own-device users, the system administrator may sign jars with their own certificate.

Several steps are involved to sign code:

  1. Determine who in your organization is responsible for code signing
  2. Purchase a signing certificate from a public Certificate Authority.
  3. System Administrators: sign a jar using normal commands
  4. Developers: integrate code signing into your build chain

Determine who in your organization is responsible for code signing

In corporate enterprises, there is often a technology group responsible for these signatures. This group is usually separate from most system administrators in order to keep the private key a secret. The goal is to decrease the number of people with access to the private key.

If you are in a corporate enterprise, please look internally for a code signing group and ask them for their signing process instead.

Purchase a signing certificate

If you or your group is identified as responsible for code signing, then the next step is to obtain a code signing certificate. If a different group provides signatures (as in many large organizations), follow their process instead.

All users (system administrators and developers) that intend to sign code must purchase a signing certificate from a known authority. Certificate authorities help manage trust across millions of systems and prevent identity spoofing, or cases where someone else generates their own certificate pretending to be you. Signing certificates are available from companies like GoDaddy, Symantec, or others. Each certificate authority provides instructions for generating a certificate signing request with the keytool command.

Code signing certificates are different from domain certificates normally used for HTTPS websites. Signing certificates must be purchased from a Certificate Authority -- Oracle is not a Certificate Authority.

System Administrators: sign a jar using normal commands

After receiving the signing certificate, system administrators can sign files using the following jarsigner command:

jarsigner -verbose -keystore "c:\Users\ecostlow\javakeystore_keepsecret.jks" -tsa http://timestamp.verisign.com -signedjar FILENAME.jar FILENAME.jar your-certificate-name
Enter Passphrase for keystore:
 updating: META-INF/MANIFEST.MF
   adding: META-INF/COSTLOW.SF
   adding: META-INF/COSTLOW.RSA
  signing: ruleset.xml

Developers: integrate code signing into your build chain

In an ideal environment, members of the development team would not have access to the private key and its password. The fewer people that have this private key, the better.

For build automation, you can create stubs that allow other members of the team to substitute the real private key and password, without exposing this sensitive information.

Please note that Oracle only maintains the default jarsigner command (described above for System Administrators) and does not manage or control build tools.

Ant

The ant build system provides a SignJar task to mimic the jarsigner command. When using this task, just be sure to call the ant sign target.

<property file="devAndBuildHaveDifferentValues.properties" />
<target name="sign">
	<signjar
		alias="${sign.alias}" keystore="${sign.keystore}"
		storepass="${sign.storepass}" tsaurl="http://timestamp.verisign.com">
	  <path>
		<fileset dir="dist" includes="**/*.jar" />
	  </path>
	</signjar>
</target>

Then, both the development team and build team would have different entries for devAndBuildHaveDifferentValues.properties

 Dev would have this for testing
Build (continuous integration) would have this, keeping it secret
sign.alias=mykey
sign.keystore=testcerts.jks
sign.storepass=changeit
sign.alias=mykey
sign.keystore=/build/keepSecretFromEveryone.jks
sign.storepass=N0bodyE1se5houldKnowThis

By taking these actions, developers can automate their build to sign jar files without exposing the private key to the entire development team.

Maven

Maven provides a maven-jarsigner plugin to mimic the jarsigner command.

<build>
	<plugins>
		...
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-jarsigner-plugin</artifactId>
			<version>1.2</version>
			<executions>
				<execution>
					<id>sign</id>
					<goals>
						<goal>sign</goal>
					</goals>
				</execution>
			</executions>
			<configuration>
				<keystore>${sign.keystore}</keystore>
				<alias>${sign.alias}</alias>
				<storepass>${sign.storepass}</storepass>
			</configuration>
		</plugin>
		...
	</plugins>
</build>

Maven uses the idea of Profiles to externalize properties.

Dev would have this for testing
Build (continuous integration) would have this, keeping it secret
sign.alias=mykey
sign.keystore=testcerts.jks
sign.storepass=changeit
sign.alias=mykey
sign.keystore=c:/build/keepSecretFromEveryone.jks
sign.storepass=N0bodyE1se5houldKnowThis

By taking these actions, developers can automate their build to sign jar files without exposing the private key to the entire development team.

Other build system

If your development team is using an alternate build system, please review its documentation for the appropriate call. Most build systems should have this, but the default jarsigner command will always work if you need.

Leveraging internal code signing authorities

Many large organizations have an internal code signing group. The benefit of these groups is that they help keep the private keys secret in a way that neither developers nor build integrators have access. Separation also allows this group to dedicate more time towards best practices, like keeping keys on tamper-proof hardware/smart-cards. If your organization has this group, the usual practice is to automate sending code artifacts to this team’s service and retrieving the resulting signed artifacts. Reference documentation for using separate hardware key components is available in the PKCS#11 Reference Guide.

A word on timestamps

The optional timestamping provides a notary-like capability of identifying when the signature was applied. This is helpful if your private key is compromised at any point. If a jar was signed before the key was thought to be compromised, the signature is still valid even through the certificate may be revoked. Certificate Authorities should allow back-dating of revocations in case the loss is not noticed right away. If a certificate is revoked and the signed jar is:

  • Timestamped before the stated date of compromise: then the signature is valid because the owner still had sole possession.
  • Timestamped on or after the stated date of compromise: the signature is not valid. Whoever else had the certificate could have faked this.
  • Not timestamped: the signature is not valid. We have no way of knowing when the jar was signed and assume it was after the compromise.

Although not required, it is a good practice to timestamp anything that you sign. Popular timestamping authority URLs include:

  • http://timestamp.verisign.com
  • http://tsa.starfieldtech.com
  • https://timestamp.geotrust.com/tsa
About

Science Duke
This blog contains topics related to Java SE, Java Security and Usability. The target audience is developers, sysadmins and architects that build, deploy and manage Java applications. Contributions come from the Java SE Product Management team.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
2
3
4
5
6
8
9
10
11
12
13
14
15
16
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today