javacard DES算法API使用示例

很多时候我们并不需要自己去实现一个较为复杂的算法,而只需要知道怎么去调用现有的实现。API调用,在C/C++是用include+函数的形式,java其实也无非就是import+类(方法、变量)的形式,其他语言的也差不多,例如web里面的前端框架,所谓框架其实就是一堆别人已经写好的代码,你拿去用,然后继续在上面填充自己的代码,说到底其实就是代码复用。而在java这里,因为以.class文件的形式封装了实现,我们看到的接口:一堆.class文件里面方法的具体实现被隐藏了,只能看到个函数原型,所以调用javacard
API的难度在于你得去看别人写的API注释(全英,学好英语的作用有木有),去了解每个函数干什么的,然后你才知道要实现自己的功能需要用到它的哪些函数以及调用顺序是怎样的,一般在API(库)的目录下面都会有使用文档(html形式的),用eclipse直接翻.class文件的话会有一堆html标签符看着眼疼。

话说不多,上代码:

Des.java(调用DES算法API的主要文件):

package helloWorld;
import javacard.framework.JCSystem;
import javacard.security.DESKey;
import javacard.security.Key;
import javacard.security.KeyBuilder;
import javacardx.crypto.Cipher;

public class Des
{
	private Cipher DESEngine;
	private Key myKey;
	private byte[] temp;
	private RandGenerator rand;

	public Des()
	{
		//必须先初始化(获得实例instance才能init否则报错)
		DESEngine = Cipher.getInstance(Cipher.ALG_DES_CBC_ISO9797_M1, false);

		//buildKey创建的是未初始化的key,密钥值需用setKey函数手动赋值
		myKey = KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES, false);

		//设置暂存变量temp
		temp = JCSystem.makeTransientByteArray((short)64, JCSystem.CLEAR_ON_DESELECT);

		//给rand对象也分配空间,不然无法执行RandGenerator类的代码!!
		rand = new RandGenerator();

		//****** 1 *******首先自动生成个密钥

		//产生64bit随机数
		temp = rand.GenrateSecureRand((short)64);

		//Util.arrayFillNonAtomic(temp1, (short)16, (short)48, (byte)0x11);

		//设置密钥--拿随机数当密钥
		((DESKey)myKey).setKey(temp, (short)0); 

		//****** 2 *******初始化加密密钥和加密模式
		DESEngine.init(myKey, Cipher.MODE_ENCRYPT);
	}

	public final void GetCipher(byte[] inBuf, short inOffset, short inLength, byte[] outBuf, short outOffset)
	{
		//****** 3 *******传入密文进行加密并得到密文
			//需要特别注意doFinal加密之后的结果估计有64位以上,所以outBuf在前面的定义时也要new出足够的大小,否则又no precise...
		DESEngine.doFinal(inBuf, inOffset, inLength, outBuf, outOffset);
	}
}

(徒手生成密钥太麻烦,所以我这里直接调用生成随机数的API,拿随机数来当密钥)

接着就是生成随机数的RandGenerator.java文件,调用了RandomData API:

package helloWorld;
import javacard.framework.JCSystem;
import javacard.security.RandomData;

public class RandGenerator
{
	private byte[] temp;	//随机数的值
	private RandomData random;
	private byte size;	//随机数长度

	//构造函数
	public RandGenerator()
	{
		size = (byte)4;
		temp = JCSystem.makeTransientByteArray((short)4, JCSystem.CLEAR_ON_DESELECT);
		//类当中有getInstance的都要先调用这个函数获取对象实例才能使用其他方法,不然6F00
		random = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
	}

	//产生length长度的随机数并返回
	public final byte[] GenrateSecureRand(short length)
	{
		temp = new byte[length];
		//生成4bit的随机数
		random.generateData(temp, (short)0, (short)length);
		return temp;
	}

	//返回随机数长度
	public final byte GetRandSize()
	{
		return size;
	}
}

最后是测试Applet,Hello.java文件:

package helloWorld;

//import Hello;
import javacard.framework.APDU;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.Util;

public class Hello extends Applet {
	//下面这些都是未分配空间的实例化!需要后面自己使用new关键字或者用getInstance函数分配空间!
	private Des des = new Des();

	public static void install(byte[] bArray, short bOffset, byte bLength) {
		// GP-compliant JavaCard applet registration
		new Hello().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
	}

	public void process(APDU apdu) {
		// Good practice: Return 9000 on SELECT
		if (selectingApplet()) {
			return;
		}

		//将缓冲区与数组buf建立映射绑定
		byte[] buf = apdu.getBuffer();

		short lc = apdu.setIncomingAndReceive();//读取data并返回data长度lc

		byte[] data = new byte[lc];
		Util.arrayCopyNonAtomic(buf, ISO7816.OFFSET_CDATA, data, (short)0, lc);

		//byte[] src = {'h','e','l','l','o',',','w','o','r','l','d'};//11 bytes
		byte[] cipher = new byte[128];

		byte ins = buf[ISO7816.OFFSET_INS];

		switch (ins) {
		case (byte) 0x00://INS == 0x00 表明要用DES加密
			//****** 3 *******传入密文进行加密并得到密文
			des.GetCipher(data, (short)0, lc, cipher, (short)0);
			Util.arrayCopyNonAtomic(cipher, (short)0, buf, (short)ISO7816.OFFSET_CDATA, lc);
			apdu.setOutgoingAndSend((short)5, lc);
			break;//一定要有break否则会继续进入switch循环
		case (byte) 0x01:
			break;
		default:
			// good practice: If you don't know the INStruction, say so:
			ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
		}
	}

}

