Java security evolution and concepts, Part 2

Discover the ins and outs of Java security

1 2 Page 2
Page 2 of 2

The keystore is a password-protected database that holds private keys and certificates. The password is selected at the time of creation. Each database entry can be guarded by its own password for extra security. Certificates accepted into the keystore are considered to be trusted. Keystore information can be used and updated by the security tools provided with the SDK.

Aspects of Java 2 Security

Aspects of Java 2 Security can be broadly classified as:

  • Core security: the core classes that deal with security
  • Security extensions: the optional packages that supplement the platform security
  • Security tools: the Java 2 Software Development Kit (SDK) tools pertaining to security
  • Application, applet, and plugin security: security deployment

In this article, I have focused on core security. I'll discuss the other aspects in subsequent articles.

Core security

Java 2's security pieces reside primarily in:

  • java.lang
  • java.security
  • java.security.cert
  • java.security.interfaces
  • java.security.spec

Another Java 2 package, java.security.acl, which exists for historical reasons, has been superseded by classes in the java.security package.

Let's examine each major security-related class in more detail.

java.lang

The java.lang package contains the SecurityManager class discussed above, which allows applications to implement a security policy. Before performing a sensitive operation, the SecurityManager determines the operation's identity and whether it can be performed in its security context. The manager contains many methods that begin with the word check. The invocation of such a check method typically looks like this:

    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkXXX(argument,  . . . );
    }

The special method checkPermission(java.security.Permission) determines whether an access request indicated by a specified permission should be granted or denied. The default implementation calls:

   AccessController.checkPermission(perm);

If a request is allowed, checkPermission returns quietly. If denied, a SecurityException is thrown. Refer to the "Sidebar 2: Security Exceptions" for an overview of security exceptions.

java.security

java.security contains most security classes and interfaces. It contains classes for access control, parameters for the various cryptographic algorithms, code source, guarded objects, key management, message digests, permission, policy, protection domains, providers, secure class loaders, random number generators, and digital signatures.

The following Java code can be used to produce a permission to read files in the /tmp directory.

FilePermission p = new FilePermission("/tmp/*", "read");

Entries in the policy file can also be used to achieve similar results. The following is a sample entry in the policy file that indicates the granularity of providing access.

// Sample policy file
grant signedBy "signer_names", codeBase "URL" {
    permission permission_class_name "target_name", "action", 
    signedBy "signer_names";
    };

Both the signedBy and codeBase name and value pairs are optional. The signedBy entry is an alias corresponding to the public key certificate of the private key used to sign the code. The alias name is mapped to the certificate in the keystore. The entry below would grant read/write access to all /tmp files if the code were signed by "Duke". The URL where the code originated is irrelevant.

grant signedBy "Duke" {
    permission java.io.FilePermission "/tmp/*", "read,write";
};

The entry shown below would provide unrestricted access -- clearly not desirable from a security viewpoint.

grant {
    // Allow everything for now
    permission java.security.AllPermission;
};

Many classes provide a Service Provider Interface (SPI) for providers to plug in their implementations. Examples include MessageDigest, Signature, KeyPairGenerator, and so on.

The MessageDigest class supports the MD5 and SHA algorithms. The getInstance() method is invoked to select the appropriate algorithm. The method update() is called to ready the input buffer, while the digest() method generates a message digest, the size of which (in this case, 128 bits, or 16 bytes) depends on the algorithm (in this case, MD5). The same digest() method would generate 160 bits (20 bytes) for the digest if the SHA algorithm was used. The code below is a complete application used to generate a message digest.

// Simple application that generates a Message Digest
import java.security.*;
import java.io.*;
public class md5 {
    public static void main(String args[]) {
        try {
        if (args.length != 1) {
            System.out.println("Usage: java md5 < some_string >");
            System.exit(1);
        }
        // Create an output file "digest"
        FileOutputStream digestStream = new FileOutputStream("digest");
        // Use the MD5 algorithm. SHA will work as well
        MessageDigest md=MessageDigest.getInstance("MD5");
        byte buf[] = args[0].getBytes();
        // Update the data and digest it
        md.update(buf);
        digestStream.write(md.digest());
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

The Signature class supports digital signatures. The signature algorithm can be, for example, DSA (digital signature algorithm), with SHA-1 (secure hashing algorithm) as the hashing algorithm. (See Part 1 of this series for more on algorithms). The DSA algorithm using the SHA-1 message digest algorithm can be specified as SHA1withDSA. In the case of RSA, there are multiple message digest algorithms possible, so the signing algorithm could be, for example, MD2withRSA, MD5withRSA, or SHA1withRSA. The algorithm name must be specified, as there is no default. Fragments of code to generate a signature are illustrated here:

    // Use SHA-1 as the hashing algorithm with DSA
    Signature sig = Signature.getInstance("SHA1withDSA", "SUN");
    // Initialize with private key
    sig.initSign(privKey);
      // Update the buffer with the message
      sig.update(buffer, 0, len);
      // Generate the signature
      String sigString = sig.sign();

Fragments of code to verify the signature are illustrated here:

    // Use SHA-1 as the hashing algorithm with DSA
    Signature sig = Signature.getInstance("SHA1withDSA", "SUN");
    // Initialize with public key
    sig.initVerify(pubKey);
      // Update the buffer with the message
      sig.update(buffer, 0, len);
      // Verify the signature
      boolean verifies = sig.verify(sigToVerify);

Notice that the signature is generated with the private key and verified with the public key. For more code samples, see Mary Dageforde's tutorial in Resources.

Wrap it up: java.security.cert, java.security.interfaces, and java.security.spec

The java.security.cert package deals with certificates. It provides, for instance, an abstract class to import, generate, and verify X.509 certificates. The java.security.interfaces package is a set of interfaces used to generate DSA and RSA key pairs. Finally, the java.security.spec package may be used to control the parameters for various algorithms, like DSA or RSA, and their corresponding keys.

Conclusion

In this article, we saw the different aspects of Java security, starting with its evolution. We looked at the different components of Java 2 Security and saw how they work together to support the design of a flexible policy.

In my next installment of this series, I'll discuss Java security extensions and the tools available as part of the platform. Finally, I'll touch on issues that affect applet security -- that is, the relationship of browser security to Java applets.

Raghavan Srinivas, a Java technology evangelist at Sun Microsystems, specializes in Java and distributed systems. He is a proponent of Java technology and teaches graduate and undergraduate classes in the evening. He has spoken on a variety of technical topics at conferences around the world, and is a member of the joint IETF/W3C working group on XML Digital Signatures (xmldsig). A software developer for over 15 years, Srinivas worked for Digital Equipment Corporation before joining Sun. He has worked in several key technology areas, including the internals of VMS, Unix, and Windows NT platforms. Srinivas holds a master's degree in computer science from the University of Southwestern Louisiana's Center of Advanced Computer Studies. He likes hiking, running, and traveling, but most of all loves to eat, especially spicy food.

Learn more about this topic

  • JavaWorld security-related articles and resources
  • java.sun.com security-related resources
  • Useful security-related books, documentation, and Websites

1 2 Page 2
Page 2 of 2