I have below function which is supposed to return 8 byte host cryptogram based on length of derived data "L" but I am getting 16 bytes data. Although key is 128 bits, I was expecting BC AESCMAC function will return data based on value of L in the derivation data. If this is not the case, do I need to extract MS 8 Bytes from output. Below is my function -
private String scp03CalculatehostCryptogram(byte[] derivedSMACSessionKey, String hostChallenge, String cardChallenge) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, UnsupportedEncodingException {
// Reference : GPC_2.2_D_SCP03_v1.1.1 > 6.2.2.3 Host Authentication Cryptogram - The host cryptogram (8 bytes) is calculated using the data derivation scheme defined in section 4.1.5 with the session key S-MAC and the derivation constant set to “host authentication cryptogram generation”. The length of the cryptogram shall be reflected in the parameter “L” (i.e. '0040'). The “context” parameter shall be set to the concatenation of the host challenge (8 bytes) and the card challenge (8 bytes).
String labelForSMAC = "000000000000000000000001";
String separationIndicator = "00";
String lInteger = "0040";
String counter = "01";
String context = hostChallenge.concat(cardChallenge);
String hostCryptogramDerivationData = labelForSMAC.concat(separationIndicator).concat(lInteger).concat(counter).concat(context);
byte[] hostCryptogramDerivationDataBytes = DatatypeConverter.parseHexBinary(hostCryptogramDerivationData);
System.out.println(" Host Cryptogram Derivation data : "+DatatypeConverter.printHexBinary(hostCryptogramDerivationDataBytes));
Mac aescmac = Mac.getInstance("AESCMAC", "BC");
SecretKey scpENCKeyObject = new SecretKeySpec(derivedSMACSessionKey, "AES");
aescmac.init(scpENCKeyObject);
aescmac.update(hostCryptogramDerivationDataBytes);
byte[] hostCryptogram = aescmac.doFinal();
System.out.println(" Calculated Host Cryptogram : "+DatatypeConverter.printHexBinary(hostCryptogram));
return DatatypeConverter.printHexBinary(hostCryptogram);
}
Output :
Host Cryptogram Derivation data : 0000000000000000000000010000400161BD435249EC20B7AA984A2D47AD4302
Calculated Host Cryptogram : 6F405B9FD1438A4633A4289B618A1FB5
Example - derived smac session key : 47297387E512687FBEB37D1C1F4B8F4C
what am I doing wrong?
The length L is included in the input of the crytogram to make the output of the cryptogram as specific as possible.
Obviously the MAC algorithm won't pay any respect to the input. A MAC simply takes a key, input and then produces a predefined amount of data. Your function is supposed to create the cryptogram. This cryptogram requires the size of the output data L as parameter. So if you're not producing the required amount of output data then that's up to you.
And yes, in general if an output of a PRF (e.g. your function) needs to be resized then the leftmost bytes are taken.