Krishna
Krishna

Reputation: 263

ISO 9797-1 MAC algorithm 3 and padding method 1 example in Java?

Looking through Java Cryptography Architecture and some code examples, I have learned how to calculate Mac using Mac class:

Please find the below code to calculate MAC:

Mac mac = Mac.getInstance("HmacSHA256");
mac.init(<secretKeyHere>);
byte[] macHash = mac.doFinal(<encryptedTextHere>);

But actually I am looking for a way to calculate Mac using the ISO 9797-1 Algorithm 3(Retail MAC) and padding 1 (if necessary, add bits with value 0 to the end of the data until the padded data is a multiple of n, where n is the block size of the DES cipher, i.e. 8).

Can anyone please suggest code example in java?

Upvotes: 1

Views: 5279

Answers (1)

mnistic
mnistic

Reputation: 11020

BouncyCastle includes a ready-to-use class to calculate "Retail MAC".

Usage example:

public byte[] getRetailMAC(byte[] key, byte[] data) {
    BlockCipher cipher = new DESEngine();
    Mac mac = new ISO9797Alg3Mac(cipher, 64, new ISO7816d4Padding());

    KeyParameter keyP = new KeyParameter(key);
    mac.init(keyP);
    mac.update(data, 0, data.length);

    byte[] out = new byte[8];

    mac.doFinal(out, 0);

    return out;
}

To use optional zero padding you need to perform your padding yourself as Bouncy Castle does always pad, even when performing the ill-defined zero padding.

public byte[] getRetailMAC(byte[] key, byte[] data) {
    int macSizeBits = 64;

    BlockCipher cipher = new DESEngine();

    Mac mac = new ISO9797Alg3Mac(cipher, macSizeBits);

    KeyParameter keyP = new KeyParameter(key);
    mac.init(keyP);
    mac.update(data, 0, data.length);

    // perform padding manually - NOT REQUIRED, SEE UPDATE
    int n = cipher.getBlockSize();
    int zeroPaddingRequired = n - (data.length + n - 1) % n - 1; 
    for (int i = 0; i < zeroPaddingRequired; i++) {
        mac.update((byte) 0x00);
    }

    byte[] out = new byte[macSizeBits / Byte.SIZE];
    mac.doFinal(out, 0);

    return out;
}

Note that this kind of padding does not distinguish between messages that end with one or more zero valued bytes (and if the number of blocks of 8 bytes remains the same). For that reason it is not secure for messages where only the number of bytes is pre-defined.

UPDATE:

The manual padding is unnecessary because this padding mode (type 1 in the spec) is actually the default and performed within the MAC implementation. So you would get this when not supplying any padding. Note that this is not the same as supplying ZeroBytePadding because the last one always pads.

Upvotes: 1

Related Questions