创建一个javaCard applet并实现加密解密功能

学习目标:

简单掌握applet加密解密


学习内容:

首先我们定义两个全局变量,方便让我们指定的apdu命令进行匹配并进行加密解密

// Instruction bytes
    private static final byte  INS_ENCRYPT = (byte) 0x10;
    private static final byte  INS_DECRYPT = (byte) 0x20;

然后我们在switch循环中当INS值是INS_ENCRYPT就进行加密,是INS_DECRYPT就进行解密

switch (buffer[ISO7816.OFFSET_INS]) {
		case INS_ENCRYPT:
			encrypt(apdu);
			break;
		case INS_DECRYPT:
			decrypt(apdu);
			break;
		default:
			// good practice: If you don't know the INStruction, say so:
			ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
		}

当进行加密时,就会进入方法encrypt,进行加密操作,并将加密后的数据进行返回

private void encrypt(APDU apdu) {
        byte[] buffer = apdu.getBuffer();
        
        // 检查P1和P2是否正确
        if (buffer[ISO7816.OFFSET_P1] != (byte) 0x00 || buffer[ISO7816.OFFSET_P2] != (byte) 0x00) {
            ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
        }

        // 设置加密模式
        cipher.init(aesKey, Cipher.MODE_ENCRYPT);

        // 加密数据
        cipher.doFinal(buffer, ISO7816.OFFSET_CDATA, (short) 16, buffer, ISO7816.OFFSET_CDATA);

        // 设置返回值
        apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, (short) 16);
    }

而当我们设置加密模式的时候,需要指定key以及mode,因此我们需要构建密钥,而构建key时需要选择算法以及长度,和是否加密,这里我选择的是TYPE_AES,这里呢也是指定了Cipher为AES ECB模式。考虑到如果我们的apdu命令如果没有带data数据,则会默认使用keyData进行一个加密解密。

private Test3(){
    	byte[] keyData = new byte[] { (byte) 0xA1, (byte) 0x12, (byte) 0xBC, (byte) 0x8C, (byte) 0xAB, (byte) 0xDC, (byte) 0x4F,
                (byte) 0x46, (byte) 0x74, (byte) 0x27, (byte) 0xDA, (byte) 0xE6, (byte) 0x41, (byte) 0xE6, (byte) 0x3D,
                (byte) 0xBF};
    	// 创建密钥,使用128位的AES算法
        aesKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false);
        // 使用固定的十六字节密钥
        aesKey.setKey(keyData, (short) 0);
        // 指定算法AES ECB模式(分块解密模式)
        cipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_ECB_NOPAD, false);
    }

而解密呢,则与加密的流程差不多,这里我附上解密方法的代码

 private void decrypt(APDU apdu) {
        byte[] buffer = apdu.getBuffer();

        // 检查P1和P2是否正确
        if (buffer[ISO7816.OFFSET_P1] != (byte) 0x00 || buffer[ISO7816.OFFSET_P2] != (byte) 0x00) {
            ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
        }

        // 设置解密模式
        cipher.init(aesKey, Cipher.MODE_DECRYPT);

        // 解密数据
        cipher.doFinal(buffer, ISO7816.OFFSET_CDATA, (short) 16, buffer, ISO7816.OFFSET_CDATA);

        // 设置返回值
        apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, (short) 16);
	}

最后然我们一起在JCOP shell测试一下,看程序是否正确

 这里看到我们加密解密成功了,状态也是90 00,这次的学习就到这里吧!

javacard applet 开发实例 正常运行 带jar包 package mifare; import com.ibm.jz.JZSystem; import javacard.framework.APDU; import javacard.framework.Applet; import javacard.framework.ISO7816; import javacard.framework.ISOException; import javacard.framework.Util; public class AmbiqApplet extends Applet { byte[] mifarePassDefault={(byte)0x0b,(byte)0x54,(byte)0x57,(byte)0x07,(byte)0x45,(byte)0xfe,(byte)0x3a,(byte)0xe7}; byte[] mifarePass8={(byte)0x0b,(byte)0x54,(byte)0x57,(byte)0x07,(byte)0x45,(byte)0xfe,(byte)0x3a,(byte)0xe7}; byte[] mifarePass9={(byte)0x0b,(byte)0x54,(byte)0x57,(byte)0x07,(byte)0x45,(byte)0xfe,(byte)0x3a,(byte)0xe7}; byte[] adminPass={(byte)0x40,(byte)0x41,(byte)0x42,(byte)0x43,(byte)0x44,(byte)0x45,(byte)0x46,(byte)0x47,(byte)0x48,(byte)0x49,(byte)0x4a,(byte)0x4b,(byte)0x4c,(byte)0x4d,(byte)0x4e,(byte)0x4f}; public static void install(byte[] bArray, short bOffset, byte bLength) { // GP-compliant JavaCard applet registration new AmbiqApplet().register(bArray, (short) (bOffset + 1), bArray[bOffset]); } public void process(APDU apdu) { short i; byte[] send=new byte[52]; byte[] send2=new byte[24]; // Good practice: Return 9000 on SELECT if (selectingApplet()) { return; } byte[] buf = apdu.getBuffer(); if(buf[ISO7816.OFFSET_CLA]==AmbiqConstant.CLS_AMBIQ) { switch (buf[ISO7816.OFFSET_INS]) { case AmbiqConstant.INS_GET_MIFARE: if(buf[ISO7816.OFFSET_P1]!=0 || buf[ISO7816.OFFSET_P2]!=0) { ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); return; } /*Get Entire Mifare Ticket data * Returns back the content of the entire sector 8 (3 block 8.0, 8.1, 8.2) and the first 4 bytes of block 9.0; total 52bytes. Filed Length (in bytes) Data Comments CLA 1 0x80 Fixed class for the applet INS 1 0x20 Read entire data P1 1 0x00 Sector number P2 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值