卡法電子商務 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.pswp.cn/news/529531.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/529531.shtml
英文地址,請注明出處:http://en.pswp.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月份就已經進行了…