然后用JCOP Shell工具执行测试。

测试脚本(des.jcsh):

/select 554433221100
/send 00000000041234567804
/send 00000000048765432104

/第一句表示选定该AID的Applet,后两句都是输入一串0x04长度的数据让Applet去执行加密(注意十六进制和十进制数之间转化,虽然这里0x04长度等于十进制的4个长度,但是0x20就千万记得要转换了)。

执行脚本看到结果:

Applet返回0x04长度的加密后的密文。

最后记录几个自己在写代码的过程中遇到的一些需要注意的事项。

1:因为涉及到了多个类,所以会有在另一个类(文件)中建立类的对象,但是千万记得要给这个对象分配空间!类如果有有getInstance函数的就调用这个函数进行对象的实例化,如果没有的就用new关键字来分配空间给对象!之前自己就出现了没分配空间给对象的情况,结果测试时返回6F00,然后调试的时候一直是跳不进去Des.java的,因为根本没分配空间给这个对象,也就无从谈跳过去执行Des.java里面的代码了。这个在面向对象编程尤其需要注意。

2:暂存对象(包含变量/数组)与永久对象。用JCSystem.makeTransientByteArray(第一个参数表示数组长度,第二个参数表示声明周期(一般用CLEAR_ON_DESELECT也就是该AID的Applet被deselect的时候被回收))函数可以声明一个固定长度的暂存数组。为什么要用到暂存对象呢?因为javacard毕竟那么小,它所拥有的存储空间(无论是内存或者是ROM(包括那个啥EEPROM))都是很有限的,ROM一般是用来存卡片操作系统(COS,一般用汇编写成)和虚拟机(必须下层有操作系统作为基础,自己并不是操作系统)的,永久对象会存放在EEPROM空间当中,而暂存对象(数组)存放在RAM空间中,自然读写速度就快很多,所以对于需要更新次数频繁的数据,并且暂存即可的,声明为暂存对象可提高程序效率。同时,EEPROM中创建的对象,对这些对象的操作必须具有原子性(例如javacard的事务[transaction]处理机制),而RAM里面对象的处理自然不具有原子性。

3:阅读API里面的函数时容易发现有些在前面带“@deprecated”字眼,@override表示覆盖父类的方法,而前面这个表示不建议使用的方法(即将被淘汰或怎样的),一般这个方法都会被删除线划掉。

4:然后说一个跟des加密不相关的,是跟公钥密码系统如RSA算法相关的,des这些对称密码系统只需要一个密钥,而公钥系统需要公钥私钥,所以需要用一个KeyPair对象去存储私钥和公钥,而不能用PrivateKey对象和PublicKey对象就算了,需要用KeyPair对象囊括住这两个对象,后面会继续写RSA算法API调用的blog。

5:switch相当于一个循环,在每一个case后面都必须要加一个break关键字,否则执行完一次case之后会继续跑去循环,下一次的话case的值是不确定的,所以会跳去执行default语句里面的代码,所以如果执行的某个case里面没有break,程序后面还会执行default里面的语句。

6:提到对象的初始化(分配空间),注意这个操作一般放在类的构造函数当中,如果是Applet主文件,就在install()的时候完成这些操作。

7:最后抽取几个上面的关键函数出来提一提:

DESEngine = Cipher.getInstance(Cipher.ALG_DES_CBC_ISO9797_M1, false);

上面这句代码是用来实例化DES引擎对象的,做一些分配空间和初始化之类的工作,替代了new去完成分配空间的事。

myKey = KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES, false);

然后这句代码是用来创建未初始化的key对象,前面我们说到对象你在用它们之前必须给他们先分配空间!这里buildKey出来的只是分配好了空白空间的对象,后面需要自己用setKey函数来初始化密钥。

((DESKey)myKey).setKey(temp, (short)0);

这句就是设置(初始化)密钥了,temp在这里存的是前面提到的生成的随机数,拿来当密钥使。

密钥设置好了,然后就是将这个密钥扔到DES引擎对象里面去,用下面这个函数:

DESEngine.init(myKey, Cipher.MODE_ENCRYPT);

第二个参数表示的是设置模式,有加密和解密两种。

最后就可以传入数据进行加密得到密文了:

DESEngine.doFinal(inBuf, inOffset, inLength, outBuf, outOffset);
时间: 2024-08-27 00:27:58

javacard DES算法API使用示例的相关文章

delphi 银联POS终端MAC算法(单倍DES算法)

//主窗体界面代码 procedure TForm1.Button1Click(Sender: TObject);  var    lv_context : string;    lv_acontext : TMyByteArray;    lv_key : string; begin   lv_context := HexToString(Trim(Edit1.Text));   lv_key := Trim(Edit3.Text);   strToByteArray(lv_context, 

