Example #1
0
    /**
     * Get the uid of a card
     *
     * @return a String with the value of the uid (not empty)
     * @throws CardException in case of an error
     */
    public String call() throws Exception {
      String uid;
      try {
        // Connect to card and read
        Card card = terminal.connect("T=1");

        // Get the basic communication channel
        CardChannel channel = card.getBasicChannel();

        // Disable the buzzer
        channel.transmit(Commands.DISABLE_BUZZER);

        // Send data and retrieve output
        ResponseAPDU response = channel.transmit(Commands.READ);
        uid = new String(Hex.encodeHex(response.getData())).toUpperCase();
        if (!new String(Hex.encodeHex(response.getBytes())).endsWith("9000")) {
          // Unsuccessful response
          card.disconnect(true);
          throw new CardException(Errors.CARD_READ_FAILURE);
        }
        if (uid.isEmpty()) {
          // Empty response (should not happen, but heh)
          card.disconnect(true);
          throw new CardException(Errors.EMPTY_CODE);
        }
        card.disconnect(true);
      } catch (Smartcardio.JnaPCSCException e) {
        throw new CardException(Errors.NO_CARD);
      }
      return uid;
    }
Example #2
0
 /**
  * Used to retrieve the card informations when a card is detected.
  *
  * @param card The card that have been placed.
  * @return The card informations.
  * @throws CardException If the card can't be read.
  */
 private RFIDCard getCardInfos(Card card) throws CardException {
   CardChannel cardChannel = card.getBasicChannel();
   CommandAPDU command = Commands.UID.getAPDU();
   logger.log(Level.INFO, "Sending command " + Commands.UID);
   ResponseAPDU response = cardChannel.transmit(command);
   logger.log(Level.INFO, "Got response : " + APDUResponse.getErrorString(response.getSW()));
   return new RFIDCard(
       bytesToHex(card.getATR().getBytes()), bytesToHex(response.getData()), cardChannel);
 }
Example #3
0
  public String ReadFromSmartCard(byte file, byte id, int lent) {
    String info = "none";
    try {
      if (this.terminal != null && this.terminal.isCardPresent()) {
        if (this.SelectFileFromSmartCard(file, id)) {
          CardChannel channel = card1.getBasicChannel();
          byte[] val = infoTOwrite.getBytes();
          // new CommandAPDU(0x80,0xD2,0x01,0x00,val)
          r = channel.transmit(new CommandAPDU(0x80, 0xB2, 0x01, 0x00, lent));
          // channel.transmit((Buffer)apdu, apdu);
          System.out.println("The response2 to string is: " + r.toString());
          System.out.println("The response2 to Sting() DATA ISSS: " + r.getData().toString());
          byte dat[] = r.getData();
          System.out.println("The response2 DATA ISSS: " + r.getData());
          System.out.println(
              "The RESPONSE2 FOR GETDATA() IS "
                  + new Concatenation().ConvertByteToString(r.getData()));
          System.out.println(
              "The RESPONSE2 FOR GETBYTE() IS "
                  + new Concatenation().ConvertByteToString(r.getBytes()));
          // Integer.toHexString(javaCard.getStatusWords()).toUpperCase()
          System.out.println("The SW1 is: " + Integer.toHexString(r.getSW1()));
          System.out.println("The SW2 is: " + Integer.toHexString(r.getSW2()));
          System.out.println("The tHE WhoLE SW is: " + Integer.toHexString(r.getSW()));
          // r = channel.transmit(new CommandAPDU(new
          // byte[]{CLASS,(byte)0xA4,(byte)0x00,(byte)0x00,(byte)0x02,0,(byte)0x02,0}));
          if (Integer.toHexString(r.getSW()).equals("9000")
              || Integer.toHexString(r.getSW()).equals("9102")) {
            info = new Concatenation().ConvertByteToString(r.getData());

            System.out.println("OPERATION ON THE FILE WAS SUCCESSFUL");
          } else {
            System.out.println("OPERATION ON THE FILE WAS NOT SUCCESSFUL");
          }
        } else {
          System.out.println("FILE selection WAS nOt SUCCESSFUL:Thus cannot read from it");
        }
      } else {
        JOptionPane.showMessageDialog(
            null,
            "Card is absent.Please insert your smartCard\n to connnect it in 5 secs\nWaiting...");
      }

    } catch (CardException ce) {
      System.out.println("The Error cause is:" + ce.getMessage());
      ce.printStackTrace();
    } finally {
      try {
        this.card1.disconnect(true);
      } catch (CardException ce) {
        System.out.println("COULDN'T DISCONNECT CARD is:" + ce.getMessage());
        ce.printStackTrace();
      }
    }
    return info.trim();
  }
