The DigestOutputStream Class Message Digest Streams

in this list are fully implemented in the base class and do not need to be implemented in the message digest subclass. Well show a simple implementation of a message digest class here. This implementation is based on a hash algorithm that produces a 4−byte output. As bytes are accumulated by this algorithm, they are stored into a 4−byte value that is, an int; when this value has all four bytes filled, it is XOR−ed to another integer that accumulates the hash: package javasec.samples.ch11; import java.security.; public class XYZMessageDigest extends MessageDigest implements Cloneable { private int hash; private int store; private int nBytes; public XYZMessageDigest { superXYZ; engineReset ; } public void engineUpdatebyte b { switchnBytes { case 0: store = b 24 0xff000000; break; case 1: store |= b 16 0x00ff0000; break; case 2: store |= b 8 0x0000ff00; break; case 3: store |= b 0 0x000000ff; break; } nBytes++; if nBytes == 4 { hash = hash store; nBytes = 0; store = 0; } } public void engineUpdatebyte b[], int offset, int length { for int i = 0; i length; i++ engineUpdateb[i + offset]; } public void engineReset { hash = 0; store = 0; nBytes = 0; } public byte[] engineDigest { while nBytes = 0 engineUpdatebyte 0; byte b[] = new byte[4]; b[0] = byte hash 24; b[1] = byte hash 16; b[2] = byte hash 8; b[3] = byte hash 0; engineReset ; return b; } } The implementation of this class is simple, which isnt surprising given the fact that the algorithm itself is too simple to be considered an effective digest algorithm. The major points to observe are: The name of the class XYZMessageDigest and the name of the algorithm that it implements XYZ must match one of the strings in the provider package for this class to be found. Hence, in our provider class in Chapter 8, we included this property: putMessageDigest.XYZ, XYZMessageDigest; • Our constructor must be public and take no arguments. It must call the superclass constructor passing the name of the message digest algorithm it implements. • In order for the getDigestLength method to function, we chose to implement the Cloneable interface instead of overriding the engine−GetDigestLength method. Since there are no embedded objects in this class, we do not need to override the clone method. The default implementation of that method a shallow copy is sufficient for this class. • The engineUpdate methods accumulate bytes of data until an integer has been accumulated, at which point that integer can be XOR−ed into the saved state held in the hash instance variable. • The engineDigest method converts the hash instance variable into a byte array and returns that to the programmer. Note that the engineDigest method is responsible for resetting the internal state of the algorithm. In addition, the engineDigest method is responsible for padding the data so that it is a multiple of four bytes the size of a Java integer. This type of data padding is a common feature of message digest calculation. • The engineReset method initializes the algorithm to its initial state. • Once we have an implementation of a message digest, we must install it into the security provider architecture. If we use the XYZProvider class from Chapter 8, we can change our Send class above to use our new digest algorithm: package javasec.samples.ch11; import java.io.; import java.security.; import javasec.samples.ch08.XYZProvider; public class SendXYZ { public static void mainString args[] { try { Security.addProvidernew XYZProvider ; FileOutputStream fos = new FileOutputStreamtest.xyz; MessageDigest md = MessageDigest.getInstanceXYZ; ObjectOutputStream oos = new ObjectOutputStreamfos; String data = This have I thought good to deliver thee, + that thou mightst not lose the dues of rejoicing + by being ignorant of what greatness is promised thee.; byte buf[] = data.getBytes ; md.updatebuf; oos.writeObjectdata; oos.writeObjectmd.digest ; } catch Exception e { System.out.printlne;