卡法电子商务 java_javacard DES算法API使用示例

**********   2017年3月15日留言 ——关于java卡Applet系列csdn博文 *************

貌似有不少人在看我写的几篇关于java卡applet的博文,也收到了一些评论指正博文错误,或者私信叫我发代码文件过去。在此需要说明的是,java卡applet的这几篇博文是自己在初学java卡applet的时候写的,当时菜鸟一枚(虽然现在也还是菜鸟),未免会有些疏漏,仅供参考,希望大家在看的时候别太当权威,如果博文中有错误也请谅解。另外关于叫我发代码的,因为有些代码文件中的部分代码并非是我写的,怕牵涉到版权问题,所以就不能私发了,不过我在博文放的我的那个github地址里面的代码可以去看看,另外因为版权问题其实我后期对博文很多地方的代码做了删改,所以现在看起来博文好像有些凌乱,几个月前自己已经不做java卡applet这方面的开发了,所以也就没再细心去修改好博文了,java卡applet在行业内已经有好几年的历史了,大家上网多找找,其实能找到很多更好的学习材料,当然,有不少是全英的,不过其实很多很好的材料就只有英文的,所以多去翻翻前辈们的精华吧!Best

wish~

********************** 新旧分割线  *****************************

很多时候我们并不需要自己去实现一个较为复杂的算法,而只需要知道怎么去调用现有的实现。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就千万记得要转换了)。

执行脚本看到结果:

c6c2d709739b4bf6823b964ac224eb26.png

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

******    更新分隔线   *********

这个代码挺不完善的,升级版的可以参考我另一篇博文:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/529531.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java http请求原理_浅谈Spring Cloud zuul http请求转发原理

