Now where have I read that before.....
Can anyone shed light on calculating the DES MAC ?
This appears to be the offical definition:
DES cipher-block chained checksum (des-mac)
The DES-MAC checksum is computed by prepending an 8 octet confounder to the plaintext, performing a DES CBC-mode encryption on the result using the key and an initialization vector of zero, taking the last block of the ciphertext, prepending the same confounder and encrypting the pair using DES in cipher-block-chaining (CBC) mode using a a variant of the key, where the variant is computed by eXclusive-ORing the key with the constant F0F0F0F0F0F0F0F0. The initialization vector should be zero. The resulting checksum is 128 bits (16 octets) long, 64 bits of which are redundant. This checksum is tamper-proof and collision-proof.
+--+--+--+--+--+--+--+--+---+---+---+---+---+---+---+---+---+---+---+
| des-cbc(confounder des-mac(conf+msg,iv=0,key),key=var(key),iv=0) |
+--+--+--+--+--+--+--+--+---+---+---+---+---+---+---+---+---+---+---+
Look Here -> |
Now where have I read that before.....
Member since March 2002 and still in the Blue
From somewhere else
How to make EMK
Format of EMK is:
C3 HSHSHS 00LN 0102 682400 11111111111111111111111111111111 22222222222222222222222222222222 PIPIPI MCMCMCMCMCMCMCMC
C3 = PMK (Group Key) update EMK
HS = 3 byte HSN
LN = Length of payload (0x30)
01 = Payload message start Position
02 = length of message
68 = PMK update nano
24 = length of update message
00 = Provider index (00 = 00, 01 = 10, 02 = 20, etc...)
11 = 16 byte PMK0 (Group Key 0)
22 = 16 byte PMK1 (Group Key 1)
PI = 3 byte provider id
MC = DES cipher-block chained checksum (DES MAC)
Say your card details are:
Init Vector (IV_PAD) = AFB049FC408D4D2C91B8588E3B691C47
HMK0 (AxiKey) = DE4C418B54D3F10F26E2255EE1FBB6EB
HMK1 (ExiKey) = 563487E47BC21CD07F6DCB023C6D467F
HSN = 123456
The new Provider ID and PMKs are:
ProvID = 098765
PMK0 (GroupKey 0) = 21A635184323AA64D04109FEBF195128
PMK1 (GroupKey 1) = 5961BBF128805F5B17576E74B81ACB49
Construct your PMK update message using the for 0x68 nano format
C3 123456 0030 0102 682400 21A635184323AA64D04109FEBF195128 5961BBF128805F5B17576E74B81ACB49 098765
Next calculate the DES MAC of the complete EMK using the Init Vector AFB049FC408D4D2C91B8588E3B691C47
and the HMK1 3DES key 563487E47BC21CD07F6DCB023C6D467F (Have a look at the gammasource code for the MAC function).
The MAC is calculated starting from the C3 all the way to the last byte.
The MAC for EMK is: 388BF7F2542757EE
So the EMK update with MAC is now
C3 123456 0030 0102 682400 21A635184323AA64D04109FEBF195128 5961BBF128805F5B17576E74B81ACB49 098765 388BF7F2542757EE
Now we begin to encrypt the EMK.
First we encrypt the PMK (Group Keys) only using the Init Vector and HMK1 (ExiKey) with Triple DES encryption in CBC mode.
21A635184323AA64D04109FEBF195128 5961BBF128805F5B17576E74B81ACB49
encrypts to:
0184BE4D56C79B7B5A95F6FB8F200124 0D2DB7694412021A3C94CCD5E5C69362
Put the encrypted keys into EMK update message:
C3 123456 0030 0102 682400 0184BE4D56C79B7B5A95F6FB8F200124 0D2DB7694412021A3C94CCD5E5C69362 098765 388BF7F2542757EE
Second we encrypt the EMK from the start payload using the Init Vector but this time HMK0 (AxiKey) with Triple DES encryption in CBC mode.
0102 682400 0184BE4D56C79B7B5A95F6FB8F200124 0D2DB7694412021A3C94CCD5E5C69362 098765 388BF7F2542757EE
encrypts:
2A0F 63349B 0E250B61E63FDB22639D8D9A37284971 389D9BEB6A7618DDFBB66A6E9F986DA1 420718 0227E06D6FAF653C
The finished result is -
C3 123456 0030 2A0F 63349B 0E250B61E63FDB22639D8D9A37284971 389D9BEB6A7618DDFBB66A6E9F986DA1 420718 0227E06D6FAF653C
To test with card send this
C3123456000000302A0F63349B0E250B61E63FDB22639D8D9A 37284971389D9BEB6A7618DDFBB66A6E9F986DA14207180227 E06D6FAF653C
Cheers, Saintaholic
Managed to work this lot out already. The part I don't understand is calculating the 8 byte MAC which is not described in the above post. Maybe I need to invest in C++ for Dummies
This Info is from the same forum as above, same/similar question was asked there and reply was...
"Here is code to calculate the DES MAC. Just pass the required data into the function "MakeMAC" "
(post#15 in a thread "gama crc calculator" )
This one from same forum thread "To create 0201 cmd ..." post #43Code:void EncryptCBCString (unsigned char *TripleDesKey, unsigned char *InitialXOR, unsigned char *Data, unsigned int datalen) { unsigned char xorbuffer1[8]; unsigned int i; unsigned int y; for (i=0;i<8;i++) xorbuffer1[i] = InitialXOR[i]; for (y=0;y<(datalen>>3);y++) { for (i=0;i<8;i++) Data[(y*8)+i] = Data[(y*8)+i] ^ xorbuffer1[i]; Encrypt3DES (TripleDesKey,(Data+(y*8)),(Data+(y*8))); for (i=0;i<8;i++) xorbuffer1[i] = Data[(y*8)+i]; } } int MakeMAC(unsigned char *CryptBuffer, unsigned char *Key, unsigned char *IV_PAD, unsigned char *Data2Sign, unsigned int DataLen) { unsigned char keybuffer[24]; unsigned int i; unsigned int y; unsigned int z; for (i=0;i<16;i++) keybuffer[i] = Key[i]; for (i=0;i<8;i++) keybuffer[16+i] = Key[i]; for (i=0;i<8;i++) { CryptBuffer[i] = 0; } z = 0; for (y=0;y<((DataLen>>3));y++) { for (i=0;i<8;i++) { if (((y*8)+i) < (DataLen - 8)) { CryptBuffer[i] = Data2Sign[(y*8)+i] ^ CryptBuffer[i]; } else { CryptBuffer[i] = IV_PAD[8+z] ^ CryptBuffer[i]; z++; } } Encrypt3DES (keybuffer,CryptBuffer,CryptBuffer); } return DataLen; }
Im sure you have read this before I have ages ago..Code:#include "stdafx.h" #include "des.h" #include <string.h> #include <stdio.h> #include <stdlib.h> /* required for randomize() and random() */ #include <time.h> void Decrypt3DES(unsigned char *TripleDesKey, unsigned char *InData, unsigned char *OutData) { des_ctx desA; // for store subkey A des_ctx desB; // for store subkey B des_setkey (desA, TripleDesKey); // Generate subkey des_setkey (desB, TripleDesKey+8); // Generate subkey des_ecb_crypt (desA, InData , OutData,1); // Encryption des_ecb_crypt (desB, OutData, OutData,0); // Decryption des_ecb_crypt (desA, OutData, OutData,1); // Encryption } void Encrypt3DES(unsigned char *TripleDesKey, unsigned char *InData, unsigned char *OutData) { des_ctx desA; // for store subkey A des_ctx desB; // for store subkey B des_setkey (desA, TripleDesKey); // Generate subkey des_setkey (desB, TripleDesKey+8); // Generate subkey des_ecb_crypt (desA, InData , OutData,0); // Encryption des_ecb_crypt (desB, OutData, OutData,1); // Decryption des_ecb_crypt (desA, OutData, OutData,0); // Encryption } void DecryptCBCString (unsigned char *TripleDesKey, unsigned char *InitialXOR, unsigned char *Data, unsigned int datalen) { unsigned char xorbuffer1[8]; unsigned char xorbuffer2[8]; unsigned char cryptbuffer[8]; unsigned int i; unsigned int y; for (i=0;i<8;i++) xorbuffer1[i] = InitialXOR[i]; for (y=0;y<(datalen>>3);y++) { for (i=0;i<8;i++) xorbuffer2[i] = Data[(y*8)+i]; for (i=0;i<8;i++) cryptbuffer[i] = Data[(y*8)+i]; Decrypt3DES (TripleDesKey,cryptbuffer,cryptbuffer); for (i=0;i<8;i++) Data[(y*8)+i] = cryptbuffer[i] ^ xorbuffer1[i]; for (i=0;i<8;i++) xorbuffer1[i] = xorbuffer2[i]; } } void EncryptCBCString (unsigned char *TripleDesKey, unsigned char *InitialXOR, unsigned char *Data, unsigned int datalen) { unsigned char xorbuffer1[8]; unsigned int i; unsigned int y; for (i=0;i<8;i++) xorbuffer1[i] = InitialXOR[i]; for (y=0;y<(datalen>>3);y++) { for (i=0;i<8;i++) Data[(y*8)+i] = Data[(y*8)+i] ^ xorbuffer1[i]; Encrypt3DES (TripleDesKey,(Data+(y*8)),(Data+(y*8))); for (i=0;i<8;i++) xorbuffer1[i] = Data[(y*8)+i]; } } int MakeMAC(unsigned char *CryptBuffer, unsigned char *Key, unsigned char *IV_PAD, unsigned char *Data2Sign, unsigned int DataLen) { unsigned char keybuffer[24]; unsigned int i; unsigned int y; unsigned int z; for (i=0;i<16;i++) keybuffer[i] = Key[i]; for (i=0;i<8;i++) keybuffer[16+i] = Key[i]; for (i=0;i<8;i++) { CryptBuffer[i] = 0; } z = 0; for (y=0;y<((DataLen>>3));y++) { for (i=0;i<8;i++) { if (((y*8)+i) < (DataLen - 8)) { CryptBuffer[i] = Data2Sign[(y*8)+i] ^ CryptBuffer[i]; } else { CryptBuffer[i] = IV_PAD[8+z] ^ CryptBuffer[i]; z++; } } Encrypt3DES (keybuffer,CryptBuffer,CryptBuffer); } return DataLen; } int Pad (unsigned char *msg, int len) { int i; for (i = len; i % 8; i++) msg[i] = 0x00; return i; } unsigned char CalculateCRC(unsigned char *msg, int len) { unsigned char CRC = 0x3F; int i; for (i = 0; i < len; i++) { CRC = CRC ^ msg[i]; } return CRC; } unsigned int CalculateMAC(unsigned char *Key, unsigned char *IV_PAD, unsigned char *Data2Sign, unsigned int DataLen) { unsigned char CryptBuffer[8]; unsigned char MACBuffer[8]; unsigned char keybuffer[24]; unsigned int i; unsigned int y; unsigned int z; for (i=0;i<16;i++) keybuffer[i] = Key[i]; for (i=0;i<8;i++) keybuffer[16+i] = Key[i]; for (i=0;i<8;i++) { CryptBuffer[i] = 0; MACBuffer[i] = Data2Sign[DataLen-8+i]; } z = 0; for (y=0;y<((DataLen>>3));y++) { for (i=0;i<8;i++) { if (((y*8)+i) < (DataLen-8)) { CryptBuffer[i] = Data2Sign[(y*8)+i] ^ CryptBuffer[i]; } else { CryptBuffer[i] = IV_PAD[8+z] ^ CryptBuffer[i]; z++; } } Encrypt3DES (keybuffer,CryptBuffer,CryptBuffer); } return memcmp(CryptBuffer, MACBuffer,8); } int CreateUpdateCmd(unsigned char *cmd, unsigned char *KeyE, int KeyIndex, unsigned char *update, int DataLen) { unsigned char CARDINIT_IV[] = {0x1A, 0x8A, 0xCB, 0x5B, 0x5E, 0x6D, 0x72, 0x7D, 0x91, 0x47, 0x7B, 0x2D, 0xF2, 0xEB, 0xDD, 0x45}; unsigned char ZEROXOR[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; unsigned char CARDMASK[] = {0x9C, 0x88, 0x36, 0x30, 0x1E, 0x60, 0xD0, 0x99, 0x91, 0xCF, 0x9F, 0xCC, 0xCF, 0x6C, 0xDF, 0x87}; unsigned char KeyA[16]; unsigned char PDU[] = {0x02, 0x01, 0x00, 0x00, 0x00}; unsigned char CRC; // Pad out command DataLen = Pad(update, DataLen); memcpy (&update[DataLen], ZEROXOR, 8); // Generate MAC key; memcpy (KeyA, CARDMASK, 16); EncryptCBCString(KeyE, ZEROXOR, KeyA, 16); // Calculate Signature DataLen = MakeMAC(&update[DataLen], KeyA, CARDINIT_IV, update, DataLen + 8); // Encrypt command EncryptCBCString(KeyE, CARDINIT_IV, update, DataLen); memcpy(cmd, PDU, sizeof(PDU)); // append encrypted update memcpy(&cmd[6], update, DataLen); // set length cmd[5] = DataLen; // set key index; cmd[3] = KeyIndex; // add PDU header DataLen += 6; // Calculate CRC CRC = CalculateCRC (cmd, DataLen); // set CRC cmd[DataLen++] = CRC; return DataLen; }
Davo
Last edited by davo; 12-05-10 at 05:37 PM. Reason: added 2nd half.
best4less (12-05-10),OzBlackKnight (13-05-10)
All a bit cryptic for me (pardon the pun). What does it all mean in plain and simple language I wonder
The code appears to do the following:
It performs a progressive XOR on the 8 byte blocks in the string, using an initial ZEROXOR. The final block before the MAC only has 6 bytes, so two bytes are added at the end from the IV_PAD (from position '8' on)
It then does an Encrypt3DES on the 8 byte result from above using an initial value of zero. The resulting 8 bytes is then compared with the MAC from the decrypted string.
I have tried this using the Exi key example given above, but don't get the same answer. I think the DES key must be manipulated before doing the 3DES calculation.
Any comments ?
Last edited by Hillsbysa; 20-05-10 at 04:59 PM.
It's all Belgian to me mate but keep up the good work......It takes a fair wad of patience to get your head around that stuff...
Cheers mate, it's easier than I thought. Simply do an ECB 3DES encryption (or CBC 3DES with zero ICV) of the decrypted C3 string using the Axi key. All that BS about prepending 8 octet confounders really confounded me for a while LOL
Last edited by Hillsbysa; 23-05-10 at 08:53 AM. Reason: more info
fred121 (25-05-10)
I believe IVPad is a 16 byte string common to all sellers cards, however I may be mistaken.
florra (23-05-10)
So are you saying that every sellers card has the same IVPad as per the example above?
where do the gmask & pmask fit into the picture
gmsk & pmsk I assume they would be gmask=gmask & pmsk=pmask
woteva
off topic
Last edited by davo; 23-05-10 at 11:55 PM.
So is there any way of finding the IV PAD of the sellers card or is it one of those things that only those in the know, know?
This is good
cheers
Bookmarks