There were some enhancement changes made to security by introducing changes to the encryption of the Primary credential which is part of the API request body.
NOTE: This is still applicable for WiFi mode of operation.
Primary credential is 8 bytes (16 hex digits) in length.
The credential value is filled with b0s until the byte boundary and 0xFF for the rest of the bytes (to form an 8 byte credential ID).
MT20W fills 0xFF as the most significant 8 bytes to form a 16 byte (128 bits) block of data for encryption.
MT20W encrypts (AES 256) the 16 bytes (from step 2) using the Site Key as the encryption key and zeros for Init Vector.
This encrypted value (16 bytes OR 32 hex digits) is encoded in Base 64 format (24 bytes) and sent as the Primary credential data to ORCA.
ORCA decodes the Base 64 encoded data and then decrypts the Primary value from step 4, using the site key as the decryption key and zeros for Init Vector.
The decryption results in a 16 byte (32 hex digits) data and ORCA pulls the least significant 8 byte to get the Primary Credential value.
| Bit position | 0 -7 | 8-15 |
|---|---|---|
| Data | Raw card data | 0xFF |
Raw card data as printed on the card: 0x9400016009A4
| Unencrypted data | Encrypted data | Encoded data | Site Key | |||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Bit position | Data | Bit position | Data | Bit position | Data | Bit position | Data | |||
| 0 | 0x94 | 0 | 0xEB | 0 | 0x36 | 0 | 0xD4 | |||
| 1 | 0x00 | 1 | 0x10 | 1 | 0x78 | 1 | 0xBE | |||
| 2 | 0x01 | 2 | 0x94 | 2 | 0x43 | 2 | 0x94 | |||
| 3 | 0x60 | 3 | 0xDA | 3 | 0x55 | 3 | 0x94 | |||
| 4 | 0x09 | 4 | 0x0B | 4 | 0x32 | 4 | 0xB8 | |||
| 5 | 0xA4 | 5 | 0xCE | 5 | 0x67 | 5 | 0x3F | |||
| 6 | 0xFF | 6 | 0x42 | 6 | 0x76 | 6 | 0xF0 | |||
| 7 | 0xFF | 7 | 0xE5 | 7 | 0x4F | 7 | 0xC0 | |||
| 8 | 0xFF | 8 | 0x9E | 8 | 0x51 | 8 | 0x18 | |||
| 9 | 0xFF | 9 | 0x41 | 9 | 0x75 | 9 | 0x87 | |||
| 10 | 0xFF | 10 | 0xB7 | 10 | 0x57 | 10 | 0x24 | |||
| 11 | 0xFF | 11 | 0xCF | 11 | 0x65 | 11 | 0xE2 | |||
| 12 | 0xFF | 12 | 0xEF | 12 | 0x51 | 12 | 0x56 | |||
| 13 | 0xFF | 13 | 0x51 | 13 | 0x62 | 13 | 0xC9 | |||
| 14 | 0xFF | 14 | 0x8F | 14 | 0x66 | 14 | 0xEE | |||
| 15 | 0xFF | 15 | 0x4A | 15 | 0x50 | 15 | 0x51 | |||
| 16 | 0x37 | 16 | 0x1D | |||||||
| 17 | 0x31 | 17 | 0x40 | |||||||
| 18 | 0x47 | 18 | 0x07 | |||||||
| 19 | 0x50 | 19 | 0x6A | |||||||
| 20 | 0x53 | 20 | 0x52 | |||||||
| 21 | 0x67 | 21 | 0xA0 | |||||||
| 22 | 0x3D | 22 | 0x82 | |||||||
| 23 | 0x3D | 23 | 0xC5 | |||||||
| 24 | 0x00 | 24 | 0xDE | |||||||
| 25 | 0x9D | |||||||||
| 26 | 0x30 | |||||||||
| 27 | 0xF3 | |||||||||
| 28 | 0x5B | |||||||||
| 29 | 0x16 | |||||||||
| 30 | 0x85 | |||||||||
| 31 | 0x28 |
The Primary credential is 8-bytes (16 hex digits) in length. The following steps are used to encrypt the Primary credential:
The credential value is filled with binary bit 0s up to the byte boundary and 0xFF for the rest of the bytes (to form an 8-byte credential ID).
The MT20W fills 0xFF as the most significant 8-bytes to form a 16-byte (128 bits) block of data.
A random number of 12 bytes is generated and used as the first part of data to be encrypted. This is followed by the Primary credential of 16-bytes mentioned in the previous step.
Two additional bytes of 0x00s are added to the data to make it 30-bytes long.
CRC is calculated on this entire data and placed in the last two bytes of the 32-byte unencrypted data array.
The MT20W encrypts (AES 256) the 32-bytes (from above step) using the Site Key as the encryption key and zeros for Init Vector.
This encrypted value (32-bytes OR 64 hex digits) is encoded in Base64 format (44-bytes) and sent as the Primary credential data to ORCA.
| Bit position | 0 -11 | 12-19 | 20-27 | 28-29 | 30-31 |
|---|---|---|---|---|---|
| Data | 12-byte Random number | Raw card data padded with 0xFF to form 8 bytes | 0xFF | 0X00 | CRC-16 |
Raw card data as printed on the card: 0x9400016009A4.
| UNencrypted data | Encrypted data | Encoded data | Site Key | |||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Bit position | Data | Bit position | Data | Bit position | Data | Bit position | Data | |||
| 0 | 0xAE | 0 | 0x51 | 0 | 0x55 | 0 | 0xD4 | |||
| 1 | 0xB0 | 1 | 0xAF | 1 | 0x61 | 1 | 0xBE | |||
| 2 | 0x8A | 2 | 0x52 | 2 | 0x39 | 2 | 0x94 | |||
| 3 | 0xF2 | 3 | 0x14 | 3 | 0x53 | 3 | 0x94 | |||
| 4 | 0x44 | 4 | 0xA6 | 4 | 0x46 | 4 | 0xB8 | |||
| 5 | 0x7E | 5 | 0xB5 | 5 | 0x4B | 5 | 0x3F | |||
| 6 | 0x0C | 6 | 0xF0 | 6 | 0x61 | 6 | 0xF0 | |||
| 7 | 0x7C | 7 | 0xBC | 7 | 0x31 | 7 | 0xC0 | |||
| 8 | 0xF8 | 8 | 0xDA | 8 | 0x38 | 8 | 0x18 | |||
| 9 | 0xF5 | 9 | 0x59 | 9 | 0x4C | 9 | 0x87 | |||
| 10 | 0x3A | 10 | 0xE6 | 10 | 0x7A | 10 | 0x24 | |||
| 11 | 0x3B | 11 | 0xCB | 11 | 0x61 | 11 | 0xE2 | |||
| 12 | 0x94 | 12 | 0x11 | 12 | 0x57 | 12 | 0x56 | |||
| 13 | 0x00 | 13 | 0xA3 | 13 | 0x65 | 13 | 0xC9 | |||
| 14 | 0x01 | 14 | 0xD6 | 14 | 0x62 | 14 | 0xEE | |||
| 15 | 0x60 | 15 | 0xC9 | 15 | 0x4C | 15 | 0x51 | |||
| 16 | 0x09 | 16 | 0x80 | 16 | 0x45 | 16 | 0x1D | |||
| 17 | 0xA4 | 17 | 0x63 | 17 | 0x61 | 17 | 0x40 | |||
| 18 | 0xFF | 18 | 0x0E | 18 | 0x50 | 18 | 0x07 | |||
| 19 | 0xFF | 19 | 0x5D | 19 | 0x57 | 19 | 0x6A | |||
| 20 | 0xFF | 20 | 0xAA | 20 | 0x79 | 20 | 0x52 | |||
| 21 | 0xFF | 21 | 0xA6 | 21 | 0x59 | 21 | 0xA0 | |||
| 22 | 0xFF | 22 | 0xBE | 22 | 0x42 | 22 | 0x82 | |||
| 23 | 0xFF | 23 | 0x45 | 23 | 0x6A | 23 | 0xC5 | |||
| 24 | 0xFF | 24 | 0x22 | 24 | 0x44 | 24 | 0xDE | |||
| 25 | 0xFF | 25 | 0xCA | 25 | 0x6C | 25 | 0x9D | |||
| 26 | 0xFF | 26 | 0xFC | 26 | 0x32 | 26 | 0x30 | |||
| 27 | 0xFF | 27 | 0x43 | 27 | 0x71 | 27 | 0xF3 | |||
| 28 | 0x00 | 28 | 0xA5 | 28 | 0x70 | 28 | 0x5B | |||
| 29 | 0x00 | 29 | 0x44 | 29 | 0x72 | 29 | 0x16 | |||
| 30 | 0XE9 | 30 | 0x42 | 30 | 0x35 | 30 | 0x85 | |||
| 31 | 0x4C | 31 | 0xE9 | 31 | 0x46 | 31 | 0x28 | |||
| 32 | 0x49 | |||||||||
| 33 | 0x73 | |||||||||
| 34 | 0x72 | |||||||||
| 35 | 0x38 | |||||||||
| 36 | 0x51 | |||||||||
| 37 | 0x36 | |||||||||
| 38 | 0x56 | |||||||||
| 39 | 0x45 | |||||||||
| 40 | 0x51 | |||||||||
| 41 | 0x75 | |||||||||
| 42 | 0x6B | |||||||||
| 43 | 0x3D | |||||||||
| 44 | 0x6D |
API must decode Base 64 and decrypt the Primary value using the site key as the decryption key. The decryption results in a 32-byte (32 hex digits) data and API pulls the masked 8-bytes to get the Primary Credential value.
The following steps are used to decrypt the Primary credential:
Decode the base64 formatted Primary credential.
Decrypt the decoded data using the Site key. This results in 32-byte un-encrypted Primary credential (Byte array of Hex values).
The last two bytes of this array contains CRC. This CRC follows [LSB, MSB] format, hence reverse the CRC byte array.
Compute the CRC16 for the first 30 bytes excluding the CRC.
Compare the CRC obtained with the CRC of incoming request. If the CRC check fails, then API returns Bad Request with a message Credential data is corrupt.
Once the CRC check is passed, Primary data (Total of from Byte[12] to Byte[27] – includes raw card data (8bytes) and padded 0xFF(8bytes)), is extracted from UNencrypted data. (See the Section: Encryption Changes for Primary Credential).
This is the method used to compute CRC. 0x10FFFF is used for masking in CRC 16 calculation and 0x1021 is the polynomial used.
public uint ComputeCrc16(byte [] bytes)
{
uint crc = 0;
foreach (byte b in bytes)
{
crc ^= (uint) (b << 8);
for (int i = 0; i < 8; i++)
{
if ((crc & 0x8000)! = 0)
{
crc = (((crc << 1) & 0x10FFFF) ^ 0x1021);
}
else
{
crc <<= 1;
}
}
}
return crc;}
Last Modified: October 15, 2019