spring cloud 网关,依赖于netflix 下的zuul 组件zuul 的流程是,自定义 了ZuulServletFilter和zuulServlet两种方式,让开发者可以去实现,并调用先来看下ZuulServletFilter的实现片段Overridepublic void doFilter(ServletRequest s…

java堆外内存溢出_JVM 案例 - 堆外内存导致的溢出错误

案例一个网站为了实现客户端实时从服务端接收数据,使用了 CometD 1.1.1 作为服务端推送框架,服务器是 Jetty7.1.4,CPU i5,内存 4G,操作系统 32位Windows。服务端常常抛出内存溢出异常,管理员把堆开到最大(3…

java mail outlook_已启用Outlook API邮件与邮箱用户

一个非常微妙的问题,也许是特定的环境 . 我正在尝试使用Outlook 2010 API从启用邮件的用户中识别邮箱用户 . 我们在Notes to Exchange迁移期间使用Dell Quest迁移工具,它是一个流动的项目 . 仍处于原型阶段,因此使用VB宏来最终将在C&#xff…

oracle java存储过程返回值_java程序调用Oracle 存储过程 获取返回值(无返回,非结果集,结果集)...

java程序调用Oracle 存储过程 获取返回值(无返回,非结果集,结果集)oracle中procedure是不能有返回值的,要想返回值,就得有输出参数,同样要想返回记录集,可以把游标类型作为输出参数。下面是详细情况说明&am…

mysql dump工具升级_MySQL数据库升级

当前不少系统的数据库依旧是MySQL5.6,由于MySQL5.7及MySQL8.0在性能及安全方面有着很大的提升,因此需要升级数据库。本文通过逻辑方式、物理方式原地升级来介绍MySQL5.6 升级至MySQL5.7的方法,并介绍其使用场景。1. 逻辑方式升级逻辑方式升级…

java int 128 ==_为什么 Java Integer 中“128==128”为false,而”100==100“为true?

这是一个挺有意思的讨论话题,让我们用代码说话吧!运行下面的代码:Integer a 128, b 128;System.out.println(a b);Integer c 100, d 100;System.out.println(c d);你会得到:falsetrue基本知识:我们知道,如果两个引用指向同一个对象&…

mysql课程表学时_Mysql 巩固提升 (学生表_课程表_成绩表_教师表)

方便Mysql 巩固提升创建表并插入数据:-- ------------------------------ Table structure for student-- ----------------------------DROP TABLE IF EXISTS student;CREATE TABLE student (id int(11) NOT NULL AUTO_INCREMENT,sname varchar(32) DEFAULT NULL,s…

初始java_第一章__初始JAVA

1.java的三个发展方向:JAVASE(面向对象、API、JVM)、JAVAME(移动设备、游戏、通信)、JAVAEE(JSP、EJB、服务)2.开发JAVA的程序步骤:1.编写源程序 2.编译 3.运行3.JDKJRE开发工具下载java环境jdk 安装并配置环境变量,.安装直接下一步下一步直到…

python最常用的版本、也称为classic_2021年中国大学《创新思维与创业》单元测试答案...

2021年中国大学《创新思维与创业》单元测试答案被人们称为 “寒地水稻第一人”的是袁隆平答:错地图数据的基本特征包括答:时间属性 空间定位属性 地理属性对卖方征税导致商品价格上升答:√( )是在床榻上使用的一种矮形家具。答:炕…

java 泛型 继承_java基础之泛型的继承

关于泛型的基本介绍和理解请参考以下几篇文章&#xff0c;或查询更多资料&#xff1a;本篇以简单的List<>方式来进行说明。ArrayList继承了List,ArrayList没有继承ListList>等价于List extends Object>请参考以下代码&#xff1a;/*** author Ding Chengyun* 2014-…

appium java环境_Appium环境搭建(Windows版)

注&#xff1a;appium安装到C盘&#xff0c;node.js安装到C盘一、安装node.js1、到官网下载node.js&#xff1a;https://nodejs.org/en/download/2、获取到安装文件后&#xff0c;直接双击安装文件&#xff0c;根据程序的提示&#xff0c;完成nodejs的安装。3、安装完成后&…

ci mysql pdo_CI框架中pdo的使用方法

1、配置文件修改application/config文件夹下的database.php文件 $db[default] array(dsn > mysql:dbnameci_ecshop;host127.0.0.1,username > root,password > ,dbdriver > pdo,2、查询操作$sql select * from aaa where id :id;$sql_array array(:id > …

ie11加载java插件_IE浏览器中ActiveX插件的使用

在某些行业的B/S应用系统中会不可避免的要用到ActiveX浏览器插件&#xff0c;而ActiveX插件只能在IE内核浏览器中运行&#xff0c;而常用的IE浏览器的版本众多&#xff0c;从IE6到IE11&#xff0c;总共有6个版本&#xff0c;这就给开发的应用系统造成了不小的困扰&#xff1a;如…

netty java开发文档_Netty简明教学文档

写个简单点&#xff0c;比较小白的文档&#xff0c;言语比较接地气Netty是什么&#xff1f;NIO的高层封装&#xff0c;NIO很难写&#xff0c;所以有了Netty&#xff0c;方便异步的操作service的主要代码片段public void run() throws Exception {EventLoopGroup bossGroup new…

mysql 全局不重复_php uniqid() 通过MYSQL实现全局不重复的唯一ID

看了国外文章&#xff1a;https://jason.pureconcepts.net/2013/09/php-convert-uniqid-to-timestamp/ 不想写&#xff50;&#xff48;&#xff50;脚本uniqid()处理&#xff0c;想到用mysql一次性把数据库的ID改过来的方法&#xff0c;所以开始了以下研究方法一: 效率最高&…

java接口允许ajax访问_服务允许AJAX请求,允许跨域请求

当工作时间&#xff0c;因为需要JS 进行AJAX请求&#xff0c;这时候存在跨域问题&#xff0c;当出现这种情况时&#xff0c;有多种方案解决比如使用JSONP&#xff0c;也有一种简单的方式&#xff0c;就是在过滤器里面增加返回请求允许跨域head配置。代码如下&#xff1a;/**** …

mysql的增_MySQL之增_insert-replace

MySQL增删改查之增insert、replace一、INSERT语句带有values子句的insert语句&#xff0c;用于数据的增加语法&#xff1a;INSERT [INTO] tbl_name[(col_name,...)]{VALUES | VALUE} (expr ,...),(...),...①用来把一个新行插入到表中②为和其它数据库保持一致&#xff0c;不要…

python manager详解_python 多进程共享全局变量之Manager()详解

Manager支持的类型有list,dict,Namespace,Lock,RLock,Semaphore,BoundedSemaphore,Condition,Event,Queue,Value和Array。但当使用Manager处理list、dict等可变数据类型时&#xff0c;需要注意一个陷阱&#xff0c;即Manager对象无法监测到它引用的可变对象值的修改&#xff0c…

java 添加等待时间_Java中线程等待特定时间的最有效方法 - java

我知道这个问题here&#xff0c;但是我有一个稍微不同的问题。如果我希望自己通过各种Thread方法(而不是通过实用程序类或Quartz)手动编码某个线程在特定时间的运行&#xff0c;那么最有效(就开销而言)进行编码。我考虑过:boolean wasInterrupted false;while (System.current…

PHP微信app接口退款,10.PHP接入微信退款接口

推荐文章摘要环境搭建开启配置服务器环境核心类验证回复拓展推荐文章今天网上和朋友圈炸开了锅&#xff0c;原因是微信小程序正式上线了。吃瓜群众表示不理解&#xff0c;于是去搜了下。不搜不要紧&#xff0c;搜了吓一跳&#xff0c;原来微信小程序早在2016年9月份就已经进行了…