Python实现各种排序算法的代码示例总结

Python实现各种排序算法的代码示例总结 作者:Donald Knuth 字体:[增加 减小] 类型:转载 时间:2015-12-11我要评论 这篇文章主要介绍了Python实现各种排序算法的代码示例总结,其实Python是非常好的算法入门学习时的配套高级语言,需要的朋友可以参考下 在Python实践中,我们往往遇到排序问题,比如在对搜索结果打分的排序(没有排序就没有Google等搜索引擎的存在),当然,这样的例子数不胜数.<数据结构>也会花大量篇幅讲解排序.之前一段时间,由于需要,我复习了

Linux程序设计学习笔记----网络通信编程API及其示例应用

转载请注明出处, http://blog.csdn.net/suool/article/details/38702855. BSD Socket 网络通信编程 BSD TCP 通信编程流程 图为面向连接的Socket通信的双方执行函数流程.使用TCP协议的通信双方实现数据通信的基本流程如下 建立连接的步骤 1.首先服务器端需要以下工作: (1)调用socket()函数,建立Socket对象,指定通信协议. (2)调用bind()函数,将创建的Socket对象与当前主机的某一个IP地址和TCP端口

速码验证码接码平台API接入示例说明

速码平台API接口示例[通用版] 一.统一说明 接口地址:http://api.eobzz.com/httpApi.do?action= 接口统一编码:UTF-8 接口调用方式: HTTP,支持GET和POST两种方式. GET方式调用实例:http://api.eobzz.com/httpApi.do?action=方法名&参数1=值&参数2=值(具体方法名及参数请参考接口方法). 软件开发者说明:服务器返回no_data时表示系统暂时没有可用号码了,请使用死循环每隔一分钟请求一次手机号

DES算法详解

本文主要介绍了DES算法的步骤,包括IP置换.密钥置换.E扩展置换.S盒代替.P盒置换和末置换. 1.DES算法简介 DES算法为密码体制中的对称密码体制,又被称为美国数据加密标准. DES是一个分组加密算法,典型的DES以64位为分组对数据加密,加密和解密用的是同一个算法. 密钥长64位,密钥事实上是56位参与DES运算(第8.16.24.32.40.48.56.64位是校验位,使得每个密钥都有奇数个1),分组后的明文组和56位的密钥按位替代或交换的方法形成密文组. DES算法的主要流程如下图

wex5 实战 加密与解密系列(1) DES算法引入与调用

作为web前端应用来说,与服务器通讯或后端通讯,以及不同用户间传递数据,在一些特定情况下需要对一些信息进行加密传输,在某个事件中取出信息并解密,得到正确的信息.纵观不同语言和不同算法,有很多种选择.今天,从最基础的加密与解密算法DES说起,深入浅出,看看wex5如何简单高效的实现DES算法加密与解密.便于课程需要,制作了demo,及js改装注释. 一 效果演示 如图所示,加密,生成一堆乱码,解密还原得到正确信息. 二 设计思路 制作并引入des.js文件,前端直接调用js方法实现加密解密. 三

Html5之高级-14 Web Socket(概述、API、示例)

一.Web Socket 概述 Web Socket 简介 - Web Socket 是 HTML5 提供的在 Web应用程序中客户端与服务器端之间进行的非 HTTP 的通信机制 - Web Socket 实现了用 HTTP 不容易实现的服务器端的数据推送等智能通讯技术 Web Socket 的特点 - Web Socket 可以在服务器与客户端之间建立一个非 HTTP 的双向连接 - 这个连接时实时的,也是永久的 - 服务器端可以主动推送消息 - 服务器端不再需要轮询客户端的请求 - 服务器端

Mahout推荐算法API详解

前言 用Mahout来构建推荐系统,是一件既简单又困难的事情.简单是因为Mahout完整地封装了“协同过滤”算法,并实现了并行化,提供非常简单的API接口:困难是因为我们不了解算法细节,很难去根据业务的场景进行算法配置和调优. 本文将深入算法API去解释Mahout推荐算法底层的一些事. 1. Mahout推荐算法介绍 Mahoutt推荐算法,从数据处理能力上,可以划分为2类: 单机内存算法实现 基于Hadoop的分步式算法实现 1). 单机内存算法实现 单机内存算法实现:就是在单机下运行的算法

Asp.Net 常用工具类之加密——对称加密DES算法(2)

又到周末,下午博客园看了两篇文章,关于老跳和老赵的程序员生涯,不禁感叹漫漫程序路,何去何从兮! 转眼毕业的第三个年头,去过苏州,跑过上海,从一开始的凌云壮志,去年背起行囊默默回到了长沙准备买房,也想有个家(毕竟年级不小了),有盼头的工作前景. 看到老赵和老跳两位前辈的故事,真实且现实,同时也有一丢丢的小迷茫,敢问路在何方! 感叹一会儿,生命不止,Code不止,继续入坑! 昨天分享了一下非对称加密RSA算法,今天给朋友们分享一下对称加密DES算法案例. 加解密过程: 1.生成加密密钥key,密码越