c# – Girocard-Maestro智能卡读卡器问题,读卡持有人姓名和IBAN

c# – Girocard-Maestro智能卡读卡器问题,读卡持有人姓名和IBAN,第1张

概述按照 on this card reader project描述的例程,并使用 this AID List,我能够在没有任何问题的情况下读取VISA卡,从而强制执行A​​ID列表.现在我在阅读德国的EC-Karten(Sparkasse Girocard)时遇到了问题. >当我尝试强制读取AID列表时,使用 foreach (byte[] aid in aidList) { 按照 on this card reader project描述的例程,并使用 this AID List,我能够在没有任何问题的情况下读取VISA卡,从而强制执行A​​ID列表.现在我在阅读德国的EC-Karten(Sparkasse Girocard)时遇到了问题.

>当我尝试强制读取AID列表时,使用

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;

Note: AID Successfuly read for selection is A0000003591010028001

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

通过这个程序,我能够读取BIC和卡片类型(“girocard”),以及PDol等数据:

9F33029F35019F4001

然后我尝试按照this post提高安全级别.但是那些选择和读取的APDU命令在我的情况下不会抛出90-00(而是6700).

>我试图通过SFI记录

APDUCommand apduGPO = new APDUCommand(0x80,0xa8,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");

当我从包括Openscdp’s Initiate Application Process在内的许多其他来源中读到,但是将PDol发送为

APDUCommand apduGPO = new APDUCommand(0x80,pdol,0);       APDUResponse apdu1 = this.cardUpdater.Transmit(apduGPO);

要么

APDUCommand apduGPO = new APDUCommand(0x80,new byte[]{0x83,0x00},0);        APDUResponse apdu1 = this.cardUpdater.Transmit(apduGPO);

在apduGPOResponse上没有再继续(错误6700,异常抛出失败读取GPO,因为结果不成功),所以我无法将SFI记录添加到列表中以进一步迭代Data [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";         }

在结果中,我发现了一些我需要的信息(现在我可以直接指向我需要的数据来加速这个过程),以及其他一些有趣的信息:

Application Label girocardApplication Priority Indicator 02 Application IDentifIEr (AID) - card A0 00 00 00 59 45 43 01 00 Application Label girocardApplication Priority Indicator 04 Application IDentifIEr (AID) - card A0 00 00 03 59 10 10 02 80 01 Application Label girocardApplication Priority Indicator 04 Application IDentifIEr (AID) - card A0 00 00 00 04 30 60 Application Label MaestroApplication Priority Indicator 07 Application IDentifIEr (AID) - card D2 76 00 00 25 45 50 02 00 Application Label GeldKarteApplication IDentifIEr (AID) - card A0 00 00 04 86 01 01 Application Label girocardApplication Priority Indicator 05

我将使用从卡中返回的上述AID值运行相同的过程来比较结果,看看会发生什么以便更好地理解.谢谢你指点我正确的方向.

解决方法 为什么我需要将Le设置为95而不是0(以获得最大长度)?

原因是该项目中的Transmit()的实现是错误的.当您传递一个已设置为Le的APDUCommand对象时,它将错误地处理该情况,就像Le不存在一样,因此不会发送Le字段.见CardNative.cs on line 446.因此,

...Transmit(new APDUCommand(0x00,new byte[] { 1,2,3,4,5 },0));

导致以下APDU发送到卡:

00 A4 0400 05 0102030405

但是,您真正想要的是以下APDU(具有Le字段):

00 A4 0400 05 0102030405 00

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

下一步是什么命令?

由于您没有透露所选应用程序的AID(或者更好的SELECT响应),因此无法确定它可能会说出哪种协议.到目前为止,所有命令似乎都被错误的长度错误(SW = 0x6700)拒绝,这似乎与第一个问题中的问题有关.

由于您引用的AID列表指示Girocard应用程序的某种形式的EMV合规性,并且您收到了pdf值9F33029F35019F4001,您可以尝试发出GET PROCESSING 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,0);

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

总结

以上是内存溢出为你收集整理的c# – Girocard-Maestro智能卡读卡器问题,读卡持有人姓名和IBAN全部内容,希望文章能够帮你解决c# – Girocard-Maestro智能卡读卡器问题,读卡持有人姓名和IBAN所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1231826.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存