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

Posted

技术标签:

【中文标题】C# PCSC-sharp 发送/接收带有数据的自定义命令【英文标题】:C# PCSC-sharp Send / Receive Custom Commands with Data 【发布时间】:2018-10-01 04:19:30 【问题描述】:

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

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

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

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

这是 github 上的示例。请注意,我可以在仅更改阅读器名称、指令(选择文件而不是获取挑战)和 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(无数据,无响应)

我试图重新创建的是 2 种不同类型的传输:

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】:

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

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


当您删除 Le = 00 时,您遇到了另一个问题。 SELECT by name (INS = A4 and P1 = 04 with P2 = 00 可能实际上返回文件控制数据,使其成为 ISO case 4 命令。这次命令被正确构造为 ISO case 3,但卡返回数据,为此库中没有保留缓冲区空间 - 在收到响应后给您一个错误。

要测试用例 3,您需要使用 INS = A4P1 = 04P2 = 0C,这表示不需要响应数据。当然,也可以是任何其他实际的 ISO 案例 3 命令,例如 SELECT by File ID。


注意事项:

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

【讨论】:

以上是关于C# PCSC-sharp 发送/接收带有数据的自定义命令的主要内容,如果未能解决你的问题,请参考以下文章

C# Socket 如何完全发送/接收数据

C# 串口发送不可接收的数据

开贴一问,Qt怎么接收DLL发送过来的自定义消息

如何使用spark streaming接收kafka中发送的自定义对象

c# 使用 stunserver 完成远程计算机发送和接收数据

每次设备连接并发送数据时,是不是使用带有 aws-iot (wss) 的自定义授权方创建一个新设备?