Christmas is coming soon! To thank for the support from all our dear customers, Christmas promotional activity is going on in JavaCardOS online store. For more activities details, please check this post.

How to compute MAC

Algorithm School

Moderator: UNKNwYSHSA

User avatar
wintstar
Posts: 14
Joined: Sun Jul 26, 2015 11:06 pm
Points :119
Contact:

How to compute MAC

Post by wintstar » Sat Aug 29, 2015 4:13 am

Hi, everyone.
I need to implement authentication process. How can I compute the MAC data?
Thanks

User avatar
UNKNwYSHSA
Posts: 630
Joined: Thu May 21, 2015 4:05 am
Points :3027
Contact:

Re: How to compute MAC

Post by UNKNwYSHSA » Sat Aug 29, 2015 11:31 pm

What's the code you write for?
The specification usually describe how to calculate the MAC step by step for details.
For example, the GP specification, has figure and text description for how to calculate MAC, very clear while writing code.
sense and simplicity

User avatar
UNKNwYSHSA
Posts: 630
Joined: Thu May 21, 2015 4:05 am
Points :3027
Contact:

Re: How to compute MAC

Post by UNKNwYSHSA » Sat Aug 29, 2015 11:34 pm

Like this:
You do not have the required permissions to view the files attached to this post. Please login first.
sense and simplicity

Bob2002
Posts: 36
Joined: Wed Jul 29, 2015 10:50 pm
Points :1216
Contact:

Re: How to compute MAC

Post by Bob2002 » Sun Aug 30, 2015 9:22 pm

Here is an example of how to do the MAC. It comes from oracle community.

Code: Select all

byte[] mac;
byte[] icv = new byte[8];
Cipher desedeCBCCipher = Cipher.getInstance("DESede/CBC/NoPadding");
Cipher desCipher = Cipher.getInstance("DES/CBC/NoPadding");

IvParameterSpec ivSpec = new IvParameterSpec(icv);

if (data.length % 8 != 0)
    throw new Exception("data block size must be multiple of 8");

int blocks = data.length / 8;

for (int i = 0; i < blocks - 1; i++) {
    desCipher.init(Cipher.ENCRYPT_MODE, singledesCMAC, ivSpec);
    byte[] block = desCipher.doFinal(data, i * 8, 8);
    ivSpec = new IvParameterSpec(block);
}

int offset = (blocks - 1) * 8;

desedeCBCCipher.init(Cipher.ENCRYPT_MODE, sessionCMAC, ivSpec);
mac = desedeCBCCipher.doFinal(data, offset, 8);

ivSpec = new IvParameterSpec(new byte[8]);
desCipher.init(Cipher.ENCRYPT_MODE, singledesCMAC, ivSpec);
icv = desCipher.doFinal(data);

Note:
icv is set to 00:00:00:00:00:00:00:00 for the external authenticate call and the resulting icv from each command is used as the ICV for the next command.
sessionCMAC is the session MAC key
singledesCMAC is left half (8 bytes) of the session MAC key.

Here is some code to derive a key from derivation data.

Code: Select all

private SecretKey getSecretKey(byte[] keyData) throws GeneralSecurityException {
    if (keyData.length == 16) {
        byte[] temp = (byte[]) keyData.clone();
        keyData = new byte[24];
        System.arraycopy(temp, 0, keyData, 0, temp.length);
        System.arraycopy(temp, 0, keyData, 16, 8);
    }

    DESedeKeySpec keySpec = new DESedeKeySpec(keyData);
    SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DESede");
    SecretKey key = secretKeyFactory.generateSecret(keySpec);

    return key;
}

private Key deriveKey(byte[] keyData, byte[] data) throws GeneralSecurityException {
    Key key = getSecretKey(keyData);
    IvParameterSpec dps = new IvParameterSpec(DEFAULT_ICV);
    desedeCBCCipher.init(Cipher.ENCRYPT_MODE, key, dps);

    byte[] result = desedeCBCCipher.doFinal(data);
    adjustParity(result);

    return getSecretKey(result);
}


/**
 * Adjust a DES key to odd parity
 *
 * @param key
 *            to be adjusted
 */
private static void adjustParity(byte[] key) {
    for (int i = 0; i < key.length; i++) {
        int akku = (key[i] & 0xFF) | 1;

        for (int c = 7; c > 0; c--) {
            akku = (akku & 1) ^ (akku >> 1);
        }
        key[i] = (byte) ((key[i] & 0xFE) | akku);
    }
}


The MAC method for verifying the card and host cryptogram is different to the retail MAC used for EXTERNAL AUTHENTICATE. Here is some code to generate the signature for host and card cryptograms.

