Miura M010 & Shuttle
The Miura Shuttle and M010 mobile payment terminals are PCI PTS 3.0 certified. They support Secure Reading, Exchange of Data (SRED) and open protocols. Both can be certified as part of the Decryptx point to point encryption (P2PE) solution. The M010 is EMV Level 1 and 2 (contact and contactless) certified, enabling the delivery of essential cryptographic and key management processing requirements (DES, TDES, RSA, DUKPT).
Miura devices support magnetic stripe, keyed and EMV (contact and contactless) input. They have Bluetooth, USB and TCP/IP interfaces, and are designed to operate as counter-top and mobile devices. Mobile devices will typically use the Bluetooth interface, whereas point of sale (POS) applications will use the serial USB or TCP/IP over wireless network interfaces. While the pin entry devices (PED) support multiple interfaces, the commands sent and responses received from them are the same no matter which interface is used. Miura supplies software development kits (SDKs) for a wide variety of operating systems and development languages on their developer's portal. They make it easy for the POS application or mobile device to obtain data from the payment terminal.
Raw commands and SDKs
As mentioned above, the Miura PEDs are designed to work over Bluetooth and USB. These interfaces consume command strings and produce response strings in an asynchronous fashion. As with most devices that utilize a Bluetooth interface, keeping these command strings compact is a high priority; they use a single byte to represent a command and as few bytes as possible. For example, the request 010004D0020000D4
has a prologue of 010004
and an LRC at end of D4
; the actual command of D0020000
requests the device information.
MiuraManager.getInstance().getSoftwareInfo(new ApiGetSoftwareInfoListener() {
@Override
public void onSuccess(SoftwareInfo softwareInfo) {
//information can be accessed here.
}
@Override
public void onError() {
System.out.println( "Error occurred" );
}
});
Identifying the serial number
A version of the serial number is printed on the back of the device. The printed value typically has a dash, e.g, 010-589951; however, the API expects that the serial value will drop the dash and leading zero to, e.g., 10589951. The serial number can also be identified by sending a GET DEVICE INFO command to the PED. The raw request is 010004D0020000D4
. The following sample code uses the Miura Android SDK to extract the serial number from the M010. Miura provides similar SDKs in Python, Objective-C, and several other languages. While the programming languages are different, the software uses a similar pattern when extracting the encrypted data from the terminal.
MiuraManager.getInstance().getSoftwareInfo(new ApiGetSoftwareInfoListener() {
@Override
public void onSuccess(SoftwareInfo softwareInfo) {
System.out.println( "Serial Number" + softwareInfo.getSerialNumber() );
}
});
Once you have the serial numbers, you need to extract the payload and key serial number (KSN). By default, all the readers (mag stripe, chip, and contactless) are disabled on the M010.
Swiped Payloads
To capture a magnetic stripe payload, send the CARD STATUS command to the device. The card status command queries the EMV slot to see if a card is inserted. It also enables or disables unsolicited card swipes. In the following Android code, connectionDelegate is attached, listens for card status changes, and CARD STATUS is set to true.
MiuraManager.getInstance().setConnectionDelegate(connectionDelegate);
MiuraManager.getInstance().cardStatus(true, null);
The following is a sample class that listens for a card swipes. When a card is swiped, or inserted into the EMV slot, a CardData object is passed into the onCardStatusChange method. In this example, the card data object is checked for Track 2 data. If Track 2 data is present, you know it is a magnetic stripe payload and will contain SRED and KSN data.
private MPIConnectionDelegate connectionDelegate = new MPIConnectionDelegate() {
public void onCardStatusChange( CardData cardData ) {
if ( cardData.getTrack2Data() != null ) {
final String payload = cardData.getSredData();
final String ksn = cardData.getSredKSN();
}
}
}
The following is a sample P2PE encrypted magnetic strip payload and associated KSN:
Payload
0e64f89987343361346fcb63419cadb9733be3d555c4024294d1ec7c9fc6997010313c15212628348b22f0cec67ab5d5c7ee63c01dd28644aad4ba94223dc224089a142d5db1a3adf7803b3396269154a5584b8c61bbffa7f382ff713e28d3cd
KSN
fffff001030000200001
Decrypting the payload results in the following tag length value (TLV) formatted data.
What is TLV?
Tag length value (TLV) is a data encoding scheme. Values are appended to a string in triplets. The first field in the triplet is the "type" of data being processed, the second field specifies the "length" of the value, the third field contains a "length" amount of data representing the value for the "type". Typically, the type and length fields are fixed in size (typically 1-4 bytes).
Multiple pieces of data can be transmitted in the same string by appending more triplets to a previously existing string.
5f21312542343132343933393939393939393939305e544553542f424c554546494e5e323231323130313132333435363738393f5f22243b343132343933393939393939393939303d323231323130313132333435363738393f3b0000000000
This data is parsed as follows:
Chars | Value | Description |
---|---|---|
1-4 | 5f21 | Tag ID: Track 1 Data |
5-6 | 31 | Tag length (Decimal 49) |
7-104 | 254234...38393f | Track 1 data in hexadecimal; the ASCII value is: %B4124939999999990^TEST/BLUEFIN^2212101123456789? |
105-108 | 5f22 | Tag ID: Track 2 data |
109-110 | 24 | Tag length (Decimal 36) |
111-182 | 3b3431...393f3b | Track 2 data in hexadecimal; the ASCII value is: ;4124939999999990=2212101123456789?; |
183-192 | 0000000000 | padding |
The following are the Track 1 and Track 2 data extracted from the payload when converted from hex to ASCII.
Track 1
%B4124939999999990^TEST/BLUEFIN^2212101123456789?
Track 2
;4124939999999990=2212101123456789?;
EMV (Chip & Pin) Payloads
To capture an EMV payload, begin by sending the same CARD STATUS command to the M010. When the CardData object is passed to the onCardStatusChange method of the MPIConnectionDelegate it will have a number of properties that will inform you whether the card is EMV enabled cardData.getCardStatus().isEMVCompatible() and in the chip reader slot cardData.getCardStatus().isCardPresent(). If both are true, initiate an EMV transaction with the START TRANSACTION command.
The following sample code initiates an EMV transaction. The code specifies the transaction type, the transaction amount, and the currency code. Attached to the command is an ApiStartTransactionListener with code that is executed once the application receives data from the contactless transaction. Included in this data are the encrypted payload and the KSN. Also, included in the data is issuer/acquirer data which can be checked before a CONTINUE TRANSACTION command is sent.
MiuraManager.getInstance().setConnectionDelegate(connectionDelegate);
MiuraManager.getInstance().cardStatus(true, null);
private MPIConnectionDelegate connectionDelegate = new MPIConnectionDelegate() {
@Override
public void onCardStatusChange( CardData cardData ) {
if (cardData.getCardStatus().isCardPresent() && cardData.getCardStatus().isEMVCompatible()) {
MiuraManager.getInstance().startTransaction(TransactionType.Purchase, transactionInfo.getAmount(), MiuraApplication.currencyCode.getValue(), new ApiStartTransactionListener() {
@Override
public void onSuccess(byte[] result) {
List<TLVObject> tlvObjects = TLVParser.decode(result);
final TLVObject payloadObj = CommandUtil.firstMatch( tlvObjects, Description.SRED_Data );
final TLVObject ksnObj = CommandUtil.firstMatch( tlvObjects, Description.SRED_KSN );
final String payload = payloadObj.getData();
final String ksn = ksnObj.getData();
}
});
}
}
}
The following is a sample EMV payload and associated KSN:
Payload
cdeb04ca81940babb24acf4ffa9d6b77fb52c6bc0890edbcfc518c7b724d1be1
KSN
fffff00103000020001b
Decrypting the payload results in a TLV formatted string with a number of standard EMV TLV values, including:
- 5A: Application Primary Account Number (PAN).
- 57: Track 2 Equivalent Data.
5a08476173900101011957134761739001010119d22122011143804400000f00
This data is parsed as follows:
Chars | Value | Description |
---|---|---|
1-2 | 5a | Tag ID: Application Primary Account Number (PAN) |
3-4 | 08 | Tag length (Decimal 8) |
5-20 | 476173...010119 | PAN |
21-22 | 57 | Tag ID: Track 2 Equivalent Data |
23-24 | 13 | Tag length (Decimal 19) |
25-62 | 476173...00000f | Track 2 Equivalent Data |
63-64 | 00 | padding |
Contactless Payloads
Because the form factor of the M010 PED is quite compact, there is a risk of the device accidentally reading a contactless payload when a user attempts to swipe their card; therefore, the M010’s contactless reader is disabled by default. A START CONTACTLESS TRANSACTION command must be sent to the PED to enable it.
The following sample code initiates a contactless transaction. Attached to the command is an ApiStartTransactionListener with code that is executed once the application receives data from the contactless transaction. Included in this data are the encrypted payload and the KSN.
MiuraManager.getInstance().startContactlessTransaction(TransactionType.Purchase, transactionInfo.getAmount(),
MiuraApplication.currencyCode.getValue(), new ApiStartTransactionListener() {
@Override
public void onSuccess(byte[] result) {
List<TLVObject> tlvObjects = TLVParser.decode(result);
final TLVObject payloadObj = CommandUtil.firstMatch( tlvObjects, Description.SRED_Data );
final TLVObject ksnObj = CommandUtil.firstMatch( tlvObjects, Description.SRED_KSN );
final String payload = payloadObj.getData();
final String ksn = ksnObj.getData();
}
});
The following is a sample contactless payload and associated KSN:
Payload
c31b8d370f9edc2d6bc2af63d49f9b37372a481653d1df25
KSN:
fffff00103000020004d
If we decrypt the payload we get a TLV formatted string with a single standard EMV TLV value:
- 57: Track 2 Equivalent Data.
57134761739001010119d22122011143804400000f00
This data is parsed as follows:
Chars | Value | Description |
---|---|---|
1-2 | 57 | Tag ID: Track 2 Equivalent Data |
3-4 | 13 | Tag length (Decimal 19) |
5-42 | 476173...00000f | Track 2 Equivalent Data |
43-44 | 00 | padding |
Keyed Payloads
To capture keyed card data, send the command GET SECURE PAN to the device. A prompt is displayed on the device to enter card data. Once the user presses the enter key the encrypted payload and KSN data are returned. The encrypted payload contains the PAN data only; expiry date and/or CVV must be retrieved separately via a GET TEXT command.
The MiuraManager class does not have a method to initiate a keyed payload capture; therefore, you must use the low-level command to retrieve the PAN. The command string to request the PAN is 01000FD25A00010AE008DFA2060400000001
where 01000F
is the prologue, D25A
is the command request a secure PAN, 0001
configures the backlight (0001
is on; 0000
is off) and 0AE008DFA2060400000001
specifies the index of the prompt text.
BaseBluetooth.getInstance().setDelegate(connectionDelegate, commandDelegate);
final byte[] dataField = BinaryUtil.parseHexBinary( "E008DFA2060400000001" );
final byte[] command = MPICommandCreator.createCommand(InterfaceType.MPI, MPICommandCreator.CommandType.Get_Secure_PAN, (byte) 0, (byte) 1, dataField);
BluetoothService.getInstance().write(command);
return command;
The following sample MPICommandDelegate extracts the encrypted payload and KSN from the message:
final MPICommandDelegate commandDelegate = new MPICommandDelegate() {
@Override
public void receivedSolicitedMessage( ResponseMessage responseMessage ) {
if( responseMessage.isSuccess() && responseMessage.getBody().length > 1) {
final List<TLVObject> tlvObjects = TLVParser.decode(responseMessage.getBody());
final TLVObject payloadObj = CommandUtil.firstMatch( tlvObjects, Description.SRED_Data );
final TLVObject ksnObj = CommandUtil.firstMatch( tlvObjects, Description.SRED_KSN );
final String payload = payloadObj.getData();
final String ksn = ksnObj.getData();
}
}
});
The following is a sample keyed payload and associated KSN:
Payload
bec06a99af283f8541875de76d05ed8676aef285646ee758
KSN:
fffff00103000020004f
Decrypting the payload results in a TLV formatted string with a single custom TLV value:
- dfa208: Track 2 Equivalent Data.
dfa20810343736313733393030313031303131390000000
This data is parsed as follows:
Chars | Value | Description |
---|---|---|
1-6 | dfa208 | Tag ID: Keyed Primary Account Number (PAN). |
7-8 | 10 | Tag length (decimal 16). |
9-40 | 343736...313139 | The PAN in hexadecimal, the ASCII value is 4761739001010119. |
41-47 | 0000000 | padding |
Updated over 2 years ago