如何在Java Card 2.2.1上生成MD5哈希?

时间:2017-03-05 09:24:52

标签: md5 smartcard javacard apdu message-digest

我试图使用支持MD5的Java Card来散列8字节消息(可能需要将其扩大到128)。这是我的源代码:

package net.sourceforge.globalplatform.jc.helloworld;
import javacard.framework.*;
import javacard.security.*;
import javacardx.crypto.Cipher;

import javax.print.attribute.standard.MediaSize;
import java.util.logging.Level;

public class HelloWorldApplet extends Applet {

final static byte  APPLET_CLA    = (byte)0x80;
final static byte  HASH          = (byte)0x05;

public static byte[] Message;

MessageDigest mDig = MessageDigest.getInstance(MessageDigest.ALG_MD5, true);

public static void install(byte[] bArray, short bOffset, byte bLength)
{
    Message = new byte[256];
    new HelloWorldApplet().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
}

public void process(APDU apdu)
{
    if (selectingApplet())
    {
        return;
    }

    byte[] buffer = apdu.getBuffer();
    if (buffer[ISO7816.OFFSET_CLA] == APPLET_CLA) {

        switch (buffer[ISO7816.OFFSET_INS]) {

            case HASH:
                hash_message(apdu);
                break;

            default:
                ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    } else {
        ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
    }
}

public void hash_message(APDU apdu) {
    byte[] buffer = apdu.getBuffer();
    short mLen = apdu.setIncomingAndReceive();
    mDig.reset();
    mDig.doFinal(buffer, (short) ISO7816.OFFSET_CDATA, mLen, Message, (short) 0);
    Util.arrayCopy(Message,(short)0,buffer,(short)0, mLen);
    apdu.setOutgoingAndSend((short)0,mLen);
}

}

这也是我使用GPShell的测试:

send_apdu -sc 1 -APDU 80050000081122334455667788
Command --> 80050000081122334455667788
Wrapped command --> 80050000081122334455667788
Response <-- DD254CDC958E53AB9000
send_APDU() returns 0x80209000 (9000: Success. No error.)

我有不同的问题:

  1. 我使用this link在MD5哈希上测试了我的数据,但我发现它无法正常工作!当我使用尽可能简单的代码时,我不知道为什么这个算法没有正确响应!有谁能告诉我这个问题?

  2. 有没有办法向/从卡发送/接收256字节的数据?

  3. 什么是GPShell的更好替代品?

  4. 更新1:我看到this链接并没有解决我的问题。

    更新2:对问题1的回答返回到Hexhell和GPShell和在线计算器中的ASCII数据差异。

1 个答案:

答案 0 :(得分:4)

MD5哈希值与通过某些在线工具生成的哈希值不同。问题在哪里?

有两个问题会导致在线工具中生成的哈希值与applet中生成的哈希值之间存在差异:

  1. 第一个问题是输入数据格式。您使用的在线工具(http://www.xorbin.com/tools/md5-hash-calculator)将输入威胁为ASCII字符串。因此,如果输入ASCII字符串“1122334455667788”,您将获得哈希值8a1bb284d84b7e7df32cba6d8e89eac9(十六进制数)。但是,您在applet中散列的数据不是ASCII字符串“1122334455667788”(它的十六进制重复将是31313232333334343535363637373838)。相反,您对十六进制数1122334455667788进行哈希处理。这导致MD5哈希dd254cdc958e53abaa67da9f797125f5。您可以使用此在线计算器进行检查:http://www.fileformat.info/tool/hash.htm?hex=1122334455667788

  2. 第二个问题是您从applet返回的哈希值的长度。您只返回mLen个字节(输入值的大小)而不是哈希值的全长。 MD5哈希值有128位(16字节)。因此,您通常希望从applet返回所有16个字节:

    mDig.doFinal(buffer, (short)ISO7816.OFFSET_CDATA, mLen, buffer, (short)0);
    apdu.setOutgoingAndSend((short)0, (short)16);
    

    请注意,不需要使用中间字节数组(尤其不是静态数组),因为MessageDigest.doFinal()支持使用相同的数组进行输入和输出,即使范围重叠。

  3. 有没有办法向卡发送/接收256字节的数据?

    如果您的卡支持扩展长度的APDU,您可以使用它们在一个命令APDU中传输超过255个字节的数据。当使用扩展长度APDU时,典型的方法是将输入数据分成多个APDU。例如,您可以使用P2来区分第一个,中间命令和最后一个命令APDU:

    public void hash_message(APDU apdu) {
        byte[] buffer = apdu.getBuffer();
        byte p2 = buffer[ISO7816.OFFSET_P2];
    
        if (p2 != (byte)0x02) {
            if (p2 == (byte)0x01) {
                mDig.reset();
            }
    
            short bytesLeft = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
            short readCount = apdu.setIncomingAndReceive();
            while (bytesLeft > 0) {
                mDig.update(buffer, (short)ISO7816.OFFSET_CDATA, readCount);
                bytesLeft -= readCount;
                readCount = apdu.receiveBytes((short)ISO7816.OFFSET_CDATA);
            }
        } else {
            mDig.doFinal(buffer, (short)ISO7816.OFFSET_CDATA, (short)0, buffer, (short)0);
            apdu.setOutgoingAndSend((short)0, (short)16);
        }
    }
    

    然后,您可以通过发送APDU开始生成新的哈希值:

    80 05 0001 08 1122334455667788
    

    您可以使用以下APDU继续将更多数据提供给哈希生成:

    80 05 0000 Lc DATA
    

    最后,您可以使用以下格式的APDU计算结果哈希:

    80 05 0002 00
    

    什么是GPShell的更好替代品?

    这在很大程度上取决于你想要达到的目标。允许您将APDU发送到智能卡的其他工具是,例如, GScriptor或opensc-tool。您还可以创建自己的应用程序,通过PC / SC API(例如Java中的Java智能卡API)发送APDU。