Java and security bits

Sunday Apr 23, 2006

Elliptic Curve Cryptography in Java

The latest Mustang build 81 available on java.net includes support for an interesting new technology: Elliptic Curve Cryptography (ECC).

Basically, ECC refers to a set of public key cryptosystems. This includes the ECDSA and ECDH algorithms, which are elliptic curve equivalents of DSA and DH. What makes ECC interesting is that it provides the same level of security with much shorter key sizes. For example, a 163 bit ECDSA key is considered to be as strong as a 1024 bit DSA or RSA key. This means memory and bandwidth savings (particularly useful for tiny devices). It also means better performance. Not so much when comparing with 1024 RSA/DSA keys, but the difference becomes very pronounced when moving to the next security level with 2048 bit RSA keys and 233 bit ECC keys (see slide 3 in this presentation). This is relevant because many believe that by 2010 we will need to move to such a longer key size. Finally, ECC is also interesting because it is mandated by some government standards. For more in depth information about ECC, see the SunLabs page or Wikipedia.

For all these reasons, Sun has been a advocate of ECC technology for some time with code contributions to OpenSSL and NSS and more recently an announcement of broad support for ECC in various products. The interesting thing that has happened over the last year is that a number of other companies have also become more interested in ECC. That has lead to the formation of an ad-hoc ECC TLS interoperability forum. This will make sure that all the various ECC enabled products, including Java SE, are able to interoperate.

Getting back to Mustang, what is available now is ECC support in the SunJSSE and SunPKCS11 providers, see bug 6405536. This means that the SunPKCS11 provider now exposes ECDSA Signature, ECDH KeyAgreement, and EC KeyPairGenerator algorithms, if the underlying PKCS#11 token supports them. The SunJSSE provider now supports all the elliptic curve ciphersuites defined in the latest IETF draft, if EC crypto is available from a Java crypto provider such as SunPKCS11. Note that we had some elliptic curve APIs (in the interfaces and spec packages) since JDK 5.0, but they were not used by any part of the JDK itself until now. Also note that although EC is supported by SunPKCS11 and SunJSSE now, we do not have a pure Java ECC implementation yet. That is planned for a future release.

This means that in order to use ECC in Mustang now, you can do something like this:

  1. get an ECC enabled PKCS#11 library

  2. configure the JDK to use it

  3. done

Currently, the only ECC enabled PKCS#11 implementation that I am aware of are the latest builds of NSS. Until NSS 3.11.1 is released, you can use these Windows test binaries of NSS and NSPR posted here. On other platforms, compile NSS yourself following these instructions.

Specifically, assuming you are running Windows, follow the instructions below. They may seem familiar given my recent Java and NSS blog. I am sure Solaris and Linux are able to transpose the instructions for their OS.

  1. create a directory for the NSS libraries, say d:\nss and unpack the NSS and NSPR libraries referenced above into that directory. There should be 9 DLL and 2 CHK files in that directory.

  2. create a directory for your other test files, say d:\ecctest. Create a SunPKCS11 configuration file called nss.cfg in that directory with the contents

    name = NSS
    nssLibraryDirectory = d:\\nss
    nssDbMode = noDb
    attributes = compatibility
    
  3. download the latest Mustang build from java.net and unpack it, say into d:\jdk6.

  4. go into the directory D:\jdk6\jre\lib\security and edit the file java.security. Add the line

    security.provider.10=sun.security.pkcs11.SunPKCS11 d:\\ecctest\\nss.cfg
    

    to the section listing the security providers.

  5. open a command prompt and go to the d:\ecctest directory. Add the JDK and NSS directories to your path using

    set PATH=D:\jdk6\bin;D:\nss;%PATH%

    The NSS directory needs to be in the path to keep the Windows dynamic linker happy. On Solaris and Linux, you may have to set LD_LIBRARY_PATH to the NSS directory.

That's it! You can now use ECC from Java. This can be verified by running commands such as keytool:

D:\ecctest>keytool -genkeypair -keyalg EC -keysize 256 -keystore ectest.jks -storepass test12 -dname "CN=ECC Test"
Enter key password for 
        (RETURN if same as keystore password):

D:\ecctest>keytool -list -v -keystore ectest.jks -storepass test12

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: mykey
Creation date: Apr 23, 2006
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=ECC Test
Issuer: CN=ECC Test
Serial number: 444c296f
Valid from: Sun Apr 23 18:27:11 PDT 2006 until: Sat Jul 22 18:27:11 PDT 2006
Certificate fingerprints:
         MD5:  48:48:DF:DF:F2:A9:74:D2:83:43:1F:9A:FD:05:3A:A2
         SHA1: 85:D7:0E:33:92:84:A1:38:3E:1E:2D:DF:C8:21:0D:D6:98:06:29:82
         Signature algorithm name: SHA1withECDSA
         Version: 3

