Thursday Dec 11, 2014

That's so SecureRandom

Random numbers are an important part of software systems, especially those that deal with security or encryption. The Java platform offers different types of randomness based on intent, and static typing can further guide that choice for library developers.

This post is intended to explain how the Oracle JDK provides random numbers, to guide their usage:

  • Developers building Java software, to use the right randomness in the right place.
  • Companies buying or running Java software to understand how to evaluate or control that software.
  • System Administrators tuning the security and performance of those systems, understanding why/where/how to make adjustments.

Randomness in the JDK

Java SE provides three mechanisms for generating random numbers based on their usage:

  1. A fast Random number designed for basic tasks where true randomness is not the main goal. This is useful for things like which shade of color to use, preventing overlap in force-directed layouts, or which picture to show from a list after evaluating demographic information.
  2. High-concurrency programs may also use ThreadLocalRandom if they value speed over true randomness. This is the same as above but will likely give better performance if simultaneous threads generate pseudo-random numbers at the same time.
  3. A slower but more random SecureRandom designed for important tasks where the inability to predict numbers is crucial to success. Examples include cases like gambling, scientific sampling, or any cryptographic operations. Although slower than the other two random number generators, its better randomness in many applications.

Having these choices allows developers to make the appropriate decision based on their application.

The Java Platform also allows software operators to override and control this behavior. For example improving true-ness of the Random generator or improving speed of SecureRandom with dedicated hardware.

Security through static typing

Java’s static typing can also enforce that program authors and library users apply the proper Random implementation. The random classes are designed with inheritance, allowing full interoperability across implementations. Both SecureRandom and ThreadLocalRandom inherit from Random, which means that implementations can be swapped or specified:

Random pseudoRandom = new Random();
Random pseudoRandomConcurrent = ThreadLocalRandom.current();
Random secureRandom = new SecureRandom();

For API design, developers can choose to only accept the appropriate version based on their use case. Given that true randomness is crucial to the success of cryptographic operations, it is critical that cryptographic APIs only accept SecureRandom arguments and never the super-class of Random. One example of this is KeyPairGenerator, which helps generate public/private keys that are used by many cryptographic systems. Users can only seed this with true-random values and not pseudo-random values.

KeyPairGenerator.initialize(int keysize, SecureRandom random);

Developers can only call this method by using statically-typed SecureRandom values. The super-type Random PRNG, which might make predictable keys, cannot work. Calling the overloaded KeyPairGenerator.initialize(int keysize) will also use a SecureRandom and is fine, the point here is that static typing prevents other types of Random from being used.

Using the previous example, one could call:

kpg.initialize(4096, (SecureRandom) secureRandom);

Or by specific static typing:

SecureRandom staticEnforcement = new SecureRandom();
kpg.initialize(4096, staticEnforcement);

API designers building secure systems should follow this example of statically typing SecureRandom in method signatures. When vetting secure software, look for usage of Random where a SecureRandom might be more appropriate. The US CERT Java coding guidelines offer additional guidance on evaluating the use of random numbers. Simon Kitching also has a good write-up about Using the SecureRandom Class.

Sources of Randomness

The sources for randomness are listed in the JDK’s security Standard Names documentation, identifying which are blocking or non-blocking. Although some sources rely on entropy pools, SecureRandoms like SHA1PRNG are quite fast once seeded and do not need additional entropy.

Blocking is especially important on Linux systems, where some calls to /dev/random may pause while the system generates a new true-random number. There is a trade-off /dev/urandom device that is non-blocking but somewhat less random.

Within a Java installation, the administrator can adjust various settings through the "JRE/lib/security/java.security" configuration file. That file contains documentation about configuring securerandom.source and securerandom.strongAlgorithms. On Linux systems, the administrator may set their securerandom.source to  /dev/random or /dev/urandom accordingly.

Each operating system contains its recommended default value. System Administrators may edit that value, for example if their system has different RNGs or if they have a separate specialized hardware RNG.

JavaMex has a page describing the sources of entropy that Java uses on different operating systems.

Additional information is available in the SecureRandom javadoc.

Wednesday Jul 02, 2014

Diagnosing TLS, SSL, and HTTPS

When building inter-connected applications, developers frequently interact with TLS-enabled protocols like HTTPS. With recent emphasis on encrypted communications, I will cover the way in which the JDK evolves regarding protocols, algorithms, and changes, as well as some advanced diagnostics to better understand TLS connections like HTTPS.

Most developers will not have to do this level of diagnosis in the process of writing or running applications. In the event that you do, the following information should provide enough information to understand what's happening within secure connections.

Stability: The evolution of protocols and algorithms

For the last 15 years (since 1998), the Java platform has evolved through the Java Community Process where companies, organizations, and dedicated individuals develop and vote on specifications to determine what makes up the Java Platform. Much of the efforts are centered on compatibility, like the TCK, ensuring that different implementations are compatible with each-other and that developers can predict how their applications will run. We are not changing critical default options (like TLS protocol) within minor versions.

The following chart depicts the protocols and algorithms supported in each JDK version:


JDK 8
(March 2014 to present)
JDK 7
(July 2011 to present)
JDK 6
(2006 to end of public updates 2013)
TLS Protocols
TLSv1.2 (default)
TLSv1.1
TLSv1
SSLv3
TLSv1.2
TLSv1.1
TLSv1 (default)
SSLv3


TLSv1 (default)
SSLv3
JSSE Ciphers:
Ciphers in JDK 8
Ciphers in JDK 7
Ciphers in JDK 6
Reference:
JDK 8 JSSE JDK 7 JSSE JDK 6 JSSE
Java Cryptography Extension, Unlimited Strength (explained later)
JCE for JDK 8 JCE for JDK 7 JCE for JDK 6

