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

MJa*_*Jay -1 md5 apdu smartcard javacard 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);
}

}
Run Code Online (Sandbox Code Playgroud)

这也是我使用GPShell进行的测试:

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

我有不同的问题:

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

  2. 有什么方法可以向卡发送/从卡接收256字节数据?

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


更新1:我已经看到链接,但它不能解决我的问题。

更新2:问题1的答案返回GPShell和在线计算器中的十六进制和ASCII数据差。

Mic*_*and 5

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

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

  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);
    
    Run Code Online (Sandbox Code Playgroud)

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

有什么方法可以向卡发送/从卡接收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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

80 05 0001 08 1122334455667788
Run Code Online (Sandbox Code Playgroud)

您可以继续使用APDU将更多数据馈入哈希生成,如下所示:

80 05 0000 Lc DATA
Run Code Online (Sandbox Code Playgroud)

最后,您可以使用以下形式的APDU计算所得的哈希值:

80 05 0002 00
Run Code Online (Sandbox Code Playgroud)

什么是GPShell的更好替代品?

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