Or start a program that uses JSSE. The ECC ciphersuites are enabled automatically if the necessary EC crypto algorithms are available. TLS test clients and servers are listed on the interop page and a JSSE based test server is running on that server as well.

More details about the supported features:

SunPKCS11

  • SHA1withECDSA and NONEwithECDSA Signatures, ECDH KeyAgreement, EC KeyPairGenerator, EC KeyFactory

  • Named prime and binary polynomial curves defined by NIST, SECG, and ANSI X9.62. Uncompressed points. No support for explicitly encoded curves or compressed points.

SunJSSE

  • All EC ciphersuites defined in the latest IETF TLS draft.

  • All named curves defined in the latest draft.

  • ECDSA_sign client authentication usable with both ECC and traditional RSA/DSA/DH ciphersuites.

  • Curve and point format negotiation using the extensions Supported Elliptic Curves and Supported Point Formats.

  • No support for point compression, explicitly encoded curves, or client authentication using ECDSA_fixed_ECDH or RSA_fixed_ECDH.

The source for the SunPKCS11 changes is also available from the Mustang download page, for b81 the direct link is this file. See the directories j2se/src/share/classes/sun/security/ec and j2se/src/share/classes/sun/security/pkcs11. Some additional work will follow soon as part of bug 6414980.

Finally, I want to acknowledge a few people that helped get this project into Mustang on time by answering questions and by quickly resolving NSS issues that impacted Java: Vipul Gupta from SunLabs, Nelson Bolyard from the Sun NSS team, and Bob Relyea and Wan-Teh Chang from the Red Hat NSS team.

Update:
I should mention that there is no code in the SunJSSE provider that is specific to SunPKCS11. It should work with any Java crypto provider that implements ECC. What SunJSSE requires is a crypto provider that:

  • implements ECC as defined by the classes and interfaces in the packages java.security.spec and java.security.interfaces. The getAlgorithm() method of elliptic curve key objects must return the String "EC"

  • supports the Signature algorithms SHA1withECDSA and NONEwithECDSA, the KeyAgreement algorithm ECDH, and a KeyPairGenerator and a KeyFactory for algorithm EC. If one of these algorithms is missing, SunJSSE will not allow EC ciphersuites to be used.

  • the crypto provider should support all the SECG curves defined in the TLS ECC specification, section 5.1.1 (see also appendix A). In certificates, points should be encoded using the uncompressed form and curves should be encoded using the namedCurve choice, i.e. using an object identifier. If these requirements are not met, EC ciphersuites may not be negotiated correctly.

I am aware that the BouncyCastle crypto provider includes some ECC support, but I am not sure it meets the requirements spelled out above. Testing it with SunJSSE is on my todo list.

Wednesday Apr 12, 2006

Hashing a file in 3 lines

As I was working on a Peabody contribution recently, I remembered a short program I wrote a couple of years ago. It shows that you can calculate the message digest of a file in 3 lines of code. Of course, I had since lost the program, so I started over:

import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import static java.nio.channels.FileChannel.MapMode.READ_ONLY;
import java.math.BigInteger;
import java.util.*;
import java.security.MessageDigest;

public class Digest {

    public static void main(String[] args) throws Exception {
        if (args.length != 1) {
            System.out.println("Usage: java Digest <file>");
            return;
        }
        FileChannel channel = new RandomAccessFile(args[0], "r").getChannel();
        ByteBuffer buffer = channel.map(READ_ONLY, 0, (int)channel.size());
        digest("md5", buffer);
        digest("sha1", buffer);
        channel.close();
    }

    private static void digest(String algorithm, ByteBuffer buffer) throws Exception {
        MessageDigest md = MessageDigest.getInstance(algorithm);
        md.update(buffer.duplicate());
        byte[] digest = md.digest();
        new Formatter(System.out).format
                ("%-5s: %0" + (digest.length * 2) + "x%n",
                algorithm, new BigInteger(1, digest));
    }
}

Obviously, this is more than three lines, but the actual digesting is only three lines: getting the MessageDigest object [MessageDigest.getInstance()] hashing the file [md.update(ByteBuffer)] and getting the result [md.digest()].

The methods that take ByteBuffers were added to MessageDigest, Signature, and Cipher in JDK 5.0. They were designed for scalable network I/O using channels and securing them via an SSLEngine, but they work just as well for memory mapped files or just plain byte arrays. FWIW, I think ByteBuffers are underrated. They are to byte arrays as Collections are to Object arrays: more powerful and easier to use. But I disgress.

