Java Security, Part 1: Crypto Basics
Java Security, Part 1: Crypto Basics
19 Jul 2002
The Java platform, both its base language features and library extensions, provides
an excellent base for writing secure applications. In this tutorial, the first of two parts
on Java security, Brad Rubin guides you through the basics of cryptography and how
it is implemented in the Java programming language, using plenty of code examples
to illustrate the concepts.
The Java platform, both the basic language and library extensions, provides an
excellent foundation for writing secure applications. This tutorial covers the basics of
cryptography and how it is implemented in the Java programming language, and it
offers example code to illustrate the concepts.
Extension (JCE) and Java Secure Sockets Extension (JSSE). In addition, this
tutorial introduces the CertPath API, which is new for JDK 1.4. In Part 2 (see
Resources), we'll expand the discussion to encompass access control, which is
managed in the Java platform by the Java Authentication and Authorization Service
(JAAS).
If you are already a Java programmer and have been curious about cryptography
(topics such as private and public key encryption, RSA, SSL, certificates) and the
Java libraries that support them (JCE, JSSE), this tutorial is for you. It does not
assume any previous background in cryptography, JCE, or JSSE.
This tutorial introduces the basic cryptographic building block concepts. Each
concept is followed by the Java implementation considerations, a code example, and
the results of the example execution.
In most cases in the example execution sections, the actual strings have been
modified to be compatible with the character set requirements of this tutorial. Also, in
most examples, we look up and display the actual security provider library used for a
given algorithm. This is done to give the user a better feel of which libraries are
called for which functions. Why? Because, in most installations, there are a number
of these providers installed.
Now, new relaxed regulations open the door to tighter integration of security features
and the base language. The following packages -- used as extensions prior to the
1.4 release -- are now integrated into JDK 1.4:
As an example of a library, we'll be working with the Bouncy Castle provider (see
Resources ). The Bouncy Castle library provides other cryptographic algorithms,
including the popular RSA algorithm discussed in What is public key cryptography?
and What are digital signatures? of this tutorial.
While your directory names and java.security files might be a bit different, here is the
template for installing the Bouncy Castle provider. To install this library, download
the bcprov-jdk14-112.jar file and place it in the j2sdk1.4.0\jre\lib\ext and the Program
Files\Java\J2re1.4.0\lib\ext directories. In both java.security files, which are in the
same directories as above but use "security" instead of "ext", add the following line:
security.provider.6=org.bouncycastle.jce.provider.BouncyCastleProvider
security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.net.ssl.internal.ssl.Provider
security.provider.3=com.sun.rsajca.Provider
security.provider.4=com.sun.crypto.provider.SunJCE
security.provider.5=sun.security.jgss.SunProvider
security.provider.6=org.bouncycastle.jce.provider.BouncyCastleProvider
Looking ahead
In this section, we've introduced the features the Java language provides, either fully
integrated or extension-based, that help to ensure that programming remains
secure. We've offered some general examples of secure programming techniques to
help you become familiar with the concept. We've covered security technologies that
used to be extensions but are now integrated into the version 1.4 release; we've also
noted two new security technologies. And we've demonstrated that third-party
libraries can enhance security programs by offering new technologies.
In the remainder of this tutorial, we will familiarize you with these concepts designed
to provide secure messaging (as they apply to Java programming):
Overview
In this section, we will learn about message digests, which take the data in a
message and generate a block of bits designed to represent the "fingerprint" of the
message. We will also cover the JDK 1.4-supported algorithms, classes, and
methods related to message digests, offer a code example and a sample execution
code for both the message digest and message authentication features.
the fingerprint from the message, but quite difficult to generate a message that
matches a given fingerprint.
Message digests can be weak or strong. A checksum -- which is the XOR of all the
bytes of a message -- is an example of a weak message-digest function. It is easy to
modify one byte to generate any desired checksum fingerprint. Most strong functions
use hashing. A 1-bit change in the message leads to a massive change in the
fingerprint (ideally, 50 percent of the fingerprint bits change).
import java.security.*;
import javax.crypto.*;
//
// Generate a Message Digest
public class MessageDigestExample {
public static void main (String[] args) throws Exception {
//
// check args and get plaintext
if (args.length !=1) {
System.err.println("Usage: java MessageDigestExample text");
System.exit(1);
}
byte[] plainText = args[0].getBytes("UTF8");
//
// get a message digest object using the MD5 algorithm
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
//
// print out the provider used
System.out.println( "\n" + messageDigest.getProvider().getInfo() );
//
// calculate the digest and print it out
messageDigest.update( plainText);
System.out.println( "\nDigest: " );
System.out.println( new String( messageDigest.digest(), "UTF8") );
}
}
import java.security.*;
import javax.crypto.*;
//
// Generate a Message Authentication Code
public class MessageAuthenticationCodeExample {
Note that the key generation takes a long time because the code is generating
excellent quality pseudo-random numbers using the timing of thread behavior. Once
the first number is generated, the others take much less time.
Also, notice that unlike the message digest, the message-authentication code uses a
cryptographic provider. (For more on providers, see Security is enriched with
third-party libraries.)
Overview
In this section, we'll examine the uses of private key encryption and focus on such
concepts as cipher blocks, padding, stream ciphers, and cipher modes. We'll quickly
detail cipher algorithms, classes, and methods and illustrate this concept with a code
example and sample executions.
Consider this scenario: Alice and Bob each have a shared key that only they know
and they agree to use a common cryptographic algorithm, or cipher. In other words,
they keep their key private. When Alice wants to send a message to Bob, she
encrypts the original message, known as plaintext, to create ciphertext and then
sends the ciphertext to Bob. Bob receives the ciphertext from Alice and decrypts the
ciphertext with his private key to re-create the original plaintext message. If Eve the
eavesdropper is listening in on the communication, she hears only the ciphertext, so
the confidentiality of the message is preserved.
You can encrypt single bits or chunks of bits, called blocks. The blocks, called cipher
blocks, are typically 64 bits in size. If the message is not a multiple of 64 bits, then
the short block must be padded (more on padding at What is padding?). Single-bit
encryption is more common in hardware implementations. Single-bit ciphers are
called stream ciphers .
When the U.S. export regulations were restrictive, only 40-bit keys were allowed for
export. This key length is fairly weak. The official U.S. standard, the DES algorithm,
used 56-bit keys and this is becoming progressively weaker as processor speeds
accelerate. Generally, 128-bit keys are preferred today. With them, if one million
keys could be tried every second, it would take an average of many times the age of
the universe to find a key!
What is padding?
As we mentioned in the previous section, if a block cipher is used and the message
length is not a multiple of the block length, the last block must be padded with bytes
to yield a full block size. There are many ways to pad a block, such as using all
zeroes or ones. In this tutorial, we'll be using PKCS5 padding for private key
encryption and PKCS1 for public key encryption.
With PKCS5, a short block is padded with a repeating byte whose value represents
the number of remaining bytes. We won't be discussing padding algorithms further in
this tutorial, but for your information, JDK 1.4 supports the following padding
techniques:
• No padding
• PKCS5
• OAEP
• SSL3
The BouncyCastle library (see Security is enriched with third-party libraries and
Resources ) supports additional padding techniques.
For example, you can allow the encryption of one block to be dependent on the
encryption of the previous block, or you can make the encryption of one block
independent of any other blocks.
The mode you choose depends on your needs and you must consider the trade-offs
(security, ability to parallel process, and tolerance to errors in both the plaintext and
the ciphertext). Selection of modes is beyond the scope of this tutorial (see
Resources for further reading), but again, for your information, the Java platform
supports the following modes:
• DES. DES (Data Encryption Standard) was invented by IBM in the 1970s
and adopted by the U.S. government as a standard. It is a 56-bit block
cipher.
• TripleDES. This algorithm is used to deal with the growing weakness of a
56-bit key while leveraging DES technology by running plaintext through
the DES algorithm three times, with two keys, giving an effective key
strength of 112 bits. TripleDES is sometimes known as DESede (for
encrypt, decrypt, and encrypt, which are the three phases).
• AES. AES (Advanced Encryption Standard) replaces DES as the U.S.
standard. It was invented by Joan Daemen and Vincent Rijmen and is
also known as the Rinjdael algorithm. It is a 128-bit block cipher with key
lengths of 128, 192, or 256 bits.
• RC2, RC4, and RC5. These are algorithms from a leading encryption
security company, RSA Security.
• Blowfish. This algorithm was developed by Bruce Schneier and is a
block cipher with variable key lengths from 32 to 448 bits (in multiples of
8), and was designed for efficient implementation in software for
microprocessors.
• PBE. PBE (Password Based Encryption) can be used in combination with
a variety of message digest and private key algorithms.
The Cipher class manipulates private key algorithms using a key produced by the
KeyGenerator class. The following methods are used in the Private key
cryptography code example:
import java.security.*;
import javax.crypto.*;
//
// encrypt and decrypt using the DES private key algorithm
public class PrivateExample {
public static void main (String[] args) throws Exception {
//
// check args and get plaintext
if (args.length !=1) {
System.err.println("Usage: java PrivateExample text");
System.exit(1);
}
byte[] plainText = args[0].getBytes("UTF8");
//
// get a DES private key
System.out.println( "\nStart generating DES key" );
KeyGenerator keyGen = KeyGenerator.getInstance("DES");
keyGen.init(56);
Key key = keyGen.generateKey();
System.out.println( "Finish generating DES key" );
//
// get a DES cipher object and print the provider
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
System.out.println( "\n" + cipher.getProvider().getInfo() );
//
// encrypt using the key and the plaintext
System.out.println( "\nStart encryption" );
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherText = cipher.doFinal(plainText);
System.out.println( "Finish encryption: " );
System.out.println( new String(cipherText, "UTF8") );
//
// decrypt the ciphertext using the same key
System.out.println( "\nStart decryption" );
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] newPlainText = cipher.doFinal(cipherText);
System.out.println( "Finish decryption: " );
System.out.println( new String(newPlainText, "UTF8") );
}
}
Start decryption
Finish decryption:
This is a test!
Overview
In this section, we'll look at public key cryptography, a feature that solves the
problem of encrypting messages between parties without prior arrangement on the
keys. We'll take a short walk through the algorithms, classes, and methods that
support the public key function, and offer a code sample and execution to illustrate
the concept.
Public key cryptography, invented in the 1970s, solves the problem of encrypting
messages between two parties without prior agreement on the key.
In public key cryptography, Alice and Bob not only have different keys, they each
have two keys. One key is private and must not be shared with anyone. The other
key is public and can be shared with anyone.
When Alice wants to send a secure message to Bob, she encrypts the message
using Bob's public key and sends the result to Bob. Bob uses his private key to
decrypt the message. When Bob wants to send a secure message to Alice, he
encrypts the message using Alice's public key and sends the result to Alice. Alice
uses her private key to decrypt the message. Eve can eavesdrop on both public
keys and the encrypted messages, but she cannot decrypt the messages because
she does not have either of the private keys.
The public and private keys are generated as a pair and need longer lengths than
the equivalent-strength private key encryption keys. Typical key lengths for the RSA
algorithm are 1,024 bits. It is not feasible to derive one member of the key pair from
the other.
Public key encryption is slow (100 to 1,000 times slower than private key
encryption), so a hybrid technique is usually used in practice. Public key encryption
is used to distribute a private key, known as a session key, to another party, and
then private key encryption using that private session key is used for the bulk of the
message encryption.
• RSA. This algorithm is the most popular public key cipher, but it's not
supported in JDK 1.4. You must use a third-party library like
BouncyCastle to get this support.
• Diffie-Hellman. This algorithm is technically known as a key-agreement
algorithm . It cannot be used for encryption, but can be used to allow two
parties to derive a secret key by sharing information over a public
channel. This key can then be used for private key encryption.
The Cipher class manipulates public key algorithms using keys produced by the
KeyPairGenerator class. The following methods are used in the Public key
cryptography code example example:
• KeyPairGenerator.getInstance("RSA") , .initialize(1024) ,
and .generateKeyPair() : Generates the key pair.
• Cipher.getInstance("RSA/ECB/PKCS1Padding") Creates a
Cipher object (specifying the algorithm, mode, and padding).
• .init(Cipher.ENCRYPT_MODE, key.getPublic()) : Initializes the
Cipher object.
• .doFinal(plainText) : Calculates the ciphertext with a plaintext
string.
• .init(Cipher.DECRYPT_MODE, key.getPrivate()) and
.doFinal(cipherText) : Decrypts the ciphertext.
import java.security.*;
import javax.crypto.*;
//
// Public Key cryptography using the RSA algorithm.
public class PublicExample {
public static void main (String[] args) throws Exception {
//
// check args and get plaintext
if (args.length !=1) {
System.err.println("Usage: java PublicExample text");
System.exit(1);
}
byte[] plainText = args[0].getBytes("UTF8");
//
// generate an RSA key
System.out.println( "\nStart generating RSA key" );
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024);
KeyPair key = keyGen.generateKeyPair();
System.out.println( "Finish generating RSA key" );
//
// get an RSA cipher object and print the provider
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
System.out.println( "\n" + cipher.getProvider().getInfo() );
//
// encrypt the plaintext using the public key
System.out.println( "\nStart encryption" );
cipher.init(Cipher.ENCRYPT_MODE, key.getPublic());
byte[] cipherText = cipher.doFinal(plainText);
System.out.println( "Finish encryption: " );
System.out.println( new String(cipherText, "UTF8") );
//
// decrypt the ciphertext using the private key
System.out.println( "\nStart decryption" );
cipher.init(Cipher.DECRYPT_MODE, key.getPrivate());
byte[] newPlainText = cipher.doFinal(cipherText);
System.out.println( "Finish decryption: " );
System.out.println( new String(newPlainText, "UTF8") );
}
}
Overview
In this section, we'll examine digital signatures, the first level of determining the
identification of parties that exchange messages. We'll illustrate both difficult and
easy ways to identify the message source through code samples. We'll also list the
digital signature algorithms that JDK 1.4 supports, and look at the classes and
methods involved.
We can solve this problem by using a digital signature -- a bit pattern that proves
that a message came from a given party.
One way of implementing a digital signature is using the reverse of the public key
process described in What is public key cryptography?. Instead of encrypting with a
public key and decrypting with a private key, the private key is used by a sender to
sign a message and the recipient uses the sender's public key to decrypt the
message. Because only the sender knows the private key, the recipient can be sure
that the message really came from the sender.
In actuality, the message digest (What is a message digest?), not the entire
message, is the bit stream that is signed by the private key. So, if Alice wants to
send Bob a signed message, she generates the message digest of the message
and signs it with her private key. She sends the message (in the clear) and the
signed message digest to Bob. Bob decrypts the signed message digest with Alice's
public key and computes the message digest from the cleartext message and
checks that the two digests match. If they do, Bob can be sure the message came
from Alice.
Note that digital signatures do not provide encryption of the message, so encryption
techniques must be used in conjunction with signatures if you also need
confidentiality.
You can use the RSA algorithm for both digital signatures and encryption. A U.S.
standard called DSA (Digital Signature Algorithm) can be used for digital signatures,
but not for encryption.
Algorithms
JDK 1.4 supports the following digital signature algorithms:
• MD2/RSA
• MD5/RSA
• SHA1/DSA
• SHA1/RSA
We'll examine two examples in this section. The first, the hard way (see Digital
signature code example: The hard way ), uses the primitives already discussed for
message digests and public key cryptography to implement digital signatures. The
second, the easy way (see Digital signature code example: The easy way ), uses the
Java language's direct support for signatures.
import java.security.*;
import javax.crypto.*;
//
// This program demonstrates the digital signature technique at the
// primative level by generating a message digest of the plaintext
// and signing it with an RSA private key, to create the signature.
// To verify the signature, the message digest is again generated from
// the plaintext and compared with the decryption of the signature
// using the public key. If they match, the signature is verified.
public class DigitalSignature1Example {
public static void main (String[] args) throws Exception {
//
// check args and get plaintext
if (args.length !=1) {
System.err.println("Usage: java DigitalSignature1Example text");
System.exit(1);
}
byte[] plainText = args[0].getBytes("UTF8");
//
// get an MD5 message digest object and compute the plaintext digest
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
System.out.println( "\n" + messageDigest.getProvider().getInfo() );
messageDigest.update( plainText );
byte[] md = messageDigest.digest();
System.out.println( "\nDigest: " );
System.out.println( new String( md, "UTF8") );
//
// generate an RSA keypair
System.out.println( "\nStart generating RSA key" );
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024);
KeyPair key = keyGen.generateKeyPair();
System.out.println( "Finish generating RSA key" );
//
Sample execution
Finish decryption:
iNdf6D213$dcd(ndz!0)
Start signature verification
Signature verified
• KeyPairGenerator.getInstance("RSA") , .initialize(1024) ,
and .generateKeyPair() : Generates the keys.
• Cipher.getInstance("MD5WithRSA") : Creates the Signature
object.
• .initSign(key.getPrivate()) : Initializes the Signature object.
• .update(plainText) and .sign() : Calculates the signature with a
plaintext string.
• .initVerify(key.getPublic()) and .verify(signature) :
Verifies the signature.
import java.security.*;
import javax.crypto.*;
//
// This example uses the digital signature features to generate and
// verify a signature much more easily than the previous example
public class DigitalSignature2Example {
public static void main (String[] args) throws Exception {
//
// check args and get plaintext
if (args.length !=1) {
System.err.println("Usage: java DigitalSignature1Example text");
System.exit(1);
}
byte[] plainText = args[0].getBytes("UTF8");
//
// generate an RSA keypair
System.out.println( "\nStart generating RSA key" );
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024);
KeyPair key = keyGen.generateKeyPair();
System.out.println( "Finish generating RSA key" );
//
// get a signature object using the MD5 and RSA combo
// and sign the plaintext with the private key,
// listing the provider along the way
Signature sig = Signature.getInstance("MD5WithRSA");
sig.initSign(key.getPrivate());
sig.update(plainText);
byte[] signature = sig.sign();
System.out.println( sig.getProvider().getInfo() );
System.out.println( "\nSignature:" );
System.out.println( new String(signature, "UTF8") );
//
// verify the signature with the public key
System.out.println( "\nStart signature verification" );
sig.initVerify(key.getPublic());
sig.update(plainText);
try {
if (sig.verify(signature)) {
System.out.println( "Signature verified" );
} else System.out.println( "Signature failed" );
} catch (SignatureException se) {
System.out.println( "Signature failed" );
}
}
}
Sample execution
Overview
In this section, we'll discuss digital certificates, the second level to determining the
identity of a message originator. We'll look at certificate authorities and the role they
play. We'll examine key and certificate repositories and management tools (keytool
and keystore) and discuss the CertPath API, a set of functions designed for building
and validating certification paths.
but how do we know for sure that the sender really is who she says she is. What if
someone claims to be Alice and signs a message, but is actually Amanda? We can
improve our security by using digital certificates which package an identity along with
a public key and is digitally signed by a third party called a certificate authority or CA.
The Java platform uses the keytool to manipulate the keystore. This tool offers many
options; the following example (keytool example) shows the basics of generating a
public key pair and corresponding certificate, and viewing the result by querying the
keystore.
The keytool can be used to export a key into a file, in X.509 format, that can be
signed by a certificate authority and then re-imported into the keystore.
There is also a special keystore that is used to hold the certificate authority (or any
other trusted) certificates, which in turn contains the public keys for verifying the
validity of other certificates. This keystore is called the truststore. The Java language
comes with a default truststore in a file called cacerts . If you search for this
filename, you will find at least two of these files. You can display the contents with
the following command:
keytool example
CertPath API
The Certification Path API is new for JDK 1.4. It is a set of functions for building and
validating certification paths or chains. This is done implicitly in protocols like
SSL/TLS (see What is Secure Sockets Layer/Transport Layer Security?) and JAR
file signature verification, but can now be done explicitly in applications with this
support.
As mentioned in What are digital certificates?, a CA can sign a certificate with its
private key, and if the recipient holds the CA certificate that has the public key
needed for signature verification, it can verify the validity of the signed certificate.
In this case, the chain of certificates is of length two -- the anchor of trust (the CA
certificate) and the signed certificate. A self-signed certificate is of length one -- the
anchor of trust is the signed certificate itself.
Certificates have expiration dates, but can be compromised before they expire, so
Certificate Revocation Lists (CRL) must be checked to really ensure the integrity of a
signed certificate. These lists are available on the CA Web sites, and can also be
programmatically manipulated with the CertPath API.
The specific API and code examples are beyond the scope of this tutorial, but Sun
has several code examples available in addition to the API documentation.
Overview
In this section, we'll review the concept of code signing, focusing on the tool that
manages the certification of a JAR file, Jarsigner.
Jarsigner tool
The jarsigner tool takes a JAR file and a private key and corresponding certificate as
input, then generates a signed version of the JAR file as output. It calculates the
message digests for each class in the JAR file and then signs these digests to
ensure the integrity of the file and to identify the file owner.
<HTML>
<HEAD>
<TITLE> Hello World Program </TITLE>
</HEAD>
<BODY>
<APPLET CODE="HelloWorld.class" ARCHIVE="HelloWorld.jar"
WIDTH=150 HEIGHT=25>
</APPLET>
</BODY>
</HTML>
When this example is executed with a browser that uses the Java plug-in as the
Java virtual machine, a dialog box pops up asking if the user wants to install and run
the signed applet distributed by "Joe User", and says that the publisher authenticity
is verified by "Company, Inc.", but that the security was issued by a company that is
not trusted. The security certificate has not expired and is still valid. It cautions that
"Joe User" asserts that this content is safe and should only be installed or viewed if
you trust "Joe User" to make that assertion. The user is given the following options:
Overview
In this section, we'll examine the building blocks of the Secure Sockets Layer (and
its replacement, Transport Layer Security), the protocol used to authenticate the
server to the client. We'll offer a few code examples as illustrations.
is in effect.
In Java programming, the only thing that needs to be done is to use an SSL Server
Socket Factory instead of a Socket Factory, using lines like the following:
SSLServerSocketFacctory sslf =
(SSLServerSocketFactor)SSLServerSocketFactory.getDefault();
ServerSocket serverSocket = sslf.createServerSocket(PORT);
import java.io.*;
import java.net.*;
import javax.net.ssl.*;
//
We first create a machine certificate. The name must match the machine name of
the computer where the daemon runs; in this case, localhost. In addition, we cannot
use the same .keystore we have used in the past. We must create a separate
keystore just for the machine certificate. In this case, it has the name sslKeyStore.
Then, we start the server daemon process specifying the special keystore and its
password:
D:\IBM>java -Djavax.net.ssl.keyStore=sslKeyStore
-Djavax.net.ssl.keyStorePassword=password HTTPSServerExample
Summary
This tutorial introduced the major cryptographic building blocks that can be used to
provide a vast array of application security solutions. You've become familiar with
such Java security topics as:
• Message digests
• Message authentication codes
• Private key cryptography
• Public key cryptography
• Digital signatures
• Digital certificates
• Certification authorities and paths
• Code signing
• SSL/TLS
You should be well poised to explore Java security in more detail (see the
Resources section) and to take the next tutorial, Java security, Part 2: Authentication
and authorization.
Resources
Learn
• See Sun Microsystems's Java Security site to learn more about the most
current Java security technologies.
• Read Brad Rubin's second tutorial in this series, "Java security, Part 2:
Authentication and authorization" (developerWorks, July 2002).
• Michael Yuan demonstrates how to digitally sign and verify XML documents on
wireless devices using the Bouncy Castle Crypto APIs in his article "Securing
your J2ME/MIDP apps" (developerWorks, June 2002).
• Greg Travis offers a practical look at JSSE in his tutorial "Using JSSE for secure
socket communication" (developerWorks, April 2002).
• For an overall discussion of Web security and Java technology, see Web
Security, Privacy, and Commerce, 2nd Edition , by Simson Garfinkel and Gene
Spafford, O'Reilly, 2002.
• If you want to focus more on Java security, see Professional Java Security , by
Jess Garms and Daniel Somerfield, Wrox Press, 2001.
• Another great resource for learning about Java security is Java Security , by
Scott Oaks, O'Reilly & Associates, 2001.
• Find out what everyone needs to know about security in order to survive and be
competitive in Secrets and Lies: Digital Security in a Networked World , by
Bruce Schneier, 2000.
• Boasting new algorithms, more information on the Clipper Chip and key escrow,
dozens of new protocols, more information on PGP, detailed information on key
management and modes of operation, and new source code, this book should
be a security winner: Applied Cryptography, Second Edition , by Bruce
Schneier, 1995.
• The IBM Java Security Research page details various security projects in the
works.
• Visit the Tivoli Developer domain for help in building and maintaining the
security of your e-business.
• You'll find hundreds of articles about every aspect of Java programming in the
developerWorks Java technology zone.
• See the developerWorks tutorials page for a complete listing of Java
technology-related free tutorials from developerWorks.
Get products and technologies
• Download the complete source code and classes used in this tutorial,
JavaSecurity1-source.jar.
• See BouncyCastle for the third-party provider library used in this tutorial.
Discuss
• Participate in the discussion forum for this content.