Sample Java code for making an HTTPS connection

Making an HTTPS connection in Java is relatively straight-forward. I will post the code here with the intent focused on tuning and understanding the underlying capabilities.

Sample back-end code for making an SSL connection:

final URL url = new URL("https://example.com");
try(final InputStream in = url.openStream()){
  //…
}

Or the connection can be tuned through a cast:

final HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
//operate on conn
conn.connect();
try(final InputStream in = conn.getInputStream()){
  //…
}

Example: Qualys SSL Labs' "View My Client" Page

Qualys SSL Labs maintains a collection of tools that are helpful in understanding SSL/TLS connections. One in particular is a View My Client page, which will display information about the client connection. By integrating with that page, I was able to control the implementation as I used different Java tuning parameters.

To test parameter tuning, I implemented a small JavaFX application in JavaScript. It displays that page in a WebView, showing information about the underlying Java SSL/TLS client connection. You can find the code in the appendix.

JSSE Tuning Parameters

When diagnosing TLS-related issues, there are a number of helpful system properties. They are generally covered in their relevant sections of JSSE but this single collection may help anyone looking to understand the flexibility of Java’s implementation or diagnose connection details.

javax.net.debug
 Prints debugging details for connections made.
Example: -Djavax.net.debug=all or -Djavax.net.debug=ssl:handshake:verbose
https.protocols

Controls the protocol version used by Java clients which obtain https connections through use of the HttpsURLConnection class or via URL.openStream() operations. For older versions, this can update the default in case your Java 7 client wants to use TLS 1.2 as its default.
Example: -Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2

For non-HTTP protocols, this can be controlled through the SocketFactory's SSLContext.

jdk.tls.client.protocols Introduced in JDK 8, this controls the underlying platform TLS implementation. Additional information is available in the JSSE Reference Guide.
Example: -Djdk.tls.client.protocols=TLSv1.1,TLSv1.2
http.agent
When initiating connections, Java will apply this as its user-agent string. Modifying this will handle cases where the receiving party responds differently based on the user-agent.
Example: -Dhttp.agent="known agent"
java.net.useSystemProxies
java.net.useSystemProxiesUse proxy details from the operating system itself.
Example: -Djava.net.useSystemProxies=true
http.proxyHost
http.proxyPort
The proxy connection to use for HTTP connections.
Example: -Dhttp.proxyHost=proxy.example.com -Dhttp.proxyPort=8080
https.proxyHost
https.proxyPort
The same as above, except that configuration is separate between HTTP and HTTPS.
http.proxyUser
http.proxyPassword
https.proxyUser
https.proxyPassword
Password-based credentials for the above proxies.

Many other protocols and properties can be found within the following areas:

Example of diagnosing a problem

When making an HTTPS connection, let’s assume that the client threw the following exception due to a failed handshake with the server:

 javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 

SSLHandshakeException is a subclass of the IOException, so you do not need to catch is explicitly. Most developers will not need an explicit catch, but it may help you more easily diagnose the cause of any IOException.

When applying the -Djavax.net.debug=all property from above, the failure associated with this SSLHandshakeException would appear immediately after algorithm negotiation in the logs.

 JDK 7 (fails on unsupported algorithm) JDK 8 (works fine)
Cipher Suites: […Long list of ciphers…]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {…}
Extension ec_point_formats, formats: [uncompressed]
Extension server_name, server_name: [host_name: HOST]
***
main, WRITE: TLSv1 Handshake, length = 168
main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT:  fatal, handshake_failure
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
Cipher Suites: […Long list of ciphers…]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {…}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: …
Extension server_name, server_name: [type=host_name (0), value=HOST]
***
main, WRITE: TLSv1.2 Handshake, length = 226
main, READ: TLSv1.2 Handshake, length = 89
*** ServerHello, TLSv1.2
RandomCookie:  GMT: -1809079139 bytes = { …}
Session ID:  {…}
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
Extension ec_point_formats, formats: [uncompressed, ansiX962_compressed_prime, ansiX962_compressed_char2]
***
%% Initialized:  [Session-1, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]
** TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
main, READ: TLSv1.2 Handshake, length = 2308

In the case above, the failure occurred during the handshake. The most likely cause for that is algorithm support. The JDK provides a separate package called JCE Unlimited Strength, designed to add stronger algorithm support than what’s available by default. Qualys SSL Labs provides a different server SSL test that will enumerate which algorithms a server supports.

Many TLS error messages are covered in a few pieces of documentation:

Adding stronger algorithms: JCE Unlimited Strength

In a high security environment, one way of strengthening algorithms in the JDK is through the JCE Unlimited Strength policy files. In this particular case, replacing those policy files within JDK 7 allows it to use the stronger variants of existing algorithms and connect successfully.

JCE Unlimited Strength downloads: JDK 8, JDK 7, or JDK 6.

Appendix

The following code will open Qualys SSL Labs’ View My Client page within a Java client. To test configurations, run this like:

jjs -fx viewmyclient.js
jjs -fx -Dhttps.protocols=TLSv1 viewmyclient.js

var Scene = javafx.scene.Scene;
var WebView = javafx.scene.web.WebView;
var browser = new WebView();
browser.getEngine().load("https://ssllabs.com/ssltest/viewMyClient.html");
$STAGE.scene = new Scene(browser);
$STAGE.show();

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.

  • If a certificate passes its natural expiration date without revocation, trust is extended for the length of the timestamp.
  • Timestamps are not considered for certificates that have been revoked, as the actual date of compromise could have been before the timestamp occurred.

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
« August 2015
SunMonTueWedThuFriSat
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
     
Today