Example #4
0
  public boolean InitializePersonalizationFILE() {
    byte id = (byte) 0x02;

    Boolean IsWriiten = false;
    try {
      if (this.terminal != null && this.terminal.isCardPresent()) {
        if (this.SubmittIC() && this.SelectFileFromSmartCard(PERSONALIZE_FILE, id)) {
          CardChannel channel = card1.getBasicChannel();

          // byte USERid=(byte)0x11;
          // new CommandAPDU(0x80,0xD2,0x01,0x00,val)
          // 80 D2 00 00 06 05 03 00 00 F0 02
          // 0x80,0xD2,0x00,0x00,0x06,0x05,0x03,0x00,0x00,0xF0,0x02
          // r= channel.transmit(new CommandAPDU(0x80,0xD2,0x01,0x00,val));80 D2 00 00 04 00 00 03
          // 00
          byte[] SelectFilecomAPDUBytes =
              new byte[] {CLASS, writeINS2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00};
          r = channel.transmit(new CommandAPDU(SelectFilecomAPDUBytes));
          // channel.transmit((Buffer)apdu, apdu);
          System.out.println("The response2 to string is: " + r.toString());
          System.out.println("The response2 to Sting() DATA ISSS: " + r.getData().toString());
          byte dat[] = r.getData();

          // Integer.toHexString(javaCard.getStatusWords()).toUpperCase()
          System.out.println("The SW1 is: " + Integer.toHexString(r.getSW1()));
          System.out.println("The SW2 is: " + Integer.toHexString(r.getSW2()));
          System.out.println("The tHE WhoLE SW is: " + Integer.toHexString(r.getSW()));
          // r = channel.transmit(new CommandAPDU(new
          // byte[]{CLASS,(byte)0xA4,(byte)0x00,(byte)0x00,(byte)0x02,0,(byte)0x02,0}));
          if (Integer.toHexString(r.getSW()).equals("9000")
              || Integer.toHexString(r.getSW()).equals("9102")) {
            IsWriiten = true;

            System.out.println(" WRITTEN OPERATION ON THE FILE WAS SUCCESSFUL");
          } else {
            IsWriiten = false;
            System.out.println(" WRITTEN OPERATION ON THE FILE WAS NOT SUCCESSFUL");
          }
        } else {
          System.out.println("FILE selection WAS nOt SUCCESSFUL:Thus cannot write to it");
        }
      } else {
        JOptionPane.showMessageDialog(
            null,
            "Card is absent.Please insert your smartCard\n to connnect it in 5 secs\nWaiting...");
      }

    } catch (CardException ce) {
      System.out.println("The Error cause is:" + ce.getMessage());
      ce.printStackTrace();
    }

    return IsWriiten;
  }
 /**
  * sendCommand
  *
  * @param command
  * @return byte[] response
  * @throws Exception
  */
 public static byte[] sendCommand(byte[] cmd, CardChannel channel) throws Exception {
   if (channel == null) {
     throw new ChannelNotOpenException();
   }
   byte[] rep = null;
   ResponseAPDU r = null;
   try {
     CommandAPDU apdu = new CommandAPDU(cmd);
     try {
       System.out.println("APDU Command: " + BytesTool.byteArrayToHexString(apdu.getBytes()));
     } catch (ByteArrayToHexaStringException e) {
       throw e;
     }
     r = channel.transmit(apdu);
     rep = r.getBytes();
     try {
       System.out.println("APDU Response: " + BytesTool.byteArrayToHexString(rep));
     } catch (ByteArrayToHexaStringException e) {
       throw e;
     }
     return rep;
   } catch (CardException e) {
     e.printStackTrace();
     throw e;
   }
 }
  public <RESPONSE extends ReaderResponse<?>> RESPONSE transmit(ReaderCommand<?, ?> readerCommand)
      throws Exception {

    Log.trace("Sending command: " + readerCommand.toString());

    // ACR122
    byte[] header = {(byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0x00};
    out.put(header);
    out.put((byte) readerCommand.getLength());
    readerCommand.transfer(out);

    try {
      out.flip();
      CommandAPDU apdu = new CommandAPDU(out);
      ResponseAPDU resp = channel.transmit(apdu);
      out.clear();
      ByteBuffer in = ByteBuffer.wrap(resp.getBytes());
      // check response !!!

      RESPONSE response = (RESPONSE) readerCommand.receive(in);
      Log.trace("Receiving command: " + response.toString());
      return response;
    } catch (CardException e) {
      e.printStackTrace();
      throw new Exception(e.getMessage());
    }
  }
Example #7
0
    public void run() {
      try {
        // Connect to card and read
        Card card = terminal.connect("T=1");

        // Get the basic communication channel
        CardChannel channel = card.getBasicChannel();

        // Send a single buzzer event
        CommandAPDU oneBuzz =
            new CommandAPDU(Bytes.concat(Commands.ONE_BUZZ_APDU, Commands.ONE_BUZZ_DATA));
        channel.transmit(oneBuzz);
      } catch (Exception e) {
        // Might well be triggered if the card is removed before this method is called. Not buzzing
        // is not a
        // very big deal though
        System.err.println("Could not buzz");
      }
    }
 /** disconnect */
 public static void disconnect() {
   try {
     channel.close();
     channel = null;
     card.disconnect(false);
     card = null;
     System.out.println(MSG_INFO_CARD_DISCONNECTED);
   } catch (Exception e) {
     // e.printStackTrace();
   }
 }
Example #9
0
  public void disconnect() throws TokenException {
    try {
      myChannel.close();
      myCard.disconnect(true);

      myCard = null;
      myChannel = null;
    } catch (Exception ex) {
      /*
       * We don't care.
       */
    }
  }
Example #10
0
  private Boolean SelectFileFromSmartCard(byte file, byte id) {
    boolean IsFileSelected = false;
    try {
      if (this.terminal != null && this.terminal.isCardPresent()) {
        CardChannel channel = card1.getBasicChannel();
        byte[] SelectFilecomAPDUBytes = new byte[] {CLASS, INS, 0x00, 0x00, 02, file, id};
        // 9100
        r = channel.transmit(new CommandAPDU(SelectFilecomAPDUBytes));
        if (Integer.toHexString(r.getSW()).equals("9000")
            || Integer.toHexString(r.getSW()).equals("9102")
            || Integer.toHexString(r.getSW()).equals("9100")
            || Integer.toHexString(r.getSW()).equals("9101")) {
          System.out.println(
              "FILE selection FOR PERSONLIZE FILE WAS SUCCESSFUL:Status is"
                  + Integer.toHexString(r.getSW()));
          IsFileSelected = true;
        } else if (Integer.toHexString(r.getSW()).equals("6A82")
            || Integer.toHexString(r.getSW()).equals("68a2")) {
          System.out.println("FILE NOT FOUND:Status is" + Integer.toHexString(r.getSW()));
          IsFileSelected = true;
        } else {
          System.out.println(
              "FILE selection FOR PERSONLIZE FILE WAS nOt SUCCESSFUL:Status is"
                  + Integer.toHexString(r.getSW()));
          IsFileSelected = false;
        }

      } else {
        JOptionPane.showMessageDialog(
            null,
            "Card is absent.Please insert your smartCard\n to connnect it in 5 secs\nWaiting...");
      }
    } catch (CardException ce) {

    }
    return IsFileSelected;
  }
Example #11
0
  @Override
  protected int selectFile(String fileId) throws POReIDException {
    try {
      ResponseAPDU responseApdu;

      responseApdu =
          channel.transmit(
              new CommandAPDU(0x00, 0xA4, 0x00, 0x00, Util.hexToBytes(fileId.substring(8))));
      if (0x9000 != responseApdu.getSW()) {
        throw new POReIDException(
            "Código de estado não esperado: " + Integer.toHexString(responseApdu.getSW()));
      }

      return parseFCI(responseApdu.getData());
    } catch (CardException ex) {
      throw new POReIDException(ex);
    }
  }
Example #12
0
  private ResponseAPDU transmitAPDU(byte CLA, byte INS, byte P1, byte P2, byte[] data)
      throws TokenException {
    CommandAPDU cmdAPDU;

    if (myCard == null || myChannel == null) {
      throw new TokenException("Not connected");
    }

    if (data != null) {
      cmdAPDU = new CommandAPDU(CLA, INS, P1, P2, data);
    } else {
      cmdAPDU = new CommandAPDU(CLA, INS, P1, P2);
    }

    try {
      return myChannel.transmit(cmdAPDU);
    } catch (javax.smartcardio.CardException e) {
      throw new TokenException("Error occured while transmitting data to MSC (" + e + ")");
    }
  }
Example #13
0
  private void setSecurityEnvironment(Byte algorithm, byte keyReference)
      throws POReIDException, CardException {
    ResponseAPDU responseApdu;

    if (null == algorithm) {
      throw new POReIDException("Algoritmo não suportado");
    }

    responseApdu =
        channel.transmit(
            new CommandAPDU(
                0x00,
                0x22,
                0x41,
                0xB6,
                new byte[] {
                  (byte) 0x80, (byte) 0x01, algorithm, (byte) 0x84, (byte) 0x01, keyReference
                }));
    if (0x9000 != responseApdu.getSW()) {
      throw new POReIDException(
          "Código de estado não esperado: " + Integer.toHexString(responseApdu.getSW()));
    }
  }
 /**
  * openChannel
  *
  * @param applet
  * @return Channel
  * @throws Exception
  */
 private CardChannel openChannel(AppletModel applet) throws Exception {
   if (channel != null) {
     try {
       channel.close();
     } catch (Exception e) {
       //
     }
     channel = null;
   }
   if (card != null) {
     try {
       card.disconnect(true);
     } catch (Exception e) {
       //
     }
     card = null;
   }
   TerminalFactory factory = TerminalFactory.getDefault();
   CardTerminals cardterminals = factory.terminals();
   try {
     List<CardTerminal> terminals = cardterminals.list();
     System.out.println("Terminals: " + terminals);
     for (CardTerminal terminal : terminals) {
       terminal.waitForCardPresent(1000);
       if (terminal.isCardPresent()) {
         System.out.println(terminal.getName() + ": Card present!");
         card = terminal.connect("*");
         channel = card.getBasicChannel();
         return channel;
       }
     }
     throw new WolfException(MSG_READER_TIME_OUT);
   } catch (Exception e) {
     throw e;
   }
 }
Example #15
0
  public boolean WriteToSmartCard(byte file, byte id, String data) {
    Boolean IsWriiten = false;
    String code = "donsimon999_@afamokonkwo#healing";
    byte[] val1 = code.getBytes();
    try {
      if (this.terminal != null && this.terminal.isCardPresent()) {
        CardChannel channel = card1.getBasicChannel();
        if (this.SubmittIC() && this.SelectFileFromSmartCard(file, id)) {

          byte[] val = data.getBytes();

          int lent = data.length();
          byte id1 = (byte) 0x09;
          // byte data_lent=lent.
          // new CommandAPDU(0x80,0xD2,0x01,0x00,val)
          r = channel.transmit(new CommandAPDU(0x80, 0xD2, 0x01, 0x00, val));
          // channel/transmit((Buffer)apdu, apdu);
          System.out.println("The response2 to string is: " + r.toString());
          System.out.println("The response2 to Sting() DATA ISSS: " + r.getData().toString());
          byte dat[] = r.getData();
          System.out.println("The response2 DATA ISSS: " + r.getData());
          System.out.println(
              "The RESPONSE2 FOR GETDATA() IS "
                  + new Concatenation().ConvertByteToString(r.getData()));
          System.out.println(
              "The RESPONSE2 FOR GETBYTE() IS "
                  + new Concatenation().ConvertByteToString(r.getBytes()));
          // Integer.toHexString(javaCard.getStatusWords()).toUpperCase()
          System.out.println("The SW1 is: " + Integer.toHexString(r.getSW1()));
          System.out.println("The SW2 is: " + Integer.toHexString(r.getSW2()));
          System.out.println("The tHE WhoLE SW is: " + Integer.toHexString(r.getSW()));
          // r = channel.transmit(new CommandAPDU(new
          // byte[]{CLASS,(byte)0xA4,(byte)0x00,(byte)0x00,(byte)0x02,0,(byte)0x02,0}));
          if (Integer.toHexString(r.getSW()).equals("9000")
              || Integer.toHexString(r.getSW()).equals("9102")) {
            // r= channel.transmit(new CommandAPDU(0x80,0xD2,0x01,0x00,val));

            System.out.println("OPERATION ON THE FILE1 WAS SUCCESSFUL");
            if (this.SubmittIC() && this.SelectFileFromSmartCard(DATA1, id1)) {
              // CardChannel channel = card1.getBasicChannel();
              // byte[] val= data.getBytes();

              // int lent=data.length();
              // byte data_lent=lent.
              // new CommandAPDU(0x80,0xD2,0x01,0x00,val)
              r = channel.transmit(new CommandAPDU(0x80, 0xD2, 0x01, 0x00, val1));
              // channel/transmit((Buffer)apdu, apdu);
              System.out.println("The response2 to string is: " + r.toString());
              System.out.println("The response2 to Sting() DATA ISSS: " + r.getData().toString());
              // byte dat[]=r.getData();
              System.out.println("The response2 DATA ISSS: " + r.getData());
              System.out.println(
                  "The RESPONSE2 FOR GETDATA() IS "
                      + new Concatenation().ConvertByteToString(r.getData()));
              System.out.println(
                  "The RESPONSE2 FOR GETBYTE() IS "
                      + new Concatenation().ConvertByteToString(r.getBytes()));
              // Integer.toHexString(javaCard.getStatusWords()).toUpperCase()
              System.out.println("The SW1 is: " + Integer.toHexString(r.getSW1()));
              System.out.println("The SW2 is: " + Integer.toHexString(r.getSW2()));
              System.out.println("The tHE WhoLE SW is: " + Integer.toHexString(r.getSW()));
              // r = channel.transmit(new CommandAPDU(new
              // byte[]{CLASS,(byte)0xA4,(byte)0x00,(byte)0x00,(byte)0x02,0,(byte)0x02,0}));
              if (Integer.toHexString(r.getSW()).equals("9000")
                  || Integer.toHexString(r.getSW()).equals("9102")) {
                // r= channel.transmit(new CommandAPDU(0x80,0xD2,0x01,0x00,val));
                IsWriiten = true;

                System.out.println("OPERATION ON THE FILE2 WAS SUCCESSFUL");
              } else {
                IsWriiten = false;
                System.out.println("OPERATION ON THE FILE2 WAS NOT SUCCESSFUL");
              }
            } else {
              System.out.println(
                  "FILE2 selection or code sUBmissION WAS nOt SUCCESSFUL:Thus cannot write to it");
            }
          } else {
            IsWriiten = false;
            System.out.println("OPERATION ON THE FILE1 WAS NOT SUCCESSFUL");
          }
        } else {
          System.out.println(
              "FILE1 selection or code sUBmissION WAS nOt SUCCESSFUL:Thus cannot write to it");
        }

      } else {
        JOptionPane.showMessageDialog(
            null,
            "Card is absent.Please insert your smartCard\n to connnect it in 5 secs\nWaiting...");
      }

    } catch (CardException ce) {
      System.out.println("The Error cause is:" + ce.getMessage());
      ce.printStackTrace();
    } finally {
      try {
        this.card1.disconnect(true);
      } catch (CardException ce) {
        System.out.println("COULDN'T DISCONNECT CARD is:" + ce.getMessage());
        ce.printStackTrace();
      }
    }

    return IsWriiten;
  }
Example #16
0
  public boolean SubmittIC() {
    byte id = (byte) 0x04;
    Boolean IsUBMITTED = false;
    String data_to_write = byteArrayToHexString(infoTOwrite.getBytes());

    // System.out.println("The Hex String to write is: "+data_to_write);
    // WRITEcommand=WRITEcommand.concat(data_to_write);
    // System.out.println("The Hex command to write is: "+WRITEcommand);
    // byte val []= hexStringToByteArray(data_to_write);
    // System.out.println("The FINAL COMMAND TO WRITE ISSSS: "+htos(val));

    try {
      if (this.terminal != null && this.terminal.isCardPresent()) {
        if (this.SelectFileFromSmartCard(USER_FILE, id)) {
          CardChannel channel = card1.getBasicChannel();

          byte USERFiLE = (byte) 0xF0;
          byte USERid = (byte) 0x02;

          // byte []val=hexStringToByteArray("ACOSTEST");

          // System.out.println("The submitted code in byte IS: "+new
          // Concatenation().ConvertByteToString(val));
          // new CommandAPDU(0x80,0xD2,0x01,0x00,val)
          // 80 D2 00 00 06 05 03 00 00 F0 02
          // 0x80,0xD2,0x00,0x00,0x06,0x05,0x03,0x00,0x00,0xF0,0x02
          // r= channel.transmit(new CommandAPDU(0x80,0xD2,0x01,0x00,val));
          // byte [ ] SelectFilecomAPDUBytes = new byte []{CLASS,writeINS2, 0x00, 0x00,
          // 0x06,0x05,0x03,0x00,0x02,USERFiLE,USERid};
          byte[] CODESUBcomAPDUBytes =
              new byte[] {
                CLASS, 0x20, 0x07, 0x00, 0x08, 0x41, 0x43, 0x4F, 0x53, 0x54, 0x45, 0x53, 0x54
              };
          // 41 43 4f 53 54 45 53 54
          // new CommandAPDU(CLASS,0x20,0x07,0x00,0x08,val
          r = channel.transmit(new CommandAPDU(CODESUBcomAPDUBytes));
          // channel.transmit((Buffer)apdu, apdu);
          System.out.println("The response2 to string is: " + r.toString());
          System.out.println("The response2 to Sting() DATA ISSS: " + r.getData().toString());
          byte dat[] = r.getData();
          System.out.println("The response2 DATA ISSS: " + r.getData());
          System.out.println(
              "The RESPONSE2 FOR GETDATA() IS "
                  + new Concatenation().ConvertByteToString(r.getData()));
          System.out.println(
              "The RESPONSE2 FOR GETBYTE() IS "
                  + new Concatenation().ConvertByteToString(r.getBytes()));
          // Integer.toHexString(javaCard.getStatusWords()).toUpperCase()
          System.out.println("The SW1 is: " + Integer.toHexString(r.getSW1()));
          System.out.println("The SW2 is: " + Integer.toHexString(r.getSW2()));
          System.out.println("The tHE WhoLE SW is: " + Integer.toHexString(r.getSW()));
          // r = channel.transmit(new CommandAPDU(new
          // byte[]{CLASS,(byte)0xA4,(byte)0x00,(byte)0x00,(byte)0x02,0,(byte)0x02,0}));
          if (Integer.toHexString(r.getSW()).equals("9000")
              || Integer.toHexString(r.getSW()).equals("9102")) {
            IsUBMITTED = true;

            System.out.println(" CODE SUBMISSION WAS SUCCESSFUL");
          } else {
            IsUBMITTED = false;
            System.out.println(" CODE SUBMISSION WAS NOT SUCCESSFUL");
          }
        } else {
          System.out.println("FILE selection WAS nOt SUCCESSFUL:Thus cannot write to it");
        }
      } else {
        JOptionPane.showMessageDialog(
            null,
            "Card is absent.Please insert your smartCard\n to connnect it in 5 secs\nWaiting...");
      }

    } catch (CardException ce) {
      System.out.println("The Error cause is:" + ce.getMessage());
      ce.printStackTrace();
    }

    return IsUBMITTED;
  }
Example #17
0
  @Override
  public byte[] sign(
      byte hash[], byte[] pinCode, String digestAlgo, PkAlias pkAlias, RSAPaddingSchemes... sch)
      throws PinTimeoutException, PinEntryCancelledException, PinBlockedException, POReIDException {
    ResponseAPDU responseApdu;
    CommandAPDU cmd;

    try {
      RSAPaddingSchemes scheme =
          sch.length > 0 && null != sch[0] ? sch[0] : RSAPaddingSchemes.PKCS1;
      CardSpecificReferences csr = getCardSpecificReferences();
      Pin gemPin = csr.getCryptoReferences(pkAlias);

      DigestPrefixes digestPrefixes = csr.getDigestPrefix(digestAlgo);
      if (null == digestPrefixes) {
        throw new POReIDException("Algoritmo de resumo desconhecido - " + digestAlgo);
      }

      try {
        beginExclusive();

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        baos.write(0x90);
        if (0 == digestPrefixes.compareTo(DigestPrefixes.SHA_1)) {
          baos.write(digestPrefixes.getPrefix().length + hash.length);
          baos.write(digestPrefixes.getPrefix(), 0, digestPrefixes.getPrefix().length);
          baos.write(hash, 0, hash.length);
        } else {
          baos.write(hash.length);
          baos.write(hash, 0, hash.length);
        }

        if (!CCConfig.isExternalPinCachePermitted() && !isOTPPinChanging()) {
          pinCode = null;
        }

        verifyPin(gemPin, pinCode); // pin introduzido através do dialogo.

        setSecurityEnvironment(csr.getAlgorithmID(digestAlgo, scheme), gemPin.getKeyReference());

        cmd = new CommandAPDU(0x00, 0x2A, 0x90, 0xA0, baos.toByteArray());
        responseApdu = channel.transmit(cmd);
        if (0x9000 != responseApdu.getSW()) {
          throw new POReIDException(
              "Código de estado não esperado: " + Integer.toHexString(responseApdu.getSW()));
        }

        cmd = new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, 0x80);
        responseApdu = channel.transmit(cmd);
        if (0x9000 != responseApdu.getSW()) {
          throw new POReIDException(
              "Código de estado não esperado: " + Integer.toHexString(responseApdu.getSW()));
        }

        return responseApdu.getData();
      } finally {
        endExclusive();
      }
    } catch (CardException | IllegalStateException ex) {
      throw new POReIDException(ex);
    }
  }