Devices that communicate over an insecure network like the Internet need to prove their identity to each other, a process called authentication. This article describes techniques MIDP clients can use for authentication. The MIDP 1.0 provides no direct API support for authentication. MIDP 2.0 does support server authentication with HTTPS, but still lacks mechanisms for client authentication.
The most trustworthy methods of authentication are based on secrets, little pieces of information that are not widely known. A password is one example of a secret; a private cryptographic key is another. Presenting the password or proving that you possess a private key are two methods of authentication. In this article you'll read about these techniques and others, applied specifically in MIDP clients.
Two Kinds of Authentication
In network communications involving two devices, a client seeking a service initiates a connection, and a server receives it. Authentication between two devices has two flavors:
One typical kind of interaction is online purchasing through a web site. After filling a shopping cart with items, the user clicks on a Check out link which leads to a checkout form where the user fills in credit card and shipping information. When the user finishes filling out the form, a click on a Buy link or button sends the information to the server to complete the transaction.
Server authentication is necessary because the user needs assurance that the store is legitimate and will deliver goods in return for money. Server authentication is usually handled with HTTPS, as described later. Client authentication is necessary because the store needs assurance that the user will pay for goods purchased. The user supplies a credit card number and expiration date to prove identity and willingness to pay.
Using DNS to Identify a Server
The simplest technique for identifying a server is to rely on the Domain Name System (DNS) or even TCP/IP addressing. As a developer, you assume that when your client application attempts to connect to a named server, like
somehost.com, your client application is connected to the correct server. This is a pretty big assumption. The path from your client application to the server is likely to include computers and equipment about which you know next to nothing. For security purposes, you can assume that one or more of these machines is operated by criminals who can see all traffic passing between your client and the server. A rogue machine could be used for a man-in-the-middle attack, allowing attackers to view and record all traffic between you and the server. Using the same machine, attackers could even modify traffic between you and the server or just impersonate the server outright. There are known techniques for spoofing DNS lookups and even IP addresses. In the absence of cryptographic authentication techniques, clients are unable to distinguish a fake server from the real one.
Using TLS for Server Authentication
In web-based commerce, a server typically identifies itself by presenting a cryptographic certificate to the client during a Transport Layer Security (TLS) handshake. Assuming the online store has obtained a server certificate signed by one of the certificate authorities embedded in the user's web browser, the browser can authenticate the server, providing the user with some assurance that the online store is legitimate. To better understand the details of server authentication in a TLS handshake, read the second part of this series, MIDP Application Security 2: Understanding SSL and TLS.
This technique works equally well for browser clients and MIDP clients. Although the MIDP 1.0 specification does not mandate HTTPS support, many MIDP 1.0 devices support HTTP over TLS and SSL. The MIDP 2.0 specification requires that implementations support HTTPS. Part 2 of this series details TLS and SSL and their implementation in MIDP.
In general, HTTPS is a seamless solution for developers and users. It does require that browsers or MIDP implementations include root certificates for commonly used certificate authorities. When a server presents a certificate or certificate chain, the device implementation must possess the root certificate so that it can verify the server's certificate.
Make sure you understand that the server doesn't authenticate itself simply by presenting a certificate. After all, the certificate contains only a public key; the certificate (and the public key it contains) are made to be distributed freely. The server authenticates itself to the client by proving that it possesses a secret, which is the private key corresponding to the public key in the certificate. In a typical TLS handshake using RSA certificates, the client uses the server's public key to encrypt a value that will be used later in the conversation. By decrypting the value using its private key, the server proves it possesses the private key. This is where authentication happens. If the server is unable to decrypt the value from the client, the remainder of the handshake cannot be completed and the server is not authenticated.
Other Possibilities for Server Authentication
You can design your own protocol for server authentication if you wish, but it's probably not a good idea. Unless you have a serious problem with the authentication provided by TLS, it's unlikely that you'll gain a lot from implementing your own protocol. TLS has the strength of being widely deployed and scrutinized by the security community over several years (if you include the track record of its predecessor SSL). Authentication in the TLS protocol is based on X.509 certificates, which have withstood a similar trial of deployment and scrutiny.
Other protocols exist; some are weaker than TLS and some are stronger, but they are all are complex. SSL and TLS are a good choice for MIDP because they are time-tested and they meet the needs of wireless commerce applications.
Devices Belong to People
So far I haven't said much that's specific to MIDP clients because server authentication is much the same whether the client is a browser or a MIDlet. Significant differences arise in client authentication because web applications and MIDP applications have a fundamentally different relationship to their users.
The difference stems from ownership. Web applications are designed for access from any machine, any browser, anywhere in the world. I should be able to access my bank account from a cyber cafe in Brussels just as easily as from a hotel room in Tokyo. To prove my identity to the web application, I need to supply a login name and a password. Assuming I'm the only person who knows the password, supplying that secret authenticates me.
J2ME devices are different. Browsers belong to no one, but devices belong to people. Most MIDP devices today are mobile phones, which are usually the constant companions of their owners. Given this relationship, it makes sense to place authentication information (the client's secret value) directly on the device.
Password Authentication in MIDP
One authentication technique that translates more or less directly from web applications is password authentication. The user supplies a user name and a secret value, a password. The server checks the user's password against a database; if the password is correct, the user is authenticated.
The simple password scheme has two problems. First, people don't handle passwords well. They tend to pick bad passwords, and they tend to write passwords down in convenient but insecure places, like on a sticky note pasted to the front of the computer monitor. A bad password is one that is easy to guess. It may be vulnerable to a dictionary attack, guessing a user's password simply by using a dictionary of common passwords. This problem can be lessened by imposing restrictions on the password a user may select: it must be X characters long, it must contain both letters and numbers, and so forth. It's nearly impossible to convince users that they shouldn't write down their passwords anywhere, although education about computer security may help. Requiring frequent changes of passwords may also help, although it makes a system less usable and actually encourages users to write passwords down.
The second problem with simple password authentication is that the password itself, the client's secret value, is sent in cleartext between the client and server. There are two ways to fix this problem. You can either send the authentication information over an encrypted connection (probably using HTTPS) or send proof of the password instead of the password itself. I'll describe the latter technique later in this article.
In MIDP, a simple password authentication scheme could be created by adding the user name and password to an HTTP or HTTPS URL as follows:
String user = "jonathan"; String password = "happy8"; String base = "https://somehost.com/someservlet"; String url = base + "?user=" + user + "&password=" + password; HttpsConnection hc = (HttpsConnection)Connector.open(url);
Because each MIDP device usually belongs to one person, user names and passwords can be stored on the device so the user doesn't have to enter them each time he or she wants to use an application. This practice significantly eases use, especially considering how hard it is to enter data on a typical MIDP device, but it entails some risk. MIDP doesn't support any kind of secure storage, so theft of the device is a disaster for the user. See JSR 177, Security and Trust Services API for J2ME, for a look at a nascent optional package for access to secure storage, among other things.
MIDP clients can take further advantage of the relationship between users and devices to strengthen password authentication. Instead of allowing the user to choose a password, a MIDP application can embed a password in the client application and send it with requests to the server automatically. This approach trades some security for usuability. The user never needs to enter a password, but the password is stored on the device and vulnerable to theft by a rogue application or a common pickpocket.
If the risks are acceptable, however, storing a password on the device offers an additional benefit. The password no longer needs to be a human-readable string; it can be a random array of binary data, which makes it immune to a dictionary attack.
Password updates get trickier. Does the client use a single password for its lifetime? Is there a protocol for automatically changing passwords within the protection of encrypted communication between the client and server? These are questions you need to consider for any authentication scheme based on passwords.
Client Authentication Using Message Digests
Further refinements of the password or authentication-secret techniques are possible. For example, the client can send a message digest value of the authentication secret (and some other data) to prove to the server that it possesses the secret without actually sending the secret over the network connection. This approach is necessary wherever the communication between client and server is not encrypted.
For more information on this technique, including source code, see Chapter 12 of the first edition of Wireless Java .
Client Authentication Using Certificates
If you're going to embed authentication information in the client application, you might as well go the distance and use X.509 certificates for authentication. One way is to create a root key pair and a root certificate representing the application itself, then create client key pairs and certificates signed by the root key. Each copy of the client software can be packaged with a unique client key and certificate. When the client connects to the server, it can use its private key to sign or encrypt some data, then send the signature and its certificate to the server, as shown below. The server uses the application root certificate to verify the client's identity and uses the client's certificate to verify the signature.
Client to server data
Distributing private keys securely is a challenge in itself. When the private keys are distributed as part of MIDlet suites, the challenge widens to include secure client provisioning. I can't cover these concepts here. For more information, see JSR 124, J2EE Client Provisioning Specification.
Because MIDP does not include APIs for code signing, I've implemented this scheme using the Bouncy Castle Cryptography APIs, a comprehensive open source package for signing, encryption, message digests, and related functionality. The Bouncy Castle APIs come in several flavors, including a minimal lightweight package suitable for J2ME.
An obfuscator is crucial to MIDlet development with the Bouncy Castle APIs for two reasons:
java.security.SecureRandom. Applications aren't allowed to define classes in the
java.*namespace. MIDP devices, including the J2ME Wireless Toolkit 2.0 emulators, will not run a MIDlet suite that includes
java.*classes. An obfuscator can rename the classes so they will not be in the restricted namespace.
To run the example included with this article, first download and unpack the lightweight Bouncy Castle APIs.
The server side of this example is implemented in
CertificateServlet. You can use whatever servlet container you'd like; I used Tomcat 4.0.1. To install and run the servlet, follow these steps. You'll have to adapt them if you use a servlet engine other than Tomcat.
security3. Do this by editing Tomcat's conf/server.xml file. If you don't know how, take a look at Wireless Development Tutorial Part II.
The client is implemented by
CertificateMIDlet. To build and run this MIDlet, you'll need the Ant build tool and the ProGuard obfuscator. See the Resources section at the end of this article for links to articles about Ant and ProGuard. (You should be able to build and run this MIDlet with the J2ME Wireless Toolkit, provided you first plug in the ProGuard obfuscator, but I haven't tested this alternative.) To run this MIDlet successfully, you must use ProGuard or another obfuscator to rename Bouncy Castle's
java.* classes into another package. Follow these instrucations to install, build, and run the MIDlet.
proguardproperty points to your installation of ProGuard.
antto build the MIDlet suite. Ant will put the JAD and JAR files in build/bin.
ant runto run the MIDlet in the emulator.
When you've got everything running, select the OK command in
CertificateMIDlet. The MIDlet creates a timestamp and a random number, signs them, and sends all of the following information to the server:
The server receives all this information and:
If both verifications succeed, the server sends the client an "ok" message indicating success. If one or both verifications fail, a "sorry" message is sent, and if some other exception occurs the server sends an "exception" message with the exception text. The MIDlet simply displays the result from the server.
If you're using this technique over an unencrypted connection, you'll have to authenticate the client each time it contacts the server. If you're using TLS connections, then authenticating the first time is sufficient.
The server could (and probably should) perform additional checks on the timestamp and random number to make sure a replay attack is not being used. A replay attack is launched by listening to a successful authentication, then replaying the same client data later.
In practice, this approach is a little heavy for basic MIDP devices. Although the size of the Bouncy Castle APIs is, at a minimum, 350 KB, an obfuscator trims off all the stuff you're not using with dramatic results. I used ProGuard to reduce the size of the MIDlet suite JAR from about 500 KB to approximately 47 KB. Speed is another concern; cryptographic calculations are famously complicated. The signing performed by
CertificateMIDlet takes a few seconds using the J2ME Wireless Toolkit emulators; I'd expect it to be quite a bit slower on a real device. Password-hash authentication is probably more practical for MIDP devices, unless you need the level of security provided by signing data on the device.
This article describes authentication between clients and servers at a high level, then examined some of the specific authentication challenges MIDP devices pose. It includes a complete example that demonstrates how to use cryptographic certificates and signatures to authenticate a MIDP client to a server. A third-party package, the Bouncy Castle Cryptography APIs, provides cryptographic functionality in MIDP. An obfuscator reduces the MIDlet suite size. Certificate-based authentication in MIDP is expensive in terms of code size and processing time, but the example in this article proves that it is a viable option.