Christmas is coming!

To celebrate the new year and thank for the support from all our dear customers, Christmas promotional activity is being held in JavaCardOS online store.

During the event, you can enjoy many promotional activities - High Discount on JavaCardOS products,Lucky Draw,Double forum Points.

Come to choose your own Christmas gift and try your luck now!

MAC Algorithm

Algorithm School

Moderator: UNKNwYSHSA

Posts: 112
Joined: Tue Sep 27, 2016 10:58 am
Points: 1460

MAC Algorithm

Postby tay00000 » Wed Mar 01, 2017 5:58 am

I would like to suggest @JavaCardOS to launch MAC algorithms for command MACs (DES-MAC, AES-MAC, HMAC).

For the HMAC codes, here is my source code contribution below.

Code: Select all

import javacard.framework.ISOException;
import javacard.framework.Util;

 * HMAC Class. Supports any supported HMAC-SHA1 and HMAC-SHA2 classes that the
 * card supports.
 * @author Tay
public class HMACSHA {

    private static final byte IPAD = (byte) 0x36;
    private static final byte OPAD = (byte) 0x5c;
    private static short outSize = 20;
    private static short blockSize = 64;

     * HMAC algo from RFC-2104. Setup the blocksize of the algo. Default
     * SHA-1.
     * @param hash MessageDigest hash class
     * @param hKey Byte array containing HMAC Key
    * @param hKeyOff Byte array of HMAC key to offset
    * @param hKeyLen Length of HMAC Key which can be any length
    * @param msg Message buffer
    * @param mOff Message buffer offset
    * @param mLen Message length
    * @param ipad IPAD buffer - Please assign an empty buffer with the same blockSize length as that of the target hash
    * @param offIPad Offset from which the IPAD buffer would be used
    * @param opad OPAD buffer - Please assign an empty buffer with the same blockSize length as that of the target hash
    * @param offOPad Offset from which the IPAD buffer would be used
    * @param secB Secret Key calculation buffer - Please assign an empty buffer with the same blockSize length as that of the target hash
    * @param offSecB Offset from which the Secret Key calculation buffer would be used
    * @param oMsg Output message buffer
    * @param outOff Output message buffer offest
    public static void process(MessageDigest hash, byte[] hKey, short hKeyOff,
            short hKeyLen, byte[] msg, short mOff, short mLen, byte[] ipad,
         short offIPad, byte[] opad, short offOPad, byte[] secB,
         short OffSecB, byte[] oMsg, short outOff) {      

      // Decide the output size from the resulting HMAC and blockSize per hash type for the HMAC
      if (hash.getAlgorithm() == MessageDigest.ALG_SHA) {
         outSize = (short) 20; // SHA-1
         blockSize = (short) 64;
        } else if (hash.getAlgorithm() == MessageDigest.ALG_SHA_256) {
            outSize = (short) 32; // SHA-256
         blockSize = (short) 64;
        } else if (hash.getAlgorithm() == MessageDigest.ALG_SHA_384) {
            outSize = (short) 48; // SHA-384           
            blockSize = (short) 128;
        } else if (hash.getAlgorithm() == MessageDigest.ALG_SHA_512) {
            outSize = (short) 64; // SHA-512           
            blockSize = (short) 128;
      // For code hygiene, always zeroize the IPAD, OPAD and SECB buffer otherwise the results will turn "dirty"
      Util.arrayFillNonAtomic(ipad, offIPad, blockSize, (byte) 0x00);
      Util.arrayFillNonAtomic(opad, offIPad, blockSize, (byte) 0x00);
      Util.arrayFillNonAtomic(secB, offIPad, blockSize, (byte) 0x00);

        // Block size == key size. Derive secret key.
        if (hKeyLen > blockSize) {
            hash.doFinal(hKey, hKeyOff, hKeyLen, secB, OffSecB);
        } else {
            Util.arrayCopyNonAtomic(hKey, hKeyOff, secB, OffSecB, hKeyLen);
        try {
            // Setup IPAD & OPAD secrets while using first byte of the outMsg array via outOffset
            oMsg[outOff] = (byte) 0x00;
            for (; (oMsg[outOff] & 0xFF) < blockSize;) {
                ipad[(short) ((oMsg[outOff] & 0xFF) + offIPad)] = (byte) (secB[(short) ((oMsg[outOff] & 0xFF) + OffSecB)] ^ IPAD);
                opad[(short) ((oMsg[outOff] & 0xFF) + offOPad)] = (byte) (secB[(short) ((oMsg[outOff] & 0xFF) + OffSecB)] ^ OPAD);
                oMsg[outOff] = (byte) ((oMsg[outOff] & 0xFF) + 1);
            oMsg[outOff] = (byte) 0x00;
        } catch (ArrayIndexOutOfBoundsException e) {
            ISOException.throwIt((short) 0xFC03);

        // hash(i_key_pad ∥ message)
        hash.update(ipad, offIPad, blockSize);
        hash.doFinal(msg, mOff, mLen, oMsg, outOff);

        //hash(o_key_pad ∥ i_pad-hashed)
        hash.update(opad, offOPad, blockSize);
        hash.doFinal(oMsg, outOff, outSize, oMsg, outOff);


User avatar
Posts: 628
Joined: Thu May 21, 2015 4:05 am
Points: 2971

Re: MAC Algorithm

Postby UNKNwYSHSA » Fri Mar 03, 2017 10:21 pm

The implementation of algorithms in specifications like GlobalPlatform/EMV/... is better. For example:
GlobalPlatform SCP authenticate algorithm.
Input: GP static Key, card challenge, ...
Output: Host cryptogram, command MAC, ...
The source code for this function can be found from GlobalPlatformPro (Java)/GPShell (C/C++)/pyGlobalPlatform(Python)/...
sense and simplicity

Return to “Algorithm School”

Who is online

Users browsing this forum: No registered users and 1 guest

JavaCard OS : Disclaimer