Java Card小程序,安全数据传输和安全通道

时间:2015-04-05 09:02:17

标签: javacard globalplatform

我想以我的卡和我的阅读器之间的传输通道中的APDU命令和状态字不清楚的方式编写我的applet。我的意思是我不想发送APDU命令和响应为第三方的纯文本。

我想我有两个选择:

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

    enter image description here

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

      还有其他办法吗?

      似乎第一种解决方案不够好,因为:

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

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

        1. 将卡置于SECURED状态。由于用户无法在此状态下使用纯文本APDU命令与卡通信(对吗?),因此他必须使用安全通道将命令发送到我的applet。对?如果不正确,有没有办法强制SD只使用安全通道?

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

        3. 还有其他办法吗?

          最后主要问题是:

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

          我知道这可能需要很长时间才能回答,但我确信它不仅为我提出了很多问题,也为其他未来的观众提出了很多问题。

          我感谢任何团体为我解决这个问题。

          示例applet更加明显。

3 个答案:

答案 0 :(得分:3)

不用担心通过applet进行安全的频道通信。如果您在applet中使用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;
        }
    }
}

答案 1 :(得分:2)

我会按顺序回答:

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

答案 2 :(得分:0)

为了进行Google搜索,Anurag Bajpai的代码必须进行少许修改,否则无法正常工作,因为如GP安全通道API中所述,小程序应该输出最终的响应数据:

  

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

因此,更正后的代码为:

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

}