2014/03/07

Just a Note:Sun JCE 驗章問題

驗章時須使用 Public Key,一般來說,在 JCE 下使用已知的 Key 值建立 Public Key 的方式有兩種:

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);

RSAPublicKeySpec keySpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(exponent));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKey pubKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);

差別在於 Key 值的保存型態,
第一種存的是 Key.getEncoded() 的值 (http://docs.oracle.com/javase/7/docs/api/java/security/Key.html),
第二種保存的是 Public Key 的 modulus 和 exponent。而使用第二種方式時,通常我們亦會把 modulus 和 exponent 用 byte[] 保存。

最近遇到的問題是,
如果 Public Key 是透過 RSAPublicKeySpec 建立的話,會驗章失敗;使用 X509EncodedKeySpec 建立的話,則會成功。
但是把兩種方式建出來的 Public Key dump 出來 (getEncoded()),卻會得到一模一樣的值。

Debug 後發現,
RSAPublicKeySpec 建出來的 Key,其 modulus 是負數,
X509EncodedKeySpec 建出來的 Key,其 modulus 則是正數。

解決方式:
當 modulus 的第一個 byte 大於等於 0x80 時,需在最前面多放一個 byte 0x00,再轉成 BigInteger,即能正確取得 modulus 的值。

String modulusStr = "C868EEE8D1D300207EA65DB1DBBFD52552AE1814E07FDF23DE040EC96E6F0F35C8ECF922C11D7F39B3E3162B96881447D16B0FCC75FB0378F2B19AFB22884B8F2E2840C74FE73DBCDBF653E26070955BB9A4011C1EDD9E1DBA482F02091DBBFAD77D13F91A06FF76C8FDE1E4F475A2DFF8A9567C115F50ACCA573315F7723D333218E266984953D0642057C46D6F952CFC7CFAEAA8945FAEDE441ADA8497F0895C1AC18CE6679467F6EFEF5C741879487E94B8DAF87FA45E87FD011BB0A794B4F433B655959B6D1D8164793421A360A39E17A2287EE5CFE7200FF6FA3F407DD7FEC2EAA6C6A89BE5A3CE3073B758E56654C17CE17A3657E76E219E1BECA9115D";
byte[] modulusTmp = Util.hexStringToByte(modulusStr);
byte[] modulus = null;
if (modulusTmp[0] < 0) {
    modulus = new byte[modulusTmp.length + 1];
    modulus[0] = 0x00;
    System.arraycopy(modulusTmp, 0, modulus, 1, modulusTmp.length);
} else {
    modulus = new byte[modulusTmp.length];
    System.arraycopy(modulusTmp, 0, modulus, 0, modulusTmp.length);
}

2014/01/05

Android App:Daily Money Change Log 2014/01/05

This project is a fork of original Daily Money project hosted on github by Dennis Chen

https://github.com/dennischen/daily-money

added: hide accounts with zero balances in reports

新增:在報表隱藏金額為零的帳戶

(顯示)

(隱藏)


2013/05/14

Android App:Daily Money Change Log 2013/05/14

This project is a fork of original Daily Money project hosted on github by Dennis Chen

https://github.com/dennischen/daily-money

added: search details by date and note

新增:根據日期及備註搜尋帳務明細






2013/04/23

Those Days in DES Team


整理硬碟,看到自己過去做的案子、寫的 code,想起自己在 DES Team 的日子。

Genkey 程式
到公司半年後的 2003/3~2004/8 一年半間密集地做了五家銀行主機安控提升案的 Genkey 程式和部分的主機 SUIP 外加一個 Open 端安控系統的功能新增。剛開始甚麼都不懂,只會拿前人已經寫好的程式,複製、修改、測試,過了就當作 OK。

就這樣做了三個專案,上百個 java Panel (12+74+65),常常遇到改個字、調個位置就要同時修改數十支 java 檔。
後面兩個專案因為前面的痛苦經驗+客戶要求,所以把數十個 Panel 彙整成八個,然後另外寫了一個工具產生選單和設定檔,不用一分鐘,就可以完成原本一個 Panel 要做的事情。如果畫面有需要微調的部分,最多也就是改 8 支程式。對比前面三個專案,如果要全部重做,開發的時間大概可以從數週縮短為兩天。
之後又花了一些時間把 Genkey 和工具加以改良,可以同時支援檔案匯出(for 主機安控)和 IC 卡儲存(for Open 安控)。

對 2004 年那個甚麼都還不會的我來說,其實很有成就感,即使現在看來那些 code 寫得一蹋糊塗,但至少縮短了大量瑣碎工作的時間。

只是有趣的是,做完這些之後,我就被派去支援端末,開始游牧民族般的專案生活,再也沒有碰過主機安控系統的開發。所以寫好的工具和程式就跟垃圾一樣一直躺在 file server 和我的硬碟裡,也沒有機會在任何專案中驗證。大概也沒人知道那套程式可以支援 IC 卡儲存。

PS. 後續有兩三個主機提升案曾拿去使用,但據我所知都是加上 Panel 複製、修改的混合體了。

留職停薪
2005/6,在支援端末又被調回後,決定留職停薪。會這麼做要感謝兩個貴人,因為他們很樂於分享,但是很多名詞我都聽不懂,即使是一些很基本的 java 概念。
美其名寫了 3 年的 java,其實當時我連 extends 和 implements 都搞不懂,也不知道甚麼是 abstract class 和 interface,別人明明寫好的 i18n 程式被自己改成 hard code 文字還感到很得意可以省下 native2ascii 的時間。
所以我決定留停 K 書考認證。原本計畫要考 SCJP 和 SCWCD,但惰性比自己預期得來的強大,所以最後草草 K 了 3 週、趕在 voucher 過期前去考了 SCJP,超低空飛過。
2005/10,WOW 開始公測,嗯...就不用多說甚麼了...

Security Server
2006/4,留職停薪後第一個正式參與的專案。
第一次從無到有寫 socket server、multi-thread、JCE 程式。其實一度因為寫不出來想放棄,所幸後來有把程式生出來交差......依然要感謝相同的兩個貴人,一個提供我很多建議、一個提供我範例程式且適當地回絕了我的推託。
接著又陸續調整,用在其他四、五個專案,相同的架構、介接不同的 HSM。
但因為工作分派的關係,幾乎都交接出去。
可能是我程式寫得很爛吧!即使花了很多時間做交接,感覺也沒人真的去了解我的想法、說了甚麼、寫了甚麼,得不到任何反饋。唯一的反饋當時覺得很刺耳,但的確也是我到現在都還不足之處。

不管是 Genkey 還是 SS,即使到現在,我都一直還覺得有很多地方可以改進、需要改善。
但說真的,想歸想,真的一點動力都沒有。反正大部分的人都覺得能跑就好了。



DES 的專案其實很有趣,完全就是看客戶環境決定你需要在甚麼平台、用甚麼程式語言寫程式。在留停之前的短短三年內,我寫過 COBOL、Java、C/C++、VB、ASP,碰過的作業系統有 OS2、Windows、RedHat、FreeBSD、CICS、IMS、AIX、AS400,雖然沒有任何一項能搬上檯面,但是在這些專案中,我想我大概理解了 SI 的意義。
時至今日,大環境並未改變,甚至更為複雜,我想,大概永遠只能當隻鼯鼠。


2013/04/05

Candy Crush


Candy Crush 最近火紅,在 FB 上連很多早就宣告不玩遊戲、不接收遊戲 request 的朋友都淪陷了。
我也不例外,完成 170 關,不過距離目前開放的 355 關,連一半都還不到。

心得:
1. 基本上這是個很吃運氣的遊戲,愈後面的關卡愈是如此。
2. 遊戲支援 Android、iOS、FB,每個裝置的「愛心」數量是獨立的、而完成的關卡在與 FB 連結後是同步的,所以像我有兩台 Android 裝置加 FB,每次玩就基本有 15 次機會。
3. 第一個連結 FB 的裝置,只要不確認,就可以保留所有 FB 好友送愛心的訊息。但如果是用 FB 開啟遊戲,所有訊息中的愛心或物品都會直接視為已接收,無論你有沒有按確認。
4. 基於 2, 3 兩點,到後來除非連玩好幾小時,不然其實很難把愛心用完。

不過決定要戒了,
我想最簡單的戒法就是當遇到需要 3 個 FB 好友才能解開後續關卡時,不要送出 request,就像現在一樣。

2013/03/23

Just a Note:SVN Repository Partial Merge

先描述一下情境,目的是要將自己開發環境的 svn 轉移到客戶的 svn repository。

客戶的 svn repository 事先就建立好,且有制定好的目錄結構,我們只是將 source 放到對應的路徑下。
現行的做法是,從開發環境 checkout 出最後一版資料,然後 commit 到客戶的 svn repository,視為全新的開始,過去的歷程就一筆勾銷。
然後開發人員便將 svn reporistory 重新指到客戶的環境。
這其實也沒什麼問題,因為客戶根本不需要知道開發期間資料來來回回異動的歷程。

只是對於沒事會常常去看歷程的人來說(<-- 就是我),歷程突然都沒了(除非連回原本的 repository),其實很困擾。

是不是有什麼辦法可以在移轉後保留原本歷程呢?因此有了這篇筆記。

2013/02/19

Just a Note:Convert Data between UTF16 String and Words

用 Java 很容易,用 javascript 完全沒頭緒......記個筆記,順便灌溉一下乾涸的 blog......

Convert data between UTF16 String and Words by using CryptoJS components.

Example:


<!DOCTYPE html>
<html>
<head>
<script src="core.js"></script>
<script src="enc-utf16.js"></script>
<script>
function testTo() {
    var data = document.getElementById("inputData").value;
    document.getElementById("result").innerHTML=CryptoJS.enc.Utf16LE.parse(data);
}
function testFrom() {
    var data = document.getElementById("inputData").value;
    var a = [];
    for(var i=0; i<data.length; i+=8){
        a.push('0x'+data.substring(i,i+8));
    }
    var words = CryptoJS.lib.WordArray.create(a);
    document.getElementById("result").innerHTML=CryptoJS.enc.Utf16LE.stringify(words);
}
</script>
</head>
<body>
<input type="text" id="inputData" />
<button type="button" onclick="testTo()">to UTF16-LE</button><button type="button" onclick="testFrom()">from UTF16-LE</button>
<div id="result"></div>
</body>
</html>


Get core.js, enc-utf16.js from CryptoJS.

Download the example code