当前位置: 首页 > 知识库问答 >
问题:

C#PCSC夏普发送/接收带有数据的自定义命令

张宣
2023-03-14

我正在开发一个C#Java卡(智能卡)程序,并试图利用github上的PCSC sharp库。

这是我的请求的“短/tl; dr”版本: PCSC清晰示例涵盖了Iso7816 Case2短。有人能纠正我下面的例子吗,或者给我提供一个Iso7816 Case3短(命令数据。没有响应数据)和Case4短(命令数据。预期的响应数据)的例子?

这是我的请求的"长"版本:在Java卡上,我同时使用标准和自定义APDU命令,我可以使用python脚本(使用智能卡库)成功调用这些命令。换句话说,我已经证明了Java卡命令。

我现在的目标是使用PCSC sharp来执行相同的命令,但当我包含数据时(即APDU LC是

这是github上的例子。请注意,我只能在更改阅读器名称、指令(选择html" target="_blank">文件而不是获取挑战)和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

... 这对我来说很有效,并且适用于案例2短(无数据,无响应)

我试图重现的是两种不同类型的传输:

Case3简短(命令数据。没有响应数据)

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);
    }

...同样地,它会收到命令,但永远不会到达传输端

我做错了什么?

哦,我在搜索中找到的最接近的答案在这里,但没有涵盖我需要的内容。

共有1个答案

丌官招
2023-03-14

案例3不期望任何返回数据。如果您不期望数据,那么Le不应该存在。Le是预期数据量的编码,称为NeLe=00表示:给我最多256个字节作为回报:Ne=256。因此包含任何Le值使其成为ISO案例4命令。如果Le不存在,则Ne=0

一般来说,即使设置了Le,智能卡仍然会发送正确的响应。不幸的是,PCSC-夏普库做出了不同的决定,不允许您发送命令——这可能是一件好事,因为智能卡实现仍然可能返回错误。

当你删除你的Le=00时,你遇到了另一个问题。按名称选择(INS=A4P1=04P2=00实际上可能会返回文件控制数据,使其成为ISO案例4命令。这一次,该命令被正确构造为ISO案例3,但卡返回的数据在库中没有为其保留缓冲区空间,这在收到响应后会给您一个错误。

要测试案例3,您需要使用INS=A4P1=04P2=0C,这表明不需要响应数据。或者任何其他实际的ISO案例3命令,例如当然是按文件ID选择。

注意事项:

  • ISO在这里是ISO/IEC 7816-4的缩写,如果摄影师可以滥用ISO名称,那么智能卡开发人员也可以
 类似资料:
  • 问题内容: 我正在尝试为请求和响应应用程序创建桌面客户端。 我能够轻松地执行GET请求。但是我想知道是否有人可以帮助我确定如何进行JSON请求和响应。并将其解析为字符串,从那里我可以锻炼如何将其全部切开 问题答案: Json.net在.net世界中无处不在。

  • 因此,我正在用Java编写一个程序,在DatagramSocket和DataGramPacket的帮助下发送和接收数据。问题是,当我发送数据/接收数据时,数据在我发送的程序中也会有所不同,但只是在某些情况下,比如: 但有时会起作用,比如:

  • 实现蓝牙发送和接收数据的demo。文件包含两个工程,一个接收,一个发送。 [Code4App.com]

  • 我一直在用c做一些套接字编程,我想让我的程序的用户指定要从中发送和接收数据包的接口。套接字(7) 的 linux 手册页说, 你可以设置套接字选项SO_BINDTODEVICE将套接字绑定到一个特定的设备, 比如 “eth0”。我还想到,在调用 bind() 时,您通常会向它传递一个sockaddr_in结构,并将 sin_addr.s_addr 属性设置为 INADDR_ANY 以指示套接字绑定

  • 我一直在为Spring云数据流在Scala中创建一个简单的自定义处理器,并且在向starter应用程序发送/接收数据时遇到了问题。我无法看到任何消息在流中传播。流的定义是时间触发器。时间单位=秒|传递日志|日志其中传递日志是我的自定义处理器。 我使用的是Spring Cloud Data Flow 2.5.1和Spring Boot 2.2.6。 这是处理器使用的代码-我使用的是功能模型。 应用y