Code: Select all

 /**
     * Calculate the DES CBC MAC using the standard cipher algorithms
     *
     * @param key
     *            Key used for MAC calculation
     * @param data
     *            Data to calculate the MAC for
     * @param iv
     *            ICV
     *
     * @returns CBC MAC
     */
    public byte[] cbcMac(byte[] data) throws AuthenticationException {

        byte[] temp;
        try {
            Cipher cbcDES = Cipher.getInstance("DESede/CBC/NoPadding");
            IvParameterSpec params = new IvParameterSpec(DEFAULT_ICV);
            cbcDES.init(Cipher.ENCRYPT_MODE, sessionSENC, params);

            temp = cbcDES.doFinal(data);
        } catch (GeneralSecurityException e) {
            throw new AuthenticationException("Error performing CBC MAC", e);
        }

        byte[] signature = new byte[8];
        System.arraycopy(temp, temp.length - 8, signature, 0, signature.length);
        return signature;
    }

simplyi
Posts: 2
Joined: Fri Mar 03, 2017 1:58 pm
Points :16
Contact:

Re: How to compute MAC

Post by simplyi » Fri Mar 03, 2017 2:08 pm

Hello!

Thank you very much for these code examples. Please allow me ask a couple of questions regarding these code examples:

1. Is the sessionCMAC calculated using the KeyGenerator.getInstance("DESede") ?
2. I am not very sure how to calculate the singledesCMAC out of sessionCMAC...Can I do it this way?

private static byte[] getHalfKey(byte[] doubleDesKey)
{
byte[] singledesCMAC = new byte[8];
System.arraycopy(doubleDesKey, doubleDesKey.length - 8, singledesCMAC, 0, singledesCMAC.length);
return singledesCMAC;
}

and then convert these bytes to a secret key this way?

byte[] halfAKeyBytes = getHalfKey(master_mac_key.getEncoded());
KeySpec halfKeySpec = new DESedeKeySpec(halfAKeyBytes);
SecretKey halfAKey = mySecretKeyFactory.generateSecret(myKeySpec);

Also, in the method: private SecretKey getSecretKey(byte[] keyData), what exactly is derivation data? Is it another key? or is it how we actually derive the singledesCMAC out of sessionCMAC?

Thank you very much!

User avatar
UNKNwYSHSA
Posts: 630
Joined: Thu May 21, 2015 4:05 am
Points :3027
Contact:

Re: How to compute MAC

Post by UNKNwYSHSA » Fri Mar 03, 2017 10:53 pm

Are you talking about MAC calculation for GP SCP02?
sense and simplicity

simplyi
Posts: 2
Joined: Fri Mar 03, 2017 1:58 pm
Points :16
Contact:

Re: How to compute MAC

Post by simplyi » Sat Mar 04, 2017 1:45 am

I was looking for Retail MAC Calculation when I came across this discussion.

User avatar
UNKNwYSHSA
Posts: 630
Joined: Thu May 21, 2015 4:05 am
Points :3027
Contact:

Re: How to compute MAC

Post by UNKNwYSHSA » Sun Mar 05, 2017 10:54 pm

You can refer source code of bouncycastle. Refer to implementation of class org.bouncycastle.crypto.macs.ISO9797Alg3Mac.
That can resolve all your questions.

For your 1st question: The DESede algorithm can only be used on the output transformation (last transformation).
sense and simplicity

stanneraustin
Posts: 6
Joined: Fri Jul 07, 2017 12:22 pm
Points :110
Contact:

Re: How to compute MAC

Post by stanneraustin » Thu Jan 18, 2018 1:03 pm

Hello
i need some clarification on C-MAC if any one can guide.
my init update and ext auth work ok
after external auth i got ICV last verified with ext auth in output of external auth
now on next i plan to implement delete AID
i have to use same ICV where for next msg ?
i am testing on JCIDE with exmple
data = "84E400800A4F" + "08" + aiddata
results1 = des(data,S_MAChalf ) question is ICV use on this or next one ?
results2 = 3des(data+8,S_MAC)
my output return 69 82 i know i made mistake some where on C-MAC but documents do not explain perfectly nor any sample to understand this.

BirdKing
Posts: 54
Joined: Wed Nov 04, 2015 7:23 am
Points :404
Contact:

Re: How to compute MAC

Post by BirdKing » Fri Jan 19, 2018 1:47 am

According to GPC_Specification_v2.2.1, the ICV should be the MAC of the EXTERNAL AUTHENTICATE command.
The description from GPC_Specification_v2.2.1 is :
E.3.2 Message Integrity ICV using Explicit Secure Channel Initiation
When using explicit Secure Channel initiation, SCP02 mandates the use of a MAC on the EXTERNAL AUTHENTICATE command.
For the EXTERNAL AUTHENTICATE command MAC verification, the ICV is set to zero.
Once successfully verified, the MAC of the EXTERNAL AUTHENTICATE command becomes the ICV for the subsequent C-MAC verification and/or R-MAC generation.


I hole that would be useful for you.

Post Reply Previous topicNext topic

Who is online

Users browsing this forum: No registered users and 1 guest

JavaCard OS : Disclaimer