Some reader favorites:
EJB fundamentals and session beans
Create a scrollable virtual desktop in Swing
Wizard API updated!
Tim Boudreau has released a new version of the Swing Wizard library (version 0.997) that fixes the WizardException bug reported in JavaWorld's recent Open Source Java Project profile. The article's examples have been reworked to test out the new, improved WizardException. Thanks, Tim, for this helpful fix!
Open Source Java Projects: The Wizard API
Java, being the network development platform that it is, has had to tackle the problem of trust head on. The result is the Java Security API and the Java Cryptography Architecture.
Before I dive headlong into APIs, code, and commentary, I'd like to briefly revisit last month's discussion. If you're joining us for the first time, you might want to back up a month and read " Signed and delivered: An introduction to security and authentication ." This column provides a thorough introduction to all the terms and concepts I'll be using this month.
Security and authentication address two crucial concerns: that of proving a message was created by a particular entity, and that of proving a message wasn't tampered with after it was created. One way of meeting both of these goals is by the use of digital signatures.
Digital signatures depend heavily on a branch of cryptography known as public-key cryptography. Public-key algorithms are characterized by the fact that they rely on a matched pair of keys (one private and one public) rather than a single key. An entity keeps its private key secret, but makes its public key available.
A digital signature algorithm takes as input a message and an entity's private key, and generates a digital signature. The digital signature is created in such a way that anyone can take the entity's public key and use it to verify that the entity in fact signed the message in question. Furthermore, if the original message has been tampered with, the signature can no longer be verified. Digital signatures provide one additional benefit: once an entity has signed and distributed a message, it's impossible for its originator to deny having signed the message (without claiming his or her private key was stolen, anyway).
The Java Cryptography API defines the Java toolkit for security and authentication. The Java Cryptography Architecture (JCA) describes how to use the API. To ensure the highest degree of flexibility for both the developer and the end user, the JCA embraces two guiding principles:
To satisfy these two requirements, the developers of the Java Cryptography API based their design on a system of engines and providers.
Engines produce instances of message-digest generators, digital-signature generators, and key-pair generators. Each instance is used to carry out its corresponding function.
The canonical engine in the JCA is a class that provides a static method (or methods) named getInstance(), which returns an instance of a class that implements a cryptographically significant algorithm. The getInstance() method comes in both a one-argument and a two-argument form. In both cases, the first argument is the name of the algorithm.
The JCA provides a list of standard names, though not all will be provided in any particular release. The second argument
selects a provider.
Only one provider -- SUN -- is supplied in JDK 1.1. SUN provides both an implementation of the NIST Digital Signature Algorithm (DSA), and an implementation of the MD5 and NIST SHA-1 message digest algorithms.
We'll begin by looking at code that generates a message digest from a message.
MessageDigest messagedigest = MessageDigest.getInstance("SHA");
MessageDigest messagedigest = MessageDigest.getInstance("SHA", "SUN");
As I mentioned just a moment ago, the getInstance() method comes in two flavors. The first requires only the algorithm to be specified. The second requires both the algorithm
and the provider to be specified. Both return an instance of a class that implements the SHA algorithm.
Next, we pass the message through the message-digest generator.
int n = 0;
byte [] rgb = new byte [1000];
while ((n = inputstreamMessage.read(rgb)) > -1)
{
messagedigest.update(rgb, 0, n);
}
Here, we assume the message is available as an input stream. This code works well for large messages of unknown length. The
update() method also accepts a single byte as an argument for messages of a few bytes in length, and a byte array for messages of
a fixed or predictable size.
rgb = messagedigest.digest();
The final step involves generating the message digest itself. The resulting digest is encoded in an array of bytes.
As you can see, the JCA conveniently hides all the low-level implementation and algorithm-specific details, allowing you to work at a higher, more abstract level.
Of course, one of the risks of such an abstract approach is the increased likelihood that we won't recognize erroneous output resulting from bugs. Given the role of cryptography, this can be a significant problem.
Consider the "off-by-one" bug in the update line below:
int n = 0;
byte [] rgb = new byte [1000];
while ((n = inputstreamMessage.read(rgb)) > -1)
{
messagedigest.update(rgb, 0, n - 1);
}
C, C++, and Java programmers use the limit-minus-one idiom so frequently that typing it becomes almost automatic -- even when it's not appropriate. The code above will compile, and the executable will run without error or warning, but the resulting message digest will be wrong.
Luckily, the JCA is well thought out and well designed, making potential pitfalls like the one above relatively rare.
Before we move on to key-pair generators, take a look at
Free Download - 5 Minute Product Review. When slow equals Off: Manage the complexity of Web applications - Symphoniq
![]()
Free Download - 5 Minute Product Review. Realize the benefits of real user monitoring in less than an hour. - Symphoniq