Wednesday 23 November 2016

DigestInputStream & DigestOutputStream Example

Message digest is a digital summary of information. Message digest functions (like SHA, MD5) are used to calculate message digest for given information.

Message digest is used to provide data integrity. Suppose ‘A’ want to send a document to ‘B’.

Step 1: A computes Message digest of the document.

Step 2: A sends document along with message digest.

Step 3: Once ‘B’ receives the document, ‘B’ recomputes message digest, and compares new message digest with original message digest. If the two message digests do not match, then 'B' knows the message was altered or corrupted.

If you want to know more about message digest, I already explained in following article.

What are Digest Streams?
java.security package provides DigestInputStream & DigestOutputStream classes to calculate the message digest of the content, while content is reading (or) written.

DigestInputStream
DigestInputStream class extends 'java.io.FilterInputStream' which again extends 'java.io.InputStream' class. DigestInputStream provide all the methods that supported by InputStream, in addition to this, whenever it reads a byte from the stream, it feeds the message digest.

FileUtil.java
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class FileUtilTest {
 private static String getHexaString(byte[] data) {
  String result = new BigInteger(1, data).toString(16);
  return result;
 }

 private static String getMessageDigest(DigestInputStream digestInputStream) {
  MessageDigest digest = digestInputStream.getMessageDigest();
  byte[] digestBytes = digest.digest();
  String digestStr = getHexaString(digestBytes);
  return digestStr;
 }

 public static void main(String args[]) throws NoSuchAlgorithmException, IOException {
  InputStream inputStream = new FileInputStream("abc.pdf");
  DigestInputStream digestInputStream = new DigestInputStream(inputStream, MessageDigest.getInstance("md5"));

  String digestBeforeRead = getMessageDigest(digestInputStream);

  while (digestInputStream.read() != -1) {

  }

  String digestAfterRead = getMessageDigest(digestInputStream);

  System.out.println("digestBeforeRead : " + digestBeforeRead);
  System.out.println("digestAfterRead : " + digestAfterRead);

  digestInputStream.close();

 }
}

Output
digestBeforeRead : d41d8cd98f00b204e9800998ecf8427e
digestAfterRead : 743b07e773e1f989aed9e1d65f76013f

Is it possible to turn off the data feeding to message digest?
Sometimes, you may not require message digest of data. In that cases, it is unnecessary to feed the data to message digest. DigestInputStream class provides ‘on’ method to turn on (or) off the data feeding to message digest.

Feeding of data to message digest will be on by default. You can turn off this by passing ‘false’ to on method.

Example
digestInputStream.on(false);

FileUtilTest.java
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class FileUtilTest {
 private static String getHexaString(byte[] data) {
  String result = new BigInteger(1, data).toString(16);
  return result;
 }

 private static String getMessageDigest(DigestInputStream digestInputStream) {
  MessageDigest digest = digestInputStream.getMessageDigest();
  byte[] digestBytes = digest.digest();
  String digestStr = getHexaString(digestBytes);
  return digestStr;
 }

 public static void main(String args[]) throws NoSuchAlgorithmException, IOException {
  InputStream inputStream = new FileInputStream("abc.pdf");
  DigestInputStream digestInputStream = new DigestInputStream(inputStream, MessageDigest.getInstance("md5"));
  digestInputStream.on(false);

  String digestBeforeRead = getMessageDigest(digestInputStream);

  while (digestInputStream.read() != -1) {

  }

  String digestAfterRead = getMessageDigest(digestInputStream);

  System.out.println("digestBeforeRead : " + digestBeforeRead);
  System.out.println("digestAfterRead : " + digestAfterRead);

  digestInputStream.close();

 }
}

Output
digestBeforeRead : d41d8cd98f00b204e9800998ecf8427e
digestAfterRead : d41d8cd98f00b204e9800998ecf8427e

DigestOutputStream
DigestOutputStream class extends java.io.FilterOutputStream which in turn extends java.io.OutputStream class. DigestOutputStream provide all the methods that supported by OutputStream, in addition to this, whenever you write data to the stream, it feeds the message digest same data.

FileUtil.java
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class FileUtilTest {
 private static String getHexaString(byte[] data) {
  String result = new BigInteger(1, data).toString(16);
  return result;
 }

 private static String getMessageDigest(DigestOutputStream digestOutputStream) {
  MessageDigest digest = digestOutputStream.getMessageDigest();
  byte[] digestBytes = digest.digest();
  String digestStr = getHexaString(digestBytes);
  return digestStr;
 }

 public static void main(String args[]) throws NoSuchAlgorithmException, IOException {
  OutputStream outputStream = new FileOutputStream("abc.txt");
  DigestOutputStream digestOutputStream = new DigestOutputStream(outputStream, MessageDigest.getInstance("md5"));

  String digestBeforeWrite= getMessageDigest(digestOutputStream);
  digestOutputStream.write(new String("Hello World").getBytes());
  String digestAfterWrite = getMessageDigest(digestOutputStream);

  System.out.println("digestBeforeWrite : " + digestBeforeWrite);
  System.out.println("digestAfterWrite : " + digestAfterWrite);

  digestOutputStream.close();

 }
}

Output
digestBeforeWrite : d41d8cd98f00b204e9800998ecf8427e
digestAfterWrite : b10a8db164e0754105b7a99be72e3fe5

Is it possible to turn off the data feeding to message digest?
Sometimes, you may not require message digest of data. In that cases, it is unnecessary to feed the data to message digest. DigestOutputStream class provides ‘on’ method to turn on (or) off the data feeding to message digest.

Feeding of data to message digest will be on by default. You can turn off this by passing ‘false’ to on method.

Example
digestOutputStream.on(false);

FileUtil.java
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class FileUtilTest {
 private static String getHexaString(byte[] data) {
  String result = new BigInteger(1, data).toString(16);
  return result;
 }

 private static String getMessageDigest(DigestOutputStream digestOutputStream) {
  MessageDigest digest = digestOutputStream.getMessageDigest();
  byte[] digestBytes = digest.digest();
  String digestStr = getHexaString(digestBytes);
  return digestStr;
 }

 public static void main(String args[]) throws NoSuchAlgorithmException, IOException {
  OutputStream outputStream = new FileOutputStream("abc.txt");
  DigestOutputStream digestOutputStream = new DigestOutputStream(outputStream, MessageDigest.getInstance("md5"));

  String digestBeforeWrite= getMessageDigest(digestOutputStream);
  digestOutputStream.on(false);
  digestOutputStream.write(new String("Hello World").getBytes());
  String digestAfterWrite = getMessageDigest(digestOutputStream);

  System.out.println("digestBeforeWrite : " + digestBeforeWrite);
  System.out.println("digestAfterWrite : " + digestAfterWrite);

  digestOutputStream.close();

 }
}

Output
digestBeforeWrite : d41d8cd98f00b204e9800998ecf8427e
digestAfterWrite : d41d8cd98f00b204e9800998ecf8427e







No comments:

Post a Comment