Below, you see an applet that generate hash value of input data based on MD5
, RIPEMD160
, SHA
, SHA224
, SHA256
, SHA384
and SHA512
:
下面,您将看到一个小程序,它根据MD5,RIPEMD160,SHA,SHA224,SHA256,SHA384和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.
问题是这个applet返回的值与在线工具返回的值不同。
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:
例如,我希望哈希值为012345(在ascii中)。所以我将其转换为十六进制值(即303132333435),然后将其发送到我的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?
如您所见,小程序返回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。怎么了?
1 个解决方案
#1
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"):
您的代码中存在错误。你的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);
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.
更新方法仅用于长输入 - 它执行前N个数据块的所有计算并且不产生输出。 doFinal方法对最后一个数据块执行相同操作,并将输出复制到输出缓冲区。
Use the second line only:
仅使用第二行:
HashObj.doFinal(buffer, ISO7816.OFFSET_CDATA, buffer[ISO7816.OFFSET_LC], hashedValue, (short) 0);
#1
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"):
您的代码中存在错误。你的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);
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.
更新方法仅用于长输入 - 它执行前N个数据块的所有计算并且不产生输出。 doFinal方法对最后一个数据块执行相同操作,并将输出复制到输出缓冲区。
Use the second line only:
仅使用第二行:
HashObj.doFinal(buffer, ISO7816.OFFSET_CDATA, buffer[ISO7816.OFFSET_LC], hashedValue, (short) 0);