## self implement ```java= package PRLab ; import javacard.framework.*; import javacard.security.*; public class HMAC { private final short BLOCK_SIZE = (short)64; private byte[] prk; private byte[] msg; private MessageDigest sha256 = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false); private byte[] ikeypad = new byte[BLOCK_SIZE]; private byte[] okeypad = new byte[BLOCK_SIZE]; HMAC(byte[] input_key){ if(input_key.length <= BLOCK_SIZE){ prk = new byte[input_key.length]; Util.arrayCopy(input_key, (short)0, prk, (short)0, (short)input_key.length); }else{ prk = new byte[32]; sha256.doFinal(input_key, (short)0, (short)input_key.length, prk, (short)0); } for(short i = 0; i<prk.length; i++){ ikeypad[i] = (byte)(prk[i]^0x36); okeypad[i] = (byte)(prk[i]^0x5c); } // The Util.arrayFill() have a strange bug that will left some bytes would not be filled. Util.arrayFillNonAtomic(ikeypad, (short)prk.length, (short)(ikeypad.length-prk.length), (byte)0x36); Util.arrayFillNonAtomic(okeypad, (short)prk.length, (short)(okeypad.length-prk.length), (byte)0x5c); } public void update(byte[] newMsg){ if(msg == null){ msg = new byte[newMsg.length]; Util.arrayCopy(newMsg, (short)0, msg, (short)0, (short)newMsg.length); return; } byte[] temp = new byte[msg.length + newMsg.length]; concat(msg, newMsg, temp); msg = temp; JCSystem.requestObjectDeletion(); } public void doFinal(byte[] output, short offset){ sha256.update(ikeypad, (short)0, (short)ikeypad.length); sha256.doFinal(msg, (short)0, (short)msg.length, output, (short)0); sha256.update(okeypad, (short)0, (short)okeypad.length); sha256.doFinal(output, (short)0, (short)32, output, (short)0); } private void concat(byte[] a, byte[] b, byte[] output){ Util.arrayCopy(a, (short)0, output, (short)0, (short)a.length); Util.arrayCopy(b, (short)0, output, (short)a.length, (short)b.length); } } ``` ## javacard api J3R180 not support..... orz ```java= HMACKey hmacKey = (HMACKey)KeyBuilder.buildKey( KeyBuilder.ALG_TYPE_HMAC, JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT, KeyBuilder.LENGTH_HMAC_SHA_256_BLOCK_64, false ); hmacKey.setKey(new byte[]{'P','A','S','S','W','O','R','D',}, (short)0, (short)8); Signature hmac = Signature.getInstance(Signature.ALG_HMAC_SHA_256, false); hmac.init(hmacKey, Signature.MODE_SIGN); hmac.sign(new byte[]{'j','o','s','h',}, (short)0, (short)4, apdu.getBuffer(), (short)0); apdu.setOutgoingAndSend((short)0, (short)32); // 3A 91 62 FE EF 7B 24 F0 92 07 DC 8E CA 56 4B 7E 69 8D E3 18 94 C9 84 5A 86 EA 52 86 95 75 03 9B ```