C#PCSC锐利的数据发送/接收自定义命令

时间:2018-10-01 04:19:30

标签: c# smartcard javacard apdu

我正在开发C#Java Card(智能卡)程序,并且正在尝试利用github上的PCSC-sharp库。

这是我的请求的“简短/ tl; dr”版本: 清晰的PCSC示例涵盖了Iso7816 Case2Short。有人可以在下面纠正我的示例,还是为我提供Iso7816 Case3Short(命令数据。无响应数据)和Case4Short(命令数据。预期响应数据)的示例?

这是我的请求的“长篇”版本: 在Java卡上,我同时使用标准和自定义APDU命令,并且可以使用python脚本(与智能卡库一起)成功调用这些命令。换句话说,我证明了Java Card命令可以正常工作。

我现在的目标是使用PCSC-sharp执行相同的命令,但是在包含数据(即APDU LC> 0)时失败了。

这是github上的示例。请注意,只有在更改阅读器名称,指令(选择文件而不是get Challenge)和Le的情况下,我才能使用它。

var contextFactory = ContextFactory.Instance;
using (var ctx = contextFactory.Establish(SCardScope.System)) {
    using (var isoReader = new IsoReader(ctx, "ACME Smartcard reader", 
        SCardShareMode.Shared, SCardProtocol.Any, false)) {

        var apdu = new CommandApdu(IsoCase.Case2Short, isoReader.ActiveProtocol) {
            CLA = 0x00, // Class
            Instruction = InstructionCode.GetChallenge,
            P1 = 0x00, // Parameter 1
            P2 = 0x00, // Parameter 2
            Le = 0x08 // Expected length of the returned data
        };

        var response = isoReader.Transmit(apdu);
        Console.WriteLine("SW1 SW2 = {0:X2} {1:X2}", response.SW1, response.SW2);
        // ..
    }
}

在我的示例版本中,APDU转换为:

Send: 00 A4 00 00 00 00
Resp: 90 00

...适用于我,适用于Case2Short(无数据,无响应)

我要重新创建的是两种不同类型的传输:

Case3Short (命令数据。无响应数据)

Send: 00 A4 04 00 06 01 02 03 04 05 06 00
Resp  90 00

这是我的代码:

    private bool SendApduCase3()
    {
        var success = false;
        DebugWriteLine("case3 start");
        using (var isoReader = new IsoReader(td.context, td.name, SCardShareMode.Shared, SCardProtocol.T1, false))
        {
            DebugWriteLine("case3 command");
            var commandApdu = new CommandApdu(IsoCase.Case3Short, isoReader.ActiveProtocol)
            {
                CLA = 0x00,
                INS = 0xA4,
                P1 = 0x04,
                P2 = 0x00,
                Data = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 },
                Le = 0x00
            };

            DebugWriteLine("case3 transmit");
            var response = isoReader.Transmit(commandApdu);
            if ((response.SW1 == 0x90) && (response.SW2 == 0x00)) success = true;
        }
        DebugWriteLine("case3 " + success.ToString());
        return (success);
    }

...但是它抓住了该命令,并且从不进行发送,而是返回以下错误:

System.ArgumentException:
    Iso7816-4 Case3Short does not expect any data fields in its return value and therefore has no bytes for Le
at PCSC.Iso7816.CommandApdu.set_Le(Int32 value)

如果= 0x00被删除,则发送命令,但是现在它挂在发送中了,这很奇怪,因为不应该有返回数据。

ReaderPresent: catch case3
PCSC.Exceptions.InsufficientBufferException: The data buffer to receive returned data is too small for the returned data."

Case4Short (命令数据。预期的响应数据)

Send: 80 11 00 00 04
Resp: 01 02 03 04 90 00

这是我的代码:

    private bool SendApduCase4()
    {
        var success = false;
        DebugWriteLine("case4 start");
        using (var isoReader = new IsoReader(td.context, td.name, SCardShareMode.Shared, SCardProtocol.T1, false))
        {
            DebugWriteLine("case4 command");
            var commandApdu = new CommandApdu(IsoCase.Case3Short, isoReader.ActiveProtocol)
            {
                CLA = 0x00,
                INS = 0xA4,
                P1 = 0x00,
                P2 = 0x00,
                Data = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 },
                Le = 0x00
            };

            DebugWriteLine("case4 transmit");
            var response = isoReader.Transmit(commandApdu);
            if (response.HasData) DebugWriteLine(response.GetData().ToString());
            if ((response.SW1 == 0x90) && (response.SW2 == 0x00))
            {
                if (response.HasData)
                {
                    byte[] expected = new byte[] { 0x51, 0x01, 0x02, 0x03 };
                    if (response.GetData() == expected) success = true;
                }
            }

        }
        DebugWriteLine("case4 " + success.ToString());
        return (success);
    }

...类似,它抓住了命令,却从未传递给发送器

我在这里做什么错了?

哦,我在搜索中找到的最接近的答案是here,但没有满足我的需要。

1 个答案:

答案 0 :(得分:1)

情况3不会返回任何数据。如果您不希望有数据,那么Le应该不存在。 Le是期​​望的数据量的编码,称为NeLe = 00的意思是:给我一个最大个256字节的返回值:Ne = 256。因此,包含任何Le值都会使其成为ISO情况4命令。如果Le不存在,则Ne = 0

通常,即使设置了Le,智能卡仍会发送正确的响应。不幸的是,对于PCSC-sharp库,您做出了不同的决定,并不允许您发送命令-这可能是一件好事,因为智能卡实现可以仍会返回错误。


删除Le = 00后,您遇到了另一个问题。通过名称进行选择(INS = A4P1 = 04P2 = 00可能实际上会返回文件控制数据,从而使其成为ISO情况4命令。这一次该命令被正确构造为ISO情况3,但是卡返回的数据,在库中没有保留任何缓冲区空间-收到响应后出现错误。

要测试案例3,您需要使用INS = A4P1 = 04P2 = 0C,这表明没有响应数据。当然,也可以使用其他任何实际的ISO情况3命令,例如按文件ID进行选择。


注意:

  • 这里的ISO是ISO / IEC 7816-4的缩写,如果摄影师可以滥用ISO名称,那么智能卡开发人员也可以使用
相关问题