【问题标题】:Java Card applets, secure data transmission and Secure ChannelJava Card 小程序、安全数据传输和安全通道
【发布时间】:2015-06-09 22:22:34
【问题描述】:

我想编写我的小程序,使其 APDU 命令和状态字在我的卡和读卡器之间的传输通道中不清晰。我的意思是我不想将 APDU 命令和响应以纯文本形式发送给第三方。

我想我有两个选择:

  1. 在卡上选择我的小程序后,对于所有其他命令,对 APDU 命令的数据部分执行加密功能,然后在卡上对其进行解密,然后对其进行分析。请注意,我无法使用此方法对整个命令进行加密,因为结果可能与另一个 SELECT APDU 命令冲突,并且卡的 SD 错误地将其识别为 SELECT 命令。对吗?

它的图表:

  1. 使用 SD 安全通道:据我所知,安全通道意味着:整个 APDU 命令响应 以加密形式传输(即它们在源(安全域/读卡器)中加密并在目标(安全域/读卡器)中解密。对吗?据我所知,SD 在此机制中执行加密方法角色以及之间的通信我的小程序和 SD 很简单(下图),对吧?

它的图表:

还有其他方法吗?

看来第一种方案还不够好,因为:

  1. 我必须自己实现! :)
  2. 我们无法对第三方隐藏命令和响应的所有部分。(我们只能隐藏数据)

我说的对吗?

现在,假设我想确保我的小程序仅适用于使用安全通道传输的 APDU 命令。我想我又有两个选择:

  1. 将卡置于SECURED 状态。由于在这种状态下用户无法使用纯文本 APDU 命令与卡进行通信(对吗?),因此他必须使用安全通道将命令发送到我的小程序。正确的?如果不正确,是否有任何方法可以强制 SD 仅使用 Secure Channel?

  2. 将卡保持在它的任何生命周期中(例如 OP_READY),但是,在收到任何 APDU 命令时,检查 CLA 部分以查看它是否是安全的传送与否! (有可能吗?来自安全通道的 APDU 命令的CLA 部分和其他命令有什么区别吗?我说的对吗?)

还有其他方法吗?

最后是主要问题:

如何使用 SD 与我的小程序进行安全通信?由于我认为我必须使用 GlobalPlatform 类(我是吗?),所以我查看了它的 API-s。我在一个名为org.globalplatform.GPSystem 的包中找到了一个名为getSecureChannel 的方法。我的方式正确吗?我必须使用这种方法吗?

我知道这可能太长无法回答,但我相信它不仅为我,也为其他未来的观众澄清了很多问题。

我很感激任何机构为我阐明了这个问题。

还有一个示例小程序更值得一看。

【问题讨论】:

  • 1.这个问题太多了。 2.有些问题不属于SO 3.这些问题是标准问题,已经解决了很多次 4.你为什么不尝试解决你的问题而不是在SO上问所有问题?
  • @PaulBastian 1- 你是对的,但我认为所有这些问题都是针对一个问题。 2-这些与我的 SO 问题有关。 3-请问您可以参考这些问题和答案吗? 4-当然我试图自己解决它们,但我做不到。此外,我认为这个问题对未来的观众也有帮助,不是吗?
  • @Abraham 你知道如何将 org.globalplatform 导入我的项目吗?我认为它没有安装在我的系统上。从哪里可以找到并下载它?
  • @M.Jalali 你可以下载JAVA COS IDE。它是免费的,并且默认包含这些库。 Download Link
  • @M.Jalali 你也可以从Global Platform card specification page下载合适的版本

标签: javacard globalplatform


【解决方案1】:

不用担心通过小程序进行的安全通道通信。如果您在小程序中使用 Global Platform API,这非常简单。

您不需要考虑很多问题,只需尝试编写一个安全通道小程序,它将按照命令数据中定义的安全级别处理您的小程序。

参考 GP 安全通道 API: http://www.win.tue.nl/pinpasjc/docs/apis/gp22/

并且您应该将卡保持在 SECURED 状态。

这是安全通道 scp02 的示例小程序:

package secureChannel;

import javacard.framework.APDU;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;

import org.globalplatform.GPSystem;
import org.globalplatform.SecureChannel;

public class Scp02 extends Applet
{
    final static byte INIT_UPDATE       = (byte) 0x50;

    final static byte EXT_AUTHENTICATE  = (byte) 0x82;

    final static byte STORE_DATA        = (byte) 0xE2;

    public static void install(byte[] bArray, short sOffset, byte bLength)
    {
        new Scp02().register(bArray, sOffset, bLength);
    }

