Следуя процедурам, описанным в этом проекте чтения карт, и используя этот список AID , я смог прочитать карту VISA без каких-либо проблем, заставив список AID. Теперь у меня проблема с чтением 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;
Примечание. AID успешно прочитан для выбора: A0000003591010028001.
Если я не установлю параметр длины для команды APDU специально на 95 вместо стандартного 0, как это видно во всех проектах (чтобы получить максимальную длину), он не ответит 90-00 (успех). Я нашел это значение только с помощью итерации, чтобы увидеть, какая длина приемлема. Почему?
С помощью этой процедуры я могу прочитать BIC и тип карты («жирокарта»), а также такие данные, как 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");
Как я читал из многих других источников, включая процесс инициации приложения Openscdp, но отправка PDOL как
APDUCommand apduGPO = new APDUCommand(0x80, 0xa8, 0, 0, pdol, 0);
APDUResponse apdu1 = this.cardUpdater.Transmit(apduGPO);
or
APDUCommand apduGPO = new APDUCommand(0x80, 0xa8, 0, 0, new byte[]{0x83, 0x00}, 0);
APDUResponse apdu1 = this.cardUpdater.Transmit(apduGPO);
дальше не идет (снова ошибка 6700, исключение выдается при неудачном чтении GPO, так как результат не удался) в apduGPOResponse, поэтому я не могу добавить записи 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 girocard
Application Priority Indicator 02
Application Identifier (AID) - card A0 00 00 00 59 45 43 01 00
Application Label girocard
Application Priority Indicator 04
Application Identifier (AID) - card A0 00 00 03 59 10 10 02 80 01
Application Label girocard
Application Priority Indicator 04
Application Identifier (AID) - card A0 00 00 00 04 30 60
Application Label Maestro
Application Priority Indicator 07
Application Identifier (AID) - card D2 76 00 00 25 45 50 02 00
Application Label GeldKarte
Application Identifier (AID) - card A0 00 00 04 86 01 01
Application Label girocard
Application Priority Indicator 05
Я проведу те же процедуры с указанными значениями AID, возвращенными с карты, чтобы сравнить результаты и посмотреть, что произойдет, чтобы лучше понять. Спасибо, что указали мне правильное направление.
67 00
указывает на неправильную длину команды. - person Pieter Witvoet   schedule 21.12.2015