3

我需要帮助在全球平台的卡上和卡外部分之间设置安全通道。如果我让自己不清楚,希望一个例子可以简化我对问题的理解。

例子:

如果我使用 JCOP shell,我需要在set-key之前输入命令ext-auth,如下所示:

cm> set-key 255/1/DES-ECB/404142434445464748494a4b4c4d4e4f
cm> set-key 255/2/DES-ECB/404142434445464748494a4b4c4d4e4f
cm> set-key 255/3/DES-ECB/404142434445464748494a4b4c4d4e4f
cm> init-update 255
cm> ext-auth

现在我需要从 c# 做同样的事情(set-key)。但是,我在 JCOP shell 中找不到 set-key 命令背后发生了什么,所以我不知道如何从 c# 中设置密钥。

4

3 回答 3

3

set-key 命令设置密钥 - 或者在您的示例中,客户端上的 3DES 密钥的 3 个部分。此命令不会向卡发送 APDU。

然后执行建立安全通道的全球平台INITIALIZE UPDATE,该平台将以APDU的形式发送到卡上。在这一步中,重要的部分是将主机端生成的质询发送到卡 - 卡生成的质询从卡发送回。

然后EXTERNAL AUTHENTICATE命令被发送到卡。

有关和命令的详细信息(APDU 的具体值),请参阅GlobalPlatform Card Specification 。它还描述了可用于建立安全通道的两种不同协议。INITIALIZE UPDATEEXTERNAL AUTHENTICATE

于 2012-09-10T19:16:36.653 回答
2

看看globalplatform.net,它是 .Net Framework 的全球平台规范的开源实现。下面的代码片段展示了如何使用它:

    SCardContext context = new SCardContext();
    context.Establish(SCardScope.System);
    string[] readers = context.GetReaders();
    IsoReader isoReader = new IsoReader(context, readers[3], SCardShareMode.Shared, SCardProtocol.Any, false);
    CommandApdu apdu = new CommandApdu(IsoCase.Case4Short, isoReader.ActiveProtocol)
    {
        CLA = 0x00,
        Instruction = InstructionCode.SelectFile,
        P1 = 0x04,
        P2 = 0x00,
        Data = new byte[] { 0xa0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00 }

    };

    Response response = isoReader.Transmit(apdu);

    GlobalPlatform gp = new GlobalPlatform();
    KeySet scKeys = new KeySet();
    scKeys.MacKey = new Key("404142434445464748494a4b4c4d4e4f");
    scKeys.EncKey = new Key("404142434445464748494a4b4c4d4e4f");
    scKeys.KekKey = new Key("404142434445464748494a4b4c4d4e4f");
    CommandAPDU initUpdate = gp.CreateInitUpdateCommand(scKeys,
        SecurityLevel.C_DECRYPTION | SecurityLevel.C_MAC, GlobalPlatform.SCP_ANY, GlobalPlatform.IMPL_OPTION_ANY);
    apdu = new CommandApdu(IsoCase.Case4Short, isoReader.ActiveProtocol)
    {
        CLA = (byte)initUpdate.CLA,
        INS = (byte)initUpdate.INS,
        P1 = (byte)initUpdate.P1,
        P2 = (byte)initUpdate.P2,
        Data = initUpdate.Data
    };
    response = isoReader.Transmit(apdu);
    if (response.SW1 == 0x6C)
    {
        apdu = new CommandApdu(IsoCase.Case2Short, isoReader.ActiveProtocol)
        {
            CLA = 0x00,
            Instruction = InstructionCode.GetResponse,
            P1 = 0x00,
            P2 = 0x00,
            Le = response.SW2

        };

        response = isoReader.Transmit(apdu);

    }

    byte[] responseData = response.GetData();

    gp.ProcessInitUpdateResponse(new ResponseAPDU(response.SW1, response.SW2, responseData));

    CommandAPDU extAuth = gp.CreateExternalAuthCommand();
    apdu = new CommandApdu(IsoCase.Case3Short, isoReader.ActiveProtocol)
    {
        CLA = (byte)extAuth.CLA,
        INS = (byte)extAuth.INS,
        P1 = (byte)extAuth.P1,
        P2 = (byte)extAuth.P2,
        Data = extAuth.Data
    };

    response = isoReader.Transmit(apdu);

    gp.ProcessExternalAuthResponse(new ResponseAPDU(response.SW1, response.SW2, response.GetData()));

    Key newMacKey = new Key("505152535455565758595a5b5c5d5e5f", 0, 0);
    Key newEncKey = new Key("505152535455565758595a5b5c5d5e5f", 1, 0);
    Key newKekKey = new Key("505152535455565758595a5b5c5d5e5f", 2, 0);

    List<Key> newKeys = new List<Key>();
    newKeys.Add(newMacKey);
    newKeys.Add(newEncKey);
    newKeys.Add(newKekKey);

    CommandAPDU putKey = gp.CreatePutKeyCommand(newKeys, true, false, GlobalPlatform.KEY_FORMAT_1);

    apdu = new CommandApdu(IsoCase.Case3Short, isoReader.ActiveProtocol)
    {
        CLA = (byte)putKey.CLA,
        INS = (byte)putKey.INS,
        P1 = (byte)putKey.P1,
        P2 = (byte)putKey.P2,
        Data = putKey.Data
    };

    response = isoReader.Transmit(apdu);
    if (response.SW1 == 0x6C)
    {
        apdu = new CommandApdu(IsoCase.Case2Short, isoReader.ActiveProtocol)
        {
            CLA = 0x00,
            Instruction = InstructionCode.GetResponse,
            P1 = 0x00,
            P2 = 0x00,
            Le = response.SW2

        };

        response = isoReader.Transmit(apdu);

    }

}
于 2015-11-05T19:54:11.493 回答
1

Bahribayli 发布的 C# 片段是对这个问题的更接近的答案。但是我要在这里添加解释,因为我的祖母正在向我询问这件事,我希望她在不涉及任何说明的情况下理解。

并且offcard需要card了解a-priori对称密钥值。并且需要对这些键的数字索引位置有一个offcard约定。现在,这里有两种情况。第一种情况是作为查询的客户端,通过apdu 命令的参数主动指定这个键的索引号,会在里面搜索这个索引对应的键。第二种情况是,apdu 命令中的值为零,意味着让积极决定使用哪个索引,然后将查找与该索引对应的键。在这两种情况下,最终结果是carda-priorioffcardp1initialize updatecardp1initialize updateoffcardcardoffcardoffcard现在card已经同意一个索引值,希望指向相同的键,以便开始安全地交谈。如果这些键的值不同,尽管它们在相同的索引上,那么initialize update就会失败并且无法继续进行安全通信。

set-key命令是您代表offcard预期存在并准备在指向相同键的两侧的键索引而执行的命令。由于通过不安全的通道仅交换索引值,card因此offcard仍然需要确定该索引号是否确实指向双方的相同密钥。从这里开始,这就像一场*** boy meets girl ***求爱,然后男孩将开始与女孩进行奇怪的神秘对话以计算某些东西,而女孩也会这样做。如果索引确实指向相同的键,那么这个初始的神秘对话将验证,第二阶段从这里开始。双方创建session keys作为继续谈话的关键。

于 2020-01-06T18:56:36.913 回答