    public void process(APDU apdu) throws ISOException
    { 
        SecureChannel sc = GPSystem.getSecureChannel();

        byte[] buffer = apdu.getBuffer();

        short inlength = 0;

        switch (ISO7816.OFFSET_INS)
        {
            case INIT_UPDATE:
            case EXT_AUTHENTICATE:
                inlength = apdu.setIncomingAndReceive();
                sc.processSecurity(apdu);
            break;

            case STORE_DATA:
                //Receive command data
                inlength = apdu.setIncomingAndReceive();
                inlength = sc.unwrap(buffer, (short) 0, inlength);

                apdu.setOutgoingAndSend((short)0, inlength);

                //Process data
                break;
        }
    }
}

【讨论】:

  • 如何通过实际的 USB 读卡器获得 SecureChannel?
  • 这只是答案的 1/2。另一半是如何在笔记本电脑上做的。
【解决方案2】:

我会按顺序回答:

  1. 是的,对于 ISO/IEC 7816-4,只有数据部分是加密的。标头仅受身份验证标记保护。
  2. 不,全球平台安全通道也只是(可选地)加密数据。不过,完整性在于标头和命令数据。
  3. 不,安全状态仅适用于全球平台,您必须使用卡上 GP API 自行编程。 GP API 具有执行身份验证、请求安全通道和检索当前状态的访问方法。
  4. 正确,CLA 字节确定 APDU 是否加密(但不是如何加密)。如果 CLA 的第一位为零,那么您的安全通道必须符合 ISO/IEC 7816-4。

【讨论】:

  • 如果 Applet 是安全域 (SD),我不能 100% 确定 3 是否正确。可以说我对 SD 所做的很少。
  • 非常感谢您的宝贵时间,谢谢。 标头只是受认证标签保护。:这个认证标签是什么?如果安全通道协议中没有对头部进行加密,第三方可以通过嗅探通道来获取。对吧?
  • @Abraham 对。认证标签 = MAC 机制的结果。是的,标题通常是可见的。这是必需的,因为 ISO/IEC 7816 没有按应有的分层(应用程序协议和传输协议混合在一起)。通常标头不包含任何机密数据,但您应该记住,将 P1/P2 用于机密信息并不是一个好主意。
【解决方案3】:

为了便于 Google 搜索,Anurag Bajpai 的代码在不进行轻微修改的情况下无法运行,因为如 GP 安全通道 API 中所述,小程序应输出最终响应数据:

如果存在响应数据,该数据将被放置在偏移量 ISO7816.OFFSET_CDATA 的 APDU 缓冲区中。返回值表示长度,必要时小程序负责输出此数据。

因此,更正后的代码是:

package secureChannel;

import javacard.framework.APDU;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import org.globalplatform.GPSystem;
import org.globalplatform.SecureChannel;


public class Scp02 extends Applet
{
    final static byte INIT_UPDATE       = (byte) 0x50;

    final static byte EXT_AUTHENTICATE  = (byte) 0x82;

    final static byte STORE_DATA        = (byte) 0xE2;

    public static void install(byte[] bArray, short sOffset, byte bLength)
    {
        new Scp02().register(bArray, sOffset, bLength);
    }

    public void process(APDU apdu) throws ISOException
    { 
        SecureChannel sc = GPSystem.getSecureChannel();

        byte[] buffer = apdu.getBuffer();

        short inlength = 0;

        switch (ISO7816.OFFSET_INS)
        {
            case INIT_UPDATE:
            case EXT_AUTHENTICATE:
                inlength = apdu.setIncomingAndReceive();
                short respLen = sc.processSecurity(apdu);
                apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, respLen);
            break;

            case STORE_DATA:
                //Receive command data
                inlength = apdu.setIncomingAndReceive();
                inlength = sc.unwrap(buffer, (short) 0, inlength);

                apdu.setOutgoingAndSend((short)0, inlength);

                //Process data
            break;
    }
}

}

【讨论】:

    【解决方案4】:

    请注意,在调用sc.processSecurity(apdu)之前调用apdu.setIncomingAndReceive()是不正确的,因为processSecurity()“负责接收被识别的命令的数据字段”。

    【讨论】:

      猜你喜欢
      • 2015-08-22
      • 1970-01-01
      • 1970-01-01
      • 2011-11-06
      • 1970-01-01
      • 2012-07-15
      • 1970-01-01
      • 1970-01-01
      • 2013-01-06
      相关资源
      最近更新 更多