哈希生成器小程序不能正常工作

Hash generator applet doesn't work fine

下面,您会看到一个小程序,它根据 MD5RIPEMD160SHASHA224SHA256 生成输入数据的哈希值, SHA384SHA512 :

package hashPack;

import javacard.framework.*;
import javacard.security.CryptoException;
import javacard.security.MessageDigest;

public class HashMachine extends Applet {

    //outputArray
    byte[] hashedValue = new byte[64];

    //output Length
    short OLength = 0x0000;

    //Defining switch case variables for Hash algorithm commands
    final byte MD5 = (byte) 0x00;
    final byte RIPEMD160 = (byte) 0X01;
    final byte SHA = (byte) 0X02;
    final byte SHA224 = (byte) 0X03;
    final byte SHA256 = (byte) 0X04;
    final byte SHA384 = (byte) 0X05;
    final byte SHA512 = (byte) 0X06;

    public static void install(byte[] bArray, short bOffset, byte bLength) {
        new HashMachine();
    }

    protected HashMachine() {
        register();
    }

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

        byte[] buffer = apdu.getBuffer();
        try {
            switch (buffer[ISO7816.OFFSET_INS]) {
                case MD5: {
                    MessageDigest HashObj = MessageDigest.getInstance(MessageDigest.ALG_MD5, false);
                    HashObj.reset();
                    OLength = 16;

                    if (buffer[ISO7816.OFFSET_LC] > 0) {
                        doHash(apdu, HashObj, OLength);
                    } else {
                        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
                    }
                }
                break;

                case RIPEMD160: {
                    MessageDigest HashObj = MessageDigest.getInstance(MessageDigest.ALG_RIPEMD160, false);
                    HashObj.reset();
                    OLength = 20;

                    if (buffer[ISO7816.OFFSET_LC] > 0) {
                        doHash(apdu, HashObj, OLength);
                    } else {
                        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
                    }
                }
                break;

                case SHA: {
                    MessageDigest HashObj = MessageDigest.getInstance(MessageDigest.ALG_SHA, false);
                    HashObj.reset();
                    OLength = 20;

                    if (buffer[ISO7816.OFFSET_LC] > 0) {
                        doHash(apdu, HashObj, OLength);
                    } else {
                        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
                    }
                }
                break;

                case SHA224: {
                    MessageDigest HashObj = MessageDigest.getInstance(MessageDigest.ALG_SHA_224, false);
                    HashObj.reset();
                    OLength = 32;

                    if (buffer[ISO7816.OFFSET_LC] > 0) {
                        doHash(apdu, HashObj, OLength);
                    } else {
                        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
                    }
                }
                break;

                case SHA256: {
                    MessageDigest HashObj = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false);
                    HashObj.reset();
                    OLength = 32;
                    if (buffer[ISO7816.OFFSET_LC] > 0) {
                        doHash(apdu, HashObj, OLength);
                    } else {
                        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
                    }
                }
                break;

                case SHA384: {
                    MessageDigest HashObj = MessageDigest.getInstance(MessageDigest.ALG_SHA_384, false);
                    HashObj.reset();
                    OLength = 64;
                    if (buffer[ISO7816.OFFSET_LC] > 0) {
                        doHash(apdu, HashObj, OLength);
                    } else {
                        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
                    }
                }
                break;

                case SHA512: {
                    MessageDigest HashObj = MessageDigest.getInstance(MessageDigest.ALG_SHA_512, false);
                    HashObj.reset();
                    OLength = 64;
                    if (buffer[ISO7816.OFFSET_LC] > 0) {
                        doHash(apdu, HashObj, OLength);
                    } else {
                        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
                    }
                }
                break;

                default:
                    ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
            }
        } catch (CryptoException e) {
            ISOException.throwIt(((CryptoException) e).getReason());

        }

    }

    public void doHash(APDU apdu, MessageDigest HashObj, short OLength) {

        byte[] buffer = apdu.getBuffer();
        HashObj.update(buffer, ISO7816.OFFSET_CDATA, buffer[ISO7816.OFFSET_LC]);
        HashObj.doFinal(buffer, ISO7816.OFFSET_CDATA, buffer[ISO7816.OFFSET_LC], hashedValue, (short) 0);
        Util.arrayCopyNonAtomic(hashedValue, (short) 0, buffer, (short) 0, OLength);
        apdu.setOutgoingAndSend((short) 0, OLength);

    }
}

问题是这个小程序 return 给我的值与在线工具 return 的值不同。

例如,我想要 012345(ascii 格式)的散列值。所以我将它转换为它的十六进制值(即 303132333435)并将它发送到我的小程序:

OSC: opensc-tool.exe -s 00a4040006C761819104D7 -s 0000000005303132333435
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 06 C7 61 81 91 04 D7
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 00 00 05 30 31 32 33 34 35
Received (SW1=0x90, SW2=0x00):
40 6B 29 64 5D 4D 8A 75 97 89 84 B5 00 25 67 D2 @k)d]M.u.....%g.

如你所见小程序returns40 6B 29 64 5D 4D 8A 75 97 89 84 B5 00 25 67 D2,而online toolsreturnd6 a9 a9 33 c8 aa fc 51 e5 5a c0 66 2b 6e 4d 4a。怎么了?

您的代码中存在错误。您的 doHash 方法从两倍长的输入开始进行散列(它从 "XX" 而不是 "X" 计算散列):

HashObj.update(buffer, ISO7816.OFFSET_CDATA, buffer[ISO7816.OFFSET_LC]);
HashObj.doFinal(buffer, ISO7816.OFFSET_CDATA, buffer[ISO7816.OFFSET_LC], hashedValue, (short) 0);

update 方法仅适用于长输入 - 它执行前 N 个数据块的所有计算并且不产生输出。 doFinal 方法对最后一个数据块执行相同的操作,并将输出复制到输出缓冲区。

仅使用第二行:

HashObj.doFinal(buffer, ISO7816.OFFSET_CDATA, buffer[ISO7816.OFFSET_LC], hashedValue, (short) 0);