title: Reading information from the smart card by secure messaging
body: <p>I have tachograph company card which is used to get the client authenticated before allowing him to download the data of the tachograph by the remote download. The used APDU command
  in my code below are commands of successfully authentication between the Tachograph and company card.</p>
  
  <p>The connection between the both parties is accomplished as the following:</p>
  
  <p>Tachograph &lt;--can cable-->  device &lt;---Bluetooth--> Android app &lt;--Socket API--> Company Card Server &lt;--USB cabel--> company card reader &lt;--> company card.</p>
  
  <p>The communication as described above is working well and the app user is getting authenticated. Now I am trying to read some information fom the company card directly without the app as the following:</p>
  
  <p>My Client Programm &lt;--> card reader &lt;--> company card </p>
  
  <p>In my client programm I am using the same APDU commands which are sent from the Android App to the company card. Currently, I am facing Problem with the external authentication
  with INS tag "82". I am getting the error <code>66 88</code> which means <code>wrong certification</code>.</p>
  
  <p>I have downloaded a certification file <code>D__TCC40-1.bin</code> from the </p>
  
  <p><a href="https://dtc.jrc.ec.europa.eu/dtc_public_key_certificates.php" rel="nofollow noreferrer">https://dtc.jrc.ec.europa.eu/dtc_public_key_certificates.php</a></p>
  
  <p>The Public Key Certification content is described as the following:</p>
  
  <blockquote>
    <p>128 Byte Signature + 58 byte Public Key reminder + 8 byte Certification Authorithy Reference = 194 byte</p>
  </blockquote>
  
  <p>when reading the file <code>D__TCC40-1.bin</code> it has <code>194</code> bytes length (The company card uses as well a certification of the length 194). The external authentication bassically starts with the ´84´ INS command.
  This command is sent to the smart card by the terminal to deliver 8 digits random number. Subsequently, the terminal receives the random number and encrypte it with some
  encryption algotrithm that uses a public key for encryption. Afterwards, the terminal sends the encrypted number by the alogrithm to the smart card with the <code>82</code> INS tag.</p>
  
  <p>Now I am trying to load the downloaded certificate <code>D__TCC40-1.bin</code> from the project root and use it to encrypte the 8 digits random number which I am getting with
  the GET CHALLANGE <code>84</code> INS tag  but I do not know how can I encrypte it with the alogrithm to sent its result to the smart card.
  How can I use <code>Public Key Certificate</code> to encyrpte the random number to sent it to the smart card to get the <code>90 00</code> as a reponse?  Currently, as I mentioned before I am getting the <code>66 88</code> as a Response.</p>
  
  <p><a href="https://i.stack.imgur.com/FYSEq.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/FYSEq.png" alt="enter image description here"></a></p>
  
  <p><a href="https://i.stack.imgur.com/wtRxZ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/wtRxZ.png" alt="enter image description here"></a></p>
  
  <p>***Code*</p>
  
  <pre><code>import java.io.FileInputStream;
  import java.io.FileNotFoundException;
  import java.io.IOException;
  import java.util.List;
  
  import javax.smartcardio.ATR;
  import javax.smartcardio.Card;
  import javax.smartcardio.CardChannel;
  import javax.smartcardio.CardException;
  import javax.smartcardio.CardTerminal;
  import javax.smartcardio.CommandAPDU;
  import javax.smartcardio.ResponseAPDU;
  import javax.smartcardio.TerminalFactory;
  import javax.xml.bind.DatatypeConverter;
  
  
  public class CardIdTest {
  
      static CardChannel channel = null;
      static byte[] signature = null;
  
  
      public static void main(String[] args) {
  
          try {
  
              try {
                  FileInputStream ecPubKeyFIS = new FileInputStream("D__TCC40-1.bin");
  
                  try {
                      int certificateLength = ecPubKeyFIS.available();
                      byte[] certificate = new byte[certificateLength];
                      ecPubKeyFIS.read(certificate);
  
                      CardIdTest.signature = new byte[128];
                      System.arraycopy(certificate, 0, CardIdTest.signature, 0, 128);
                      int sigLength = CardIdTest.signature.length;
  
                      byte[] publicKeyReminder = new byte[58];
                      System.arraycopy(certificate, 128, publicKeyReminder, 0, 58);
                      int PKLength = publicKeyReminder.length;
  
                      byte[] certificationAuthorithyReference = new byte[8];
                      System.arraycopy(certificate, 186, certificationAuthorithyReference, 0, 8);
                      int referenceLength = certificationAuthorithyReference.length;
                      System.out.println("End");
                  } catch (IOException e1) {
                      // TODO Auto-generated catch block
                      e1.printStackTrace();
                  }
              } catch (FileNotFoundException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              }
  
              TerminalFactory factory = TerminalFactory.getDefault();
              List&lt;CardTerminal&gt; terminals = factory.terminals().list();
              CardTerminal terminal = terminals.get(0);
              Card card = terminal.connect("T=1");
              System.out.println("Terminals list: " + terminals);
              ATR atr = card.getATR();
              byte[] atrArray = atr.getBytes();
              String atrHex = CardIdTest.byteArrayToHexString(atrArray);
              System.out.println("ATR: " + atrHex);
              CardIdTest.channel = card.getBasicChannel();
  
              String command1 = "00 a4 02 0c 02 00 02"; // select EF_ICC file.
              CardIdTest.execute(command1, 1);
              String command2 = "00 b0 00 00 09";  // Read binary
              String cardExtendedSerialNumberTemp = CardIdTest.execute(command2, 2);
              String cardExtendedSerialNumber = cardExtendedSerialNumberTemp.substring(4);
              String command3 = "00 a4 04 0c 06 ff 54 41 43 48 4f"; // select DF file or master file.
              CardIdTest.execute(command3, 3);
              String command4 = "00 a4 02 0c 02 05 01"; // select 05 01 elementary file.
              CardIdTest.execute(command4, 4);
              String command5 = "00 b0 00 00 01"; // read the binary byte.
              CardIdTest.execute(command5, 5);
              String command6 = "00 22 c1 b6 0a 83 08 00 00 00 05 09 02 ff a1"; // issse security managment environment.
              CardIdTest.execute(command6, 6);
              String command8 = "00 88 00 00 10 e9 96 79 ec 74 27 e6 50 00 00 00 05 09 02 ff a1 80"; // internal authentication.
              CardIdTest.execute(command8, 8);
              String command9 = "00 84 00 00 08"; // Get Challange / 8 digits random number
              String exteranlAuthenticationChallange = CardIdTest.execute(command9, 9);
              String digitalSignature = CardIdTest.byteArrayToHexString(CardIdTest.signature);
              String command10 = "00 82 00 00 80 " + digitalSignature; // eternal authentication.
              CardIdTest.execute(command10, 10);
              String command11 = "00 a4 02 0c 02 05 01"; // select 05 01 file
              String command12 = "0c b0 00 00 09 97 01 01 8e 04 1e ee 49 a1 00"; // read the birnay of the selected file.
  
              card.disconnect(true); // reset
  
          } catch (CardException e) {
  
              e.printStackTrace();
          }
  
      }
  
  
      private static String execute(String commandWithSpace, int number) throws CardException {
          String commandWithoutSpace = commandWithSpace.replace(" ", "");
          byte[] apdu = DatatypeConverter.parseHexBinary(commandWithoutSpace);
          CommandAPDU command = new CommandAPDU(apdu);
          ResponseAPDU responseAPDU = CardIdTest.channel.transmit(command);
          byte[] reponseData = responseAPDU.getData();
          String response = responseAPDU.toString();
          if (reponseData.length &gt; 0) {
              String msg = new String(reponseData);
              String dataHex = CardIdTest.byteArrayToHexString(reponseData);
              System.out.println("command       (" + number + ")   (*" + apdu.length + "): " + commandWithSpace);
  
              System.out.println("response with data:  ( #" + msg.length() + ") :" + dataHex);
              System.out.println("msg: " + msg);
              return dataHex;
  
          } else {
              byte[] bytes = responseAPDU.getBytes();
              String responseHex = CardIdTest.byteArrayToHexString(bytes);
              System.out.println("command        (" + number + ")   (*" + apdu.length + "): " + commandWithSpace);
              System.out.println("response without data :" + responseHex);
              return responseHex;
          }
      }
  
  
      public static String byteArrayToHexString(byte[] byteArray) {
          StringBuilder sb = new StringBuilder();
  
          for (byte b : byteArray) {
              sb.append(String.format(" %02x", b));
          }
          return sb.toString();
  
      }
  
  
      public static byte[] hexStringToByteArray(String s) {
          int len = s.length();
          byte[] data = new byte[len / 2];
          for (int i = 0; i &lt; len; i += 2) {
              data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) &lt;&lt; 4) + Character.digit(s.charAt(i + 1), 16));
          }
          return data;
      }
  
      public static String byteArrayToHex(byte[] byteArray) {
          StringBuilder sb = new StringBuilder();
          for (byte b : byteArray) {
              sb.append(String.format(" %02x", b));
          }
          return sb.toString();
  
      }
  
  }
  </code></pre>
  
  <p><strong>Output with the 66 88 error</strong></p>
  
  <pre><code>Terminals list: [PC/SC terminal Generic Smart Card Reader Interface 0]
  ATR:  3b 9f 96 c0 0a 31 fe 45 43 54 31 69 0b 01 00 01 00 00 00 00 00 00 00 0d
  command        (1)   (*7): 00 a4 02 0c 02 00 02
  response without data : 90 00
  command       (2)   (*5): 00 b0 00 00 09
  response with data:  ( #9) : 00 00 01 98 fa 03 16 14 ad
  command        (3)   (*11): 00 a4 04 0c 06 ff 54 41 43 48 4f
  response without data : 90 00
  command        (4)   (*7): 00 a4 02 0c 02 05 01
  response without data : 90 00
  command       (5)   (*5): 00 b0 00 00 01
  response with data:  ( #1) : 04
  command        (6)   (*15): 00 22 c1 b6 0a 83 08 00 00 00 05 09 02 ff a1
  response without data : 90 00
  command       (8)   (*22): 00 88 00 00 10 e9 96 79 ec 74 27 e6 50 00 00 00 05 09 02 ff a1 80
  response with data:  ( #128) : 7f 96 43 f2 ee d9 44 34 2d 09 b6 c3 47 a0 08 28 6d 3f 3d 30 e8 3d 82 fb 21 e0 5f 7a 3e bd 99 f9 ba 4c 2c c5 56 df fc cc b1 7e 66 bc 9a 26 b0 0e 53 52 fe d7 51 a3 84 75 f6 7d 3a 24 48 d1 a4 fe 8d 82 0e a8 bb 10 2d f2 51 8d 0c 6c 96 0f 0b 2a e3 a7 ce 5c d9 27 91 8f 7c 2b 21 1c f5 fa 65 cd 5f 5c e6 6f 1c a5 ad 27 4a 57 c3 16 76 0b 06 e1 d8 fc af 20 ce 48 61 1d 53 48 f9 78 5b b9 3a c1
  command       (9)   (*5): 00 84 00 00 08
  response with data:  ( #8) : 06 ba 52 a6 34 7a fe 30
  command        (10)   (*133): 00 82 00 00 80  9b 33 b2 68 9a 71 93 3b 50 c2 4d 65 95 e7 84 59 db 40 77 e1 40 a1 b1 a3 b9 8c a8 a1 fb 36 ac b5 a6 2b 60 b3 63 f8 dd 77 de ad a1 4d ab 39 ab cc c8 79 51 aa d1 7a 97 bd 16 c3 d8 2d dd 74 cf 98 47 89 b9 36 d0 02 43 29 f6 69 2d a5 1f f2 27 89 ad fb 81 3d 47 93 08 e4 56 7c 4f 0d a1 b8 07 4e cb 9b 18 80 73 33 75 2b c9 dc de c4 ce 96 71 07 d8 5f 6d 20 f6 a3 09 88 87 8c 69 ec 6f de 51 ca
  response without data : 66 88
  </code></pre>
  
  <p><strong>By the way the code to read the information of the driver card works without secure messaging and looks like the following:</strong></p>
  
  <pre><code>        // String masterFile = "00 A4 04 0C 06 FF544143484F";
          // String elementaryFile = "00 A4 02 0C 02 0520";
          // String readBinary = "00 B0 00 01 10";
  </code></pre>