哈希生成器小程序不能正常工作 [英] Hash generator applet doesn't work fine

查看:127
本文介绍了哈希生成器小程序不能正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面,您会看到一个applet,它根据 MD5 RIPEMD160 ,<$生成输入数据的哈希值c $ c> SHA , SHA224 SHA256 SHA384 和 SHA512

  package hashPack; 

import javacard.framework。*;
导入javacard.security.CryptoException;
导入javacard.security.MessageDigest;

public class HashMachine extends Applet {

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

//输出长度
短OLength = 0x0000;

//为散列算法命令定义开关情况变量
最终字节MD5 =(字节)0x00;
最终字节RIPEMD160 =(字节)0X01;
最终字节SHA =(字节)0X02;
最终字节SHA224 =(字节)0X03;
最终字节SHA256 =(字节)0X04;
最终字节SHA384 =(字节)0X05;
最终字节SHA512 =(字节)0X06;

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


protected HashMachine(){
register();
}

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

byte [] buffer = apdu.getBuffer();
switch {缓冲区[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;

默认值:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); ((CryptoException)e).getReason());
}
} catch(CryptoException e){
ISOException.throwIt




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

byte [ ] buffer = apdu.getBuffer();
HashObj.update(缓冲区,ISO7816.OFFSET_CDATA,缓冲区[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);


$ b $ / code $ / pre
$ b $ p

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



例如,我想要散列值为 012345 (以ascii表示)。因此,我将它转换为它的十六进制值(即 303132333435 ),然后将它发送到我的小应用程序:

  OSC:opensc-tool.exe -s 00a4040006C761819104D7 -s 0000000005303132333435 
在卡上使用读卡器:ACS CCID USB读卡器0
发送:00 A4 04 00 06 C7 61 81 91 04接收到(SW1 = 0x90,SW2 = 0x00)
发送:00 00 00 00 05 30 31 32 33 34 35
接收到(SW1 = 0x90,SW2 = 0x00):
40 6B 29 64 5D 4D 8A 75 97 89 84 B5 00 25 67 D2 @k)d] Mu ....%g。

当您看到小程序返回 40 6B 29 64 5D 4D 8A 75 97 89 84 B5 00 25 67 D2 ,而在线工具返回 d6 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,(简短)0); 


Below, you see an applet that generate hash value of input data based on MD5, RIPEMD160, SHA, SHA224, SHA256, SHA384 and SHA512 :

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

    }
}

The problem is that the values that this applet returns me, are different from the values that online tools return.

For example I want to have hash value of 012345(in ascii). So I convert it to its hex value (i.e 303132333435) and I sent it to my applet:

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.

As you see the applet returns 40 6B 29 64 5D 4D 8A 75 97 89 84 B5 00 25 67 D2, while online toolsreturn d6 a9 a9 33 c8 aa fc 51 e5 5a c0 66 2b 6e 4d 4a. What's wrong?

解决方案

There is a bug in your code. Your doHash method does the hashing as from a twice as long input (it computes the hash from "XX" instead of "X"):

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

The update method is for long inputs only - it does all the computation of the first N data blocks and produces no output. The doFinal method does the same for the last block of data and it copies the output to the output buffer.

Use the second line only:

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

这篇关于哈希生成器小程序不能正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