Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Girocard Maestro智能卡读卡器问题,读取持卡人姓名和IBAN_C#_Credit Card_Apdu_Smartcard Reader_Emv - Fatal编程技术网

C# Girocard Maestro智能卡读卡器问题,读取持卡人姓名和IBAN

C# Girocard Maestro智能卡读卡器问题,读取持卡人姓名和IBAN,c#,credit-card,apdu,smartcard-reader,emv,C#,Credit Card,Apdu,Smartcard Reader,Emv,按照所描述的程序,并使用,我能够阅读VISA卡,没有任何问题,迫使援助名单。现在我读德国的EC卡顿(Sparkasse Girocard)有一个问题 当我试图强制阅读援助清单时,使用 foreach (byte[] aid in aidList) { byte[] atrValue = this.cardUpdater.GetAttribute(SCARD_ATTR_VALUE.ATR_STRING); string st

按照所描述的程序,并使用,我能够阅读VISA卡,没有任何问题,迫使援助名单。现在我读德国的EC卡顿(Sparkasse Girocard)有一个问题

  • 当我试图强制阅读援助清单时,使用

           foreach (byte[] aid in aidList)
           {
    
               byte[] atrValue = this.cardUpdater.GetAttribute(SCARD_ATTR_VALUE.ATR_STRING);
               string strATR = ByteArrayToString(atrValue);
    
    
               APDUCommand apduSelectEMVApl = null;
               APDUResponse apdu2 = null;
    
               apduSelectEMVApl = new APDUCommand(0x00, 0xA4, 0x04, 0x00, aid, 95);
               apdu2 = this.cardUpdater.Transmit(apduSelectEMVApl);
    
              if (apdu2.SW1 == 0x90)
               {
                   //Label = ASCIIEncoding.ASCII.GetString(apdu2.Data, 15, apdu2.Data[14]);
                   //found it!
                   m_EMVAID = aid;
                   if (apdu2.Data[0] == 0x6f)  //fci template
                   {
                       ExtractData(ReadTagData(apdu2.Data, 0));
                   }
                   return true;
    
               }
    
           }
        return false;
    
  • 注:成功读取供选择的AID为A0000035910100280001

    如果我没有将APDU命令的length参数专门设置为95,而不是所有项目中的标准0(以获得最大长度),它将不会响应90-00(成功)。我通过迭代找到了这个值,以确定哪种长度是可以接受的。为什么?

    通过此过程,我能够读取BIC和卡类型(“girocard”),以及PDOL等数据:

    9F33029F35019F4001

    然后,我尝试按照标准提高安全级别。但在我的例子中,那些用于选择和读取的APDU命令不会抛出90-00(而是6700)

  • 我已经试着通过SFI记录

        APDUCommand apduGPO = new APDUCommand(0x80, 0xa8, 0, 0, new byte[] { 0x83, 0 }, 0);
        APDUResponse apdu1 = this.cardUpdater.Transmit(apduGPO);
        if (apdu1.SW1 != 0x90) throw new Exception("Read GPO Data fail");
        //two possible forms, 0x80 and 0x77
        if (apdu1.Data[0] == 0x80)
        {
            for (int i = 4; i < apdu1.Data.Length; i += 4)
            {
                byte sfi = (byte)((apdu1.Data[i] >> 3) & 0xf);
                byte lowRange = apdu1.Data[i + 1];
                byte hiRange = apdu1.Data[i + 2];
                byte[] records = new byte[hiRange - lowRange + 1];
                for (int j = lowRange; j <= hiRange; j++)
                    records[j - lowRange] = (byte)j;
                sfiRecords.Add(new SFIRecords(sfi, records));
            }
        }
        else if (apdu1.Data[0] == 0x77)
        {
            //look for the application file locator AFL
            int a, tag;
            for (a = 2; (tag = ReadTag(apdu1.Data, a)) != 0x94; a = SkipTag(apdu1.Data, a)) ;
            if (tag == 0x94)
            {
                //found it
                a++;
                int len = apdu1.Data[a++];
                for (int i = a; i < a + len; i += 4)
                {
                    byte sfi = (byte)((apdu1.Data[i] >> 3) & 0xf);
                    byte lowRange = apdu1.Data[i + 1];
                    byte hiRange = apdu1.Data[i + 2];
                    byte[] records = new byte[hiRange - lowRange + 1];
                    for (int j = lowRange; j <= hiRange; j++)
                        records[j - lowRange] = (byte)j;
                    sfiRecords.Add(new SFIRecords(sfi, records));
                }
            }
        }
        else
            throw new Exception("Unknown GPO template");
    

    在apdugporeResponse上不再进一步(再次出现错误6700,由于结果不成功,读取GPO时引发异常失败),因此我无法将SFI记录添加到列表中,以进一步迭代数据[0]并查找要读取的记录。没有90-00响应

    有没有想过我错过了什么

    已更新

    我运行这段代码强制直接读取所有可能的值,而不使用GPO:

            APDUCommand apduReadAll = null;
            APDUResponse apdu1 = null;
             for (var sfi = 1; sfi <= 31; sfi++)
            {
                for (var rec = 1; rec <= 16; rec++)
                {
    
                    for (byte le = 0; le < 255; le++)
                    {
                        apduReadAll = new APDUCommand(0x00, 0xB2, (byte)rec, (byte)((sfi << 3) | 4), null, le);
                        apdu1 = this.cardUpdater.Transmit(apduReadAll);
    
                        if (apdu1.SW1 == 0x90)
                        {
                            Console.WriteLine("SFI " + sfi.ToString() + " record #" + rec);
                            if (apdu1.Data[0] == 0x70 || apdu1.Data[0] == 0x77)
                            {
                                Console.WriteLine("Chalk one here " + sfi.ToString() + " record #" + rec + " len " + le);
                                try
                                {
                                    ExtractData(ReadTagData(apdu1.Data, 0));
                                }
    
                                catch
                                {
    
                                }
                                //if (!String.IsNullOrEmpty(NumberString) && !String.IsNullOrEmpty(Name) &&
                                //    !String.IsNullOrEmpty(ExpiryString) && !String.IsNullOrEmpty(CardType) &&
                                //    !String.IsNullOrEmpty(Label))
                                //    return;  //we have all info we need
                            }
                        }
                    }
                }
            }
            foreach (TagData tag in Properties)
             {
                 Console.WriteLine(tag.Name + " " + tag.DataString);
                 strAllData += tag.Name + " " + tag.DataString + "\r\n";
             }
    
    我将使用从卡返回的提到的AID值运行相同的过程,以比较结果,并查看发生了什么,以便更好地理解。感谢您为我指出了正确的方向。

    为什么我需要将Le设置为95而不是0(以获得最大长度)? 原因是该项目中的
    Transmit()
    的实现存在缺陷。当传递Le设置为0的APDUCommand对象时,它将错误地将该情况视为Le不存在,因此不会发送Le字段。看见因此,

    ...Transmit(new APDUCommand(0x00, 0xA4, 0x04, 0x00, new byte[] { 1, 2, 3, 4, 5 }, 0));
    
    将以下APDU发送到卡的结果:

    00 A4 0400 05 0102030405
    
    但是,您实际需要的是以下APDU(具有Le字段):

    这可以通过区分Le不存在(表示预期没有响应数据,Ne=0)和Le为0(表示预期最多256字节的响应数据,Ne=256)这两种情况来解决

    接下来是什么命令? 由于您没有显示所选应用程序的帮助(或者更好的是选择响应),因此无法判断它可能会使用哪种协议。到目前为止,所有命令似乎都因错误的长度错误(SW=
    0x6700
    )而被拒绝,这似乎与第一个问题中的问题有关

    由于您引用的AID列表表明Girocard应用程序符合某种形式的EMV,并且您收到的PDOL值为
    9F33029F35019F4001
    ,因此您可以尝试发出GET PROCESSION OPTIONS命令(类似于您当前尝试执行的操作)。由于卡提供了一个PDOL,您需要在GPO命令中用期望值填充与PDOL相关的数据对象

    PDOL列出了以下元素:

    • 9F33(2字节)
    • 9F35(1字节)
    • 9F40(1字节)
    因此,您可以尝试创建一个与PDOL相关的数据对象,用零填充所有这些元素:

    0000 00 00
    
    请注意,您的卡可能需要一些特定的值。由于PDOL中的数据对象与EMV中的定义不匹配(9F33(终端功能)的长度预计为3,9F40(附加终端功能)的长度预计为5),因此我无法说出它们的实际含义/编码

    然后,GPO命令可能如下所示:

    APDUCommand apduGPO = new APDUCommand(0x80, 0xa8, 0, 0, new byte[] { 0x83, 4, 0, 0, 0, 0 }, 0);
    

    同样,这只有在解决了Le字段的问题时才有效。

    我不熟悉您试图读取的芯片类型,但据我所知,
    67 00
    表示错误的命令长度。这就是为什么我运行循环不是通过长度,而是通过所有参数。。。在APDUCommand apduGPO=new APDUCommand(0,34193164,new byte[]{0x83,0},0)上,第二个问题只得到了9000个响应;我认为这与处理选项的不匹配有关,如中所示。在任何情况下,当我想要获得最大长度时,为什么我必须将其设置为95(阅读第一个问题),而不是0?我有同样的问题。你现在已经拿到Iban了?对不起,我的错。95长度的成功援助是A0000035910100280001,在原始帖子中编辑。谢谢你的意见。
    00 A4 0400 05 0102030405
    
    00 A4 0400 05 0102030405 00
    
    0000 00 00
    
    APDUCommand apduGPO = new APDUCommand(0x80, 0xa8, 0, 0, new byte[] { 0x83, 4, 0, 0, 0, 0 }, 0);