Question

Je dois lire le numéro de compte dans Maestro / Mastercard avec un lecteur de carte à puce. J'utilise Java 1.6 et son package javax.smartcardio. J'ai besoin d'envoyer une commande APDU qui demandera à l'application EMV stockée sur la puce de la carte le numéro PAN. Le problème, c’est que je ne trouve pas un tableau d’octets régulier pour construire une commande APDU qui renverra les données nécessaires n’importe où ...

Était-ce utile?

La solution

Vous ne devriez plus avoir besoin d'envelopper l'APDU. La couche API devrait s’occuper de cela.

Il semble que la réponse 0x6D00 signifie simplement que l'application ne prend pas en charge l'INS.

Vous venez de résoudre le problème maintenant, mais vous avez commencé par sélectionner l'application MasterCard, n'est-ce pas?

I.e. quelque chose comme ceci:

void selectApplication(CardChannel channel) throws CardException {
  byte[] masterCardRid = new byte[]{0xA0, 0x00, 0x00, 0x00, 0x04};
  CommandAPDU command = new CommandAPDU(0x00, 0xA4, 0x04, 0x00, masterCardRid);
  ResponseAPDU response = channel.transmit(command);
  return response.getData();
}

Autres conseils

voici quelques exemples de travail:

CardChannel channel = card.getBasicChannel(); 

 byte[] selectMaestro={(byte)0x00, (byte)0xA4,(byte)0x04,(byte)0x00 ,(byte)0x07 ,(byte)0xA0 ,(byte)0x00 ,(byte)0x00 ,(byte)0x00 ,(byte)0x04 ,(byte)0x30 ,(byte)0x60 ,(byte)0x00};
  byte[] getProcessingOptions={(byte)0x80,(byte)0xA8,(byte)0x00,(byte)0x00,(byte)0x02,(byte)0x83,(byte)0x00,(byte)0x00};
  byte[] readRecord={(byte)0x00,(byte)0xB2,(byte)0x02,(byte)0x0C,(byte)0x00};

  ResponseAPDU r=null;

   try {
     ATR atr = card.getATR(); //reset kartice

      CommandAPDU capdu=new CommandAPDU( selectMaestro   );

       r=card.getBasicChannel().transmit( capdu );

      capdu=new CommandAPDU(getProcessingOptions);
      r=card.getBasicChannel().transmit( capdu );


      capdu=new CommandAPDU(readRecord);
      r=card.getBasicChannel().transmit( capdu );

Cela fonctionne avec la carte Maestro, je peux lire le numéro PAN, mais je dois maintenant lire le numéro PAN de MasterCard. Je ne sais pas si je dois changer l'APDU d'enregistrement en lecture ou sélectionner l'APDU d'application. Toute personne familière avec les APDU?

atr = open();
prints(atr);

prints("[Step 1] Select 1PAY.SYS.DDF01 to get the PSE directory");
cmd = new ISOSelect(ISOSelect.SELECT_AID, EMV4_1.AID_1PAY_SYS_DDF01);
card_response = execute(cmd);
prints(card_response);
SFI = NumUtil.hex2String((byte)((1 < < 3) | 4));

// try SFI 1 record 1
prints("[Step 2] Send READ RECORD with 0 to find out where the record is");
read = new EMVReadRecord(SFI, "01", "00");
card_response = execute(read);
prints(card_response);
byte_size = NumUtil.hex2String(card_response.getStatusWord().getSw2());

prints("[Step 3] Send READ RECORD with 1C to get the PSE data");
read = new EMVReadRecord(SFI, "01", byte_size);
card_response = execute(read);
prints(card_response);
// the AID is A0000000031010
prints("[Step 4] Now that we know the AID, select the application");

cmd = new ISOSelect(ISOSelect.SELECT_AID, "A0000000031010");
card_response = execute(cmd);
prints(card_response);
prints("[Step 5] Send GET PROCESSING OPTIONS command");

cmd = new EMVGetProcessingOptions();
card_response = execute(cmd);
prints(card_response);

// SFI for the first group of AFL is 0C

prints("[Step 6] Send READ RECORD with 0 to find out where the record is");
read = new EMVReadRecord("0C", "01", "00");
card_response = execute(read);
prints(card_response);
byte_size = NumUtil.hex2String(card_response.getStatusWord().getSw2());

prints("[Step 7] Use READ RECORD with the given number of bytes to retrieve the data");
read = new EMVReadRecord("0C", "01", byte_size);
card_response = execute(read);
prints(card_response);

data = new TLV(card_response.getData());

close();

Vous devez créer un objet CommandAPDU et le transmettre à la commande Transmettre ().

Vous devriez pouvoir trouver la commande précise dans la documentation de votre carte à puce, mais voici un exemple:

byte[] readFile(CardChannel channel) throws CardException {
  CommandAPDU command = new CommandAPDU(0xB0, 0x60, 0x10, 0x00);
  ResponseAPDU response = channel.transmit(command);
  return response.getData();
}

Avez-vous essayé de chercher dans votre documentation ce que 0x6D00 signifie? Il semble que cela pourrait signifier que la commande ENVELOPE n'est pas prise en charge. Avez-vous essayé d'utiliser le protocole T = 0 au lieu de T = 1?

Je ne m'attendrais pas à ce que mon exemple fonctionne sur votre carte. Je ne sais pas quelles APDU sont prises en charge par Maestro / MasterCard, je ne peux donc pas vous donner un exemple concret.

Essayez de donner à la commande une longueur attendue explicite comme ceci:

byte[] readPan(CardChannel channel) throws CardException {
  CommandAPDU command = new CommandAPDU(0x00, 0xB2, 0x5a, 0x14, 250);
  ResponseAPDU response = channel.transmit(command);
  return response.getData();
}

Qu'en est-il d'utiliser un scanner, obtenir une image de la carte, numériser le contenu de l'image avec une bonne bibliothèque java ocr (comme http://ocr4j.sourceforge.net/ par exemple) et recherchez une séquence (généralement) de 16 chiffres XXXX-XXXX-XXXX-XXXX, puis vous obtiendrez le PAN de toute carte EMV en utilisant java.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top