2008-11-12 18 views
9

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

Répondre

6

Vous ne devriez pas besoin d'envelopper davantage la APDU. La couche API devrait prendre soin de cela.

Il semble que la réponse 0x6D00 signifie simplement que l'application ne supportait pas l'INS. Dépannage juste maintenant, mais vous avez commencé en sélectionnant 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(); 
} 
+0

Je ne comprends pas très bien votre réponse. ma réponse a toujours frappé 0x6D00. Que dois-je faire si ma carte ne prend pas en charge INS comme vous l'avez dit? – HelmiB

0

Vous devez construire un objet CommandAPDU et le passer à la commande de transmission().

Vous devriez être en mesure de 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(); 
} 
0

Avez-vous essayé la recherche dans la documentation ce que signifie 0x6D00? Il semble que cela puisse 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 connais pas les APDU prises en charge par Maestro/MasterCard, donc je ne peux pas vous donner d'exemple.

Essayez de donner la commande une longueur explicite attendue 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(); 
} 
3

est ici 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 maintenant je dois lire le numéro PAN de MasterCard. Je ne sais pas si je devrais changer l'enregistrement APDU ou sélectionner l'application APDU. Quelqu'un connaît-il les APDU?

+0

Il s'agit de la commande de sélection d'application que vous devez modifier. La dernière partie de cette commande est l'AID de l'application que vous voulez sélectionner. Changer cela pour le MasterCard AID devrait fonctionner. Ou vous pourriez vouloir juste raccourcir l'AID. Si vous fournissez A400000004, ... –

+0

... il devrait correspondre à tous les AID commençant par A400000004. –

1
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(); 
+0

Salut Grandie, Pouvez-vous ajouter la classe TLV ici – KCN

-2

ce que sur l'utilisation d'un scanner, d'obtenir une image de la carte, l'analyse du contenu de l'image avec une bonne bibliothèque java ocr (comme http://ocr4j.sourceforge.net/ par exemple) et la recherche d'un (généralement) 16 séquence de chiffres XXXX- XXXX-XXXX-XXXX, alors vous obtiendrez le PAN à partir de n'importe quelle carte EMV en utilisant Java.