How to compute MAC
Posted: Sat Aug 29, 2015 4:13 am
Hi, everyone.
I need to implement authentication process. How can I compute the MAC data?
Thanks
I need to implement authentication process. How can I compute the MAC data?
Thanks
JavaCardOS - JavaCardForum
http://www.javacardos.com/javacardforum/
http://www.javacardos.com/javacardforum/viewtopic.php?f=12&t=103
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);
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);
}
}
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;
}