February 25, 2021
Hot Topics:

Message Authentication: Unlocking the Secrets of the Java Cryptography Extensions

  • By David Thurmond
  • Send Email »
  • More Articles »

The final step of the process is to write this data out to a file, sender_mac_data.txt, which the recipient can verify against his own authentication check.

Listing 4 shows how the recipient would recalculate the MAC on the decrypted message received by using the secret MAC key, and then would compare the calculated MAC to the sender's MAC to verify the integrity of the decrypted message.

Listing 4: VerifyMACFileExample.java

package com.dlt.developer.mac;

import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;

import javax.crypto.*;import java.security.Key;

import java.io.*;

public class VerifyMACFileExample {
   public static void main(String[] args) throws Exception {
      System.out.println("Calculating MAC and comparing to MAC
                          from sender...");

      BufferedInputStream in = new
         BufferedInputStream(new FileInputStream("mac_key.txt"));
      byte[] keyBytes = new byte[in.available()];
      SecretKeySpec skeySpec =
         new SecretKeySpec(keyBytes, "HmacMD5");

      Mac theMac = Mac.getInstance("HmacMD5");


      BufferedInputStream inData = new
         BufferedInputStream(new FileInputStream("plaintext.txt"));
      while (inData.available() > 0) {
         byte[] plaintextBytes = new byte[inData.available()];
      }    // while
      byte[] calculatedMacCode = theMac.doFinal();

      in = new BufferedInputStream(new FileInputStream(
      byte[] senderMacCode = new byte[in.available()];

      boolean macsAgree = true;
      if (calculatedMacCode.length != calculatedMacCode.length) {
         macsAgree = false;
         System.out.println("Sender MAC and calculated MAC length
                             are not the same.");
      } else {

         for (int i = 0; i < senderMacCode.length; i++) {
            if (senderMacCode[i] != calculatedMacCode[i]) {
               macsAgree = false;
               System.out.println("Sender MAC and calculated MAC
                                   are different. Message cannot
                                   be authenticated.");

            }    // if
         }       // for i
      }          // if

      if (macsAgree) {
         System.out.println("Message authenticated successfully.");
      }    // if

   }    // main

}    // class VerifyMACFile

The output from the VerifyMACFileExample.java program is shown below:

Calculating MAC and comparing to MAC from sender...
Message authenticated successfully.

To verify the integrity of the sender's message, the recipient first reads the mac_key.txt file that contains the agreed-upon secret key value. Then, as in the sender's example, the Mac object is initialized with this secret key.

Next, the recipient loops through the decrypted plaintext.txt file and performs the same calls using the Mac object that the sender did earlier. Of course, in real life, the recipient would have received an encrypted file, and would have had to decrypt this file to get to this point in the process. I have omitted any encryption or decryption from these examples to avoid confusion, but one might well decrypt and authenticate within the same program for efficiency's sake.

After the final invocation of Mac.doFinal(), the recipient has a calculated MAC that should agree with the sender's. Now, the receiver reads the sender's sender_mac_data.txt file into another byte array for comparison.

At last, the time has come to verify the authenticity of the message. The code first checks to see whether the two arrays of bytes are the same length. If so, each array element is compared; if any do not match, authentication fails. Once both of these checks have passed, the message recipient can rest easy that the message the sender sent is the same as the one he has received.


Message authentication is necessary in situations where a message recipient must be guaranteed that the message he received was the one the sender sent. Here, you have learned how to create and verify MACs using the Java Cryptography Extensions. Using the techniques discussed here, you now have the tools to create a secure message exchange between a sender and a recipient, even when the message must pass through unsecured channels.

Download the Code

You can download code examples here.


About the Author

David Thurmond is a Sun Certified Developer with over fifteen years of software development experience. He has worked in the agriculture, construction equipment, financial, home improvement, and logistics industries.

Page 4 of 4

This article was originally published on December 1, 2008

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date