熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

MD5的Java Bean實現

2013-11-23 19:05:01  來源: Java核心技術 

  MD簡介
  MD的全稱是MessageDigest Algorithm 年代初由MIT的計算機科學實驗室和RSA Data Security Inc發明經MDMD和MD發展而來
  MessageDigest泛指字節串(Message)的Hash變換就是把一個任意長度的字節串變換成一定長的大整數請注意我使用了字節串而不是字符串這個詞是因為這種變換只與字節的值有關與字符集或編碼方式無關
  MD將任意長度的字節串變換成一個bit的大整數並且它是一個不可逆的字符串變換算法換句話說就是即使你看到源程序和算法描述也無法將一個MD的值變換回原始的字符串從數學原理上說是因為原始的字符串有無窮多個這有點象不存在反函數的數學函數
  MD的典型應用是對一段Message(字節串)產生fingerprint(指紋)以防止被篡改舉個例子你將一段話寫在一個叫readmetxt文件中並對這個readmetxt產生一個MD的值並記錄在案然後你可以傳播這個文件給別人別人如果修改了文件中的任何內容你對這個文件重新計算MD時就會發現如果再有一個第三方的認證機構用MD還可以防止文件作者的抵賴這就是所謂的數字簽名應用
  MD還廣泛用於加密和解密技術上在很多操作系統中用戶的密碼是以MD值(或類似的其它算法)的方式保存的 用戶Login的時候系統是把用戶輸入的密碼計算成MD然後再去和系統中保存的MD值進行比較而系統並不知道用戶的密碼是什麼
  一些黑客破獲這種密碼的方法是一種被稱為跑字典的方法有兩種方法得到字典一種是日常搜集的用做密碼的字符串表另一種是用排列組合方法生成的先用MD程序計算出這些字典項的MD然後再用目標的MD值在這個字典中檢索
  即使假設密碼的最大長度為同時密碼只能是字母和數字++=個字符排列組合出的字典的項數則是P()+P()…+P()那也已經是一個很天文的數字了存儲這個字典就需要TB級的磁盤組而且這種方法還有一個前提就是能獲得目標賬戶的密碼MD值的情況下才可以
  在很多電子商務和社區應用中管理用戶的Account是一種最常用的基本功能盡管很多Application Server提供了這些基本組件但很多應用開發者為了管理的更大的靈活性還是喜歡采用關系數據庫來管理用戶懶惰的做法是用戶的密碼往往使用明文或簡單的變換後直接保存在數據庫中因此這些用戶的密碼對軟件開發者或系統管理員來說可以說毫無保密可言本文的目的是介紹MD的Java Bean的實現同時給出用MD來處理用戶的Account密碼的例子這種方法使得管理員和程序設計者都無法看到用戶的密碼盡管他們可以初始化它們但重要的一點是對於用戶密碼設置習慣的保護
  有興趣的讀者可以從這裡取得MD也就是RFC 的文本
  實現策略
  MD的算法在RFC中實際上已經提供了C的實現我們其實馬上就能想到至少有兩種用Java實現它的方法第一種是用Java語言重新寫整個算法或者再說簡單點就是把C程序改寫成Java程序第二種是用JNI(Java Native Interface)來實現核心算法仍然用這個C程序用Java類給它包個殼
  但我個人認為JNI應該是Java為了解決某類問題時的沒有辦法的辦法(比如與操作系統或I/O設備密切相關的應用)同時為了提供和其它語言的互操作性的一個手段使用JNI帶來的最大問題是引入了平台的依賴性打破了SUN所鼓吹的一次編寫到處運行的Java好處因此我決定采取第一種方法一來和大家一起嘗試一下一次編寫到處運行的好處二來檢驗一下Java 現在對於比較密集的計算的效率問題
  實現過程
  限於這篇文章的篇幅同時也為了更多的讀者能夠真正專注於問題本身我不想就某一種Java集成開發環境來介紹這個Java Bean的制作過程介紹一個方法時我發現步驟和命令很清晰我相信有任何一種Java集成環境三天以上經驗的讀者都會知道如何把這些代碼在集成環境中編譯和運行用集成環境講述問題往往需要配很多屏幕截圖這也是我一直對集成環境很頭疼的原因我使用了一個普通的文本編輯器同時使用了Sun公司標准的JDK for Windows NT
  其實把C轉換成Java對於一個有一定C語言基礎的程序員並不困難這兩個語言的基本語法幾乎完全一致.我大概花了一個小時的時間完成了代碼的轉換工作我主要作了下面幾件事
  把必須使用的一些#define的宏定義變成Class中的final static這樣保證在一個進程空間中的多個Instance共享這些數據
  刪去了一些無用的#if define因為我只關心MD這個推薦的C實現同時實現了MD MD和 MD而且有些#if define還和C不同編譯器有關
  將一些計算宏轉換成final static 成員函數
  所有的變量命名與原來C實現中保持一致在大小寫上作一些符合Java習慣的變化計算過程中的C函數變成了private方法(成員函數)
  關鍵變量的位長調整
  定義了類和方法
  需要注意的是很多早期的C編譯器的int類型是 bit的MD使用了unsigned long int並認為它是bit的無符號整數而在Java中int是 bit的long是 bit的在MD的C實現中使用了大量的位操作這裡需要指出的一點是盡管Java提供了位操作由於Java沒有unsigned類型對於右移位操作多提供了一個無符號右移>>>等價於C中的 >> 對於unsigned 數的處理
  因為Java不提供無符號數的運算兩個大int數相加就會溢出得到一個負數或異常因此我將一些關鍵變量在Java中改成了long類型(bit)我個人認為這比自己去重新定義一組無符號數的類同時重載那些運算符要方便同時效率高很多並且代碼也易讀OO(Object Oriented)的濫用反而會導致效率低下
  限於篇幅這裡不再給出原始的C代碼有興趣對照的讀者朋友可以去看RFC MDjava源代碼
  測試
  在RFC 給出了Test suite用來檢驗你的實現是否正確
  
  MD () = ddcdfbeecfe
  
  MD (a) = ccbcfbace
  
  MD (abc) = cdfbdfdef
  
  MD (message digest) = fbdcbdafaafd
  MD (abcdefghijklmnopqrstuvwxyz) = cfcddedfbccaeb
  ……
  這些輸出結果的含義是指空字符串的MD值是ddcdfbeecfe字符串a的MD值是ccbcfbace……
  編譯並運行我們的程序
  javac –d MDjava
  java beartoolMD
  為了將來不與別人的同名程序沖突我在我的程序的第一行使用了package beartool;
  因此編譯命令javac –d MDjava 命令在我們的工作目錄下自動建立了一個beartool目錄目錄下放著編譯成功的 MDclass
  我們將得到和Test suite同樣的結果當然還可以繼續測試你感興趣的其它MD變換例如
  java beartoolMD 
  將給出的MD
  可能是我的計算機知識是從Apple II和Z單板機開始的我對大寫十六進制代碼有偏好如果您想使用小寫的Digest String只需要把byteHEX函數中的ABCDEF改成ab cdef就可以了
  MD據稱是一種比較耗時的計算我們的Java版MD一閃就算出來了沒遇到什麼障礙而且用肉眼感覺不出來Java版的MD比C版的慢
  為了測試它的兼容性我把這個MDclass文件拷貝到我的另一台Linux+IBM JDK 的機器上執行後得到同樣結果確實是一次編寫到處運行了
  Java Bean簡述
  現在我們已經完成並簡單測試了這個Java Class我們文章的標題是做一個Java Bean
  其實普通的Java Bean很簡單並不是什麼全新的或偉大的概念就是一個Java的Class盡管 Sun規定了一些需要實現的方法但並不是強制的而EJB(Enterprise Java Bean)無非規定了一些必須實現(非常類似於響應事件)的方法這些方法是供EJB Container使用(調用)的
  在一個Java Application或Applet裡使用這個bean非常簡單最簡單的方法是你要使用這個類的源碼工作目錄下建一個beartool目錄把這個class文件拷貝進去然後在你的程序中import beartoolMD就可以了最後打包成jar或war是保持這個相對的目錄關系就行了
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26240.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.