PS: I think it is also pretty clear that this program is not the smartest way to digest a file using multiple algorithms. Apart from the fact that it does not work for files larger than 2G at all (the limit for ByteBuffers), it also processes the entire file first using MD5 and then again using SHA1. That should really be done in chunks to take advantage of the OS page cache, but if I did all that I could not claim that I hashed the file using three lines of code ;-)

Thursday Feb 16, 2006

The Java PKCS#11 Provider and NSS

Mustang beta has just been released. Read all about it in Mark's blog and if you have not been running the snapshots, you should definitely download and try out the beta. But you knew all that already, so let's get to the point.

Last time I wrote about the dramatic crypto performance gains you can achieve just by running your existing Java applications on UltraSPARC-T1 based servers. You'll also see a very noticeable improvement on any other Solaris 10 systems thanks to the Solaris Cryptographic Framework.

But what about all those people not (yet?) on Solaris 10? The good news is that because Java utilizes the PKCS#11 standard, users that run Linux and Windows can see performance improvements, too. It is not out-of-the-box as on Solaris 10, but all you have to do is configure Java to utilize an optimized PKCS#11 crypto module, such as NSS.

NSS is an open source C based security library that is used in all products derived from the former Netscape product line. In other words, the Mozilla/Firefox browsers, the Sun Java Enterprise System server software, and more. To download the source or binaries, read this page first and then go to the FTP server. You will also need their platform layer, which is called NSPR and available here.

Still with me? Good. The crypto modules in NSS are based on PKCS#11, but with a few quirks. In Mustang, we have made it easier to access NSS. Now all you have to do is create a config file like this one:

name = NSS
nssLibraryDirectory = /opt/tests/nss/lib
nssDbMode = noDb
attributes = compatibility

Where /opt/tests/nss/lib is the directory in which you placed all the NSS and NSPR library files. Depending on your platform, you may also have to set your LD_LIBRARY_PATH or your Windows PATH to include this directory. Finally, configure your program to use NSS via the SunPKCS11 provider:

import java.security.*;

// your code here

// program startup code
Provider nss = new sun.security.pkcs11.SunPKCS11(configFileName);
Security.insertProviderAt(nss, 1);

// your other code here

Pretty neat. But there is more to PKCS#11 than just performance.

A second reason to use the SunPKCS11 provider is that it allows you to utilize crypto implementations that can be considered more secure, either because they employ tamper resistant hardware (e.g. Smart Cards) or because they have been through security certification program (such as FIPS 140). Some products are all this and very fast as well, see the Sun Crypto Accelerator 4000 or the just announced SCA 6000.

But what if you need security certification but don't want to spend money on a hardware security module? In that case, we are back at NSS. It is currently going through FIPS 140 validation, and of course you can also access NSS in FIPS mode from Java. It really gets interesting when you combine that with the experimental FIPS mode in the SunJSSE provider. This combination is intended to give you a FIPS 140 compliant TLS solution in Java. Which will be free, and available on Solaris, Linux, and Windows.

It works something like this. Create another configuration file for the PKCS#11 provider:

name = NSSfips
nssLibraryDirectory = /opt/tests/nss/lib
nssSecmodDirectory = /opt/tests/nss/fipsdb
nssModule = fips

Where the fipsdb contains the NSS secmod.db, which has been configured in FIPS mode, and the key and cert db files. See the NSS documentation for more information. Then have your Java program do this at startup:

Provider nss = new sun.security.pkcs11.SunPKCS11(fipsConfigFileName);
Security.addProvider(nss);

Security.removeProvider("SunJSSE");
Provider jsse = new com.sun.net.ssl.internal.ssl.Provider(nss);
Security.addProvider(jsse);

KeyStore ks = KeyStore.getInstance("PKCS11", nss);
ks.load(null, myNssPassphrase);
// next configure JSSE to use 'ks' as the KeyStore
// for its KeyManager

Not bad. But there is more to the SunPKCS11 provider ;-)

A third way in which PKCS#11 could come in handy is to allow Java applications to employ cryptographic algorithms for which we don't have a pure Java implementation yet. We don't do that currently, but this could change soon. If you have been following the news, it should not be hard to guess and - would you believe it - could even involve NSS yet again.

But that is another story. Watch this space.

Wednesday Dec 07, 2005

Crypto acceleration included

Today Sun announced two truly terrific servers, the Sun Fire T2000 and the T1000. For many workloads, they are simply the fastest 2RU/1RU machines on the planet. Just check out the benchmarks. Plus, they are cheaper than the competition and use very little power. Lot's to read about it in various blogs. I could go on, but I don't want to sound like a marketing droid.

The reason I am writing about these systems is that the processor they incorporate has another interesting feature. The UltraSPARC T1 processor, maybe better known under its Niagara codename, has crypto acceleration built in. In particular, each core also incorporates a dedicated crypto unit.

This means that those RSA operations that used be rather slow suddenly become really fast. How fast? Let's say more than 10000 RSA private key operations per second for 1024-bit keys. This is far more than other processors and even more than dedicated PCI crypto acceleration cards. Not only that, but the CPU cores can continue to execute application code while the crypto unit performs the RSA operation.

So far so good, but how do you take advantage of that feature in your Java apps? The answer is just run your existing Java 5 application! It will benefit immediately. No code changes required. No configuration changes. It simply works.

Under the covers, the extensible Java Cryptography Architecture combined with the PKCS#11 work in JDK 5.0 and the Solaris Cryptographic Framework make it happen. All you need is a JDK 5.0 runtime. As always, for best results we recommend that you run the latest update release.

So go ahead and secure your web pages with HTTPS, digitally sign your SOAP messages, or try something creative. If you run a T2000 or a T1000 server, performance will not be an issue.

PS: I find it reassuring that Sun's competitors immediately went into FUD mode claiming that the T1 processor is a niche chip that is not relevant for real applications. If such transparent nonsense that can easily be proven wrong by just looking at public benchmark results is the best they can do, they don't stand a chance.

PPS: full Verilog design for a state of the art microprocessor available under an open source license, how cool is that?

Friday Dec 02, 2005

JSSE now fully pluggable

J2SE 5.0 Update 6 was just released yesterday. One change I want to highlight is that the JSSE framework is now fully pluggable. This means you can use any 3rd party JSSE provider you wish. No restrictions on the ciphersuites that may be used. No code signing required from the developers that implement a JSSE provider.

So what does this mean for you? Ideally, nothing at all. I say that because I hope you are happy with the SunJSSE provider included in the Sun JDK and that you will just keep using it. But if you do not like SunJSSE, you can choose another provider. Or write your own, it's your choice. And choice is good.

So go ahead and download 5.0u6 or a Mustang build and play. Note the pluggability restrictions were also removed from Mustang a little while ago.

BTW, if you don't like SunJSSE, let us know why so we can fix it. Report a bug, contact the Java security feedback alias or email me directly and share your pain.

For those of you that care, let me explain a bit of the legal background. DISCLAIMER: I am not a lawyer. The following is not legal advice, only my limited understanding of the export control rules as they affect JSSE.

The U.S. government (and many other governments) is concerned that cryptography could be misused by criminals, so it imposes certain restriction on encryption software and hardware that is exported from the U.S. Although those constraints are far less severe than they used to be years ago and from a consumer perspective have all but disappeared, they still cause a bit of trouble for companies like Sun. Apart from lots of paperwork, one big issue that remains is open cryptographic interfaces. In other words, pluggable systems like JCE or JSSE. Unlimited pluggability is generally not approved.

That is why at one point we had two versions of JSSE: a domestic version that allowed 3rd party providers and an international one that did not. That was back when JSSE 1.0.x was an optional package for JDK 1.2 and 1.3. When JSSE became part of the core platform in JDK 1.4, maintaining two versions became impractical and we instead only shipped the non-pluggable international version.

Of course we wanted a better solution, and it finally arrived in JDK 5.0. We received approval from the government to allow 3rd party JSSE providers as long as they only supported the ciphersuites on a predefined list. That list includes all currently standardized ciphersuites, so it is a pretty good solution.

Still, the fact that there is any limitation at all was a little annoying. So we tried again and after a some back and forth we received approval to remove that restriction and allow any 3rd party JSSE provider without constraints. This probably does not sound like a bit achievement but it has been a long journey and I am glad it is over now.

Friday Oct 01, 2004

First (semi-real) post

OK, so here I am. Not that I have anything interesting to write about right now. For the future, my plan is to post little tidbits, debugging tips, and information about things I am currently working on. I hope that will be useful to a few of you.

One event that I obviously need to mention is the Tiger launch (go here for download). While this is certainly very cool, it actually affects me very little. For the past several months the release has been in the hands of the testing organization. They made sure that all the new stuff works, all the old stuff still works, and if not, they light a few fires under somebody's, aehm, chair.

Anyway, that's all for now. I hope to have something more exciting soon.

PS: if there is anything in particular that you are interested in, post a comment.

Calendar

Feeds

Links

Recent Posts

Referers