JAVA—咖啡館

          ——歡迎訪問rogerfan的博客,常來《JAVA——咖啡館》坐坐,喝杯濃香的咖啡,彼此探討一下JAVA技術,交流工作經驗,分享JAVA帶來的快樂!本網站部分轉載文章,如果有版權問題請與我聯系。

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            447 Posts :: 145 Stories :: 368 Comments :: 0 Trackbacks

          Java 加密技術:消息摘要。

          一個消息摘要就是一個數據塊的數字指紋。即對一個任意長度的一個數據塊進行計算,產生一個唯一指印(對于SHA1是產生一個20字節的二進制數組)。

          消息摘要有兩個基本屬性:

          兩個不同的報文難以生成相同的摘要
          難以對指定的摘要生成一個報文,而由該報文反推算出該指定的摘要
          代表:美國國家標準技術研究所的SHA1和麻省理工學院Ronald Rivest提出的MD5


          類 java.security.MessageDigest

          java.lang.Object
          |
          +----java.security.MessageDigest
          

          public abstract class MessageDigest
          extends Object

          MessageDigest 提供了消息摘要算法,如 MD5 或 SHA,的功能。消息摘要是安全單向散列函數,它采用任意大小的數據并輸出一個固定長度的散列值。

          象 Java 安全性中的其它基于算法的類一樣,MessageDigest 有兩個主要的組件:

          消息摘要 API ( 應用程序接口 )
          這是需要消息摘要服務的應用調用的方法的接口。這個 API 由所有公有方法組成。
          消息摘要 SPI ( 服務提供者接口 )
          該接口是由提供特殊算法的提供者實現的接口。它由所有名字前綴為 engine 的方法組成。每個這樣的方法由具有相應名字的公有 API 方法調用。例如,engineReset 方法由 reset 方法調用。SPI 方法是抽象的;提供者必須提供一個具體的實現。

          MessageDigest 對象在啟動時被初始化。使用 update 方法處理數據。在任何地方都可調用 reset 復位摘要。一旦所有需要修改的數據都被修改了,將調用一個 digest 方法完成散列碼的計算。

          對于給定次數的修改,只能調用 digest 方法一次。在調用 digest 之后,MessageDigest 對象被復位為初始化的狀態。

          可以自由的實現 Cloneable 接口,這樣做將會使客戶應用在復制前用 instanceof Cloneable 測試可復制性:

           

           MessageDigest md = MessageDigest.getInstance("SHA");
          if (md instanceof Cloneable) {
          md.update(toChapter1);
          MessageDigest tc1 = md.clone();
          byte[] toChapter1Digest = tc1.digest;
          md.update(toChapter2);
          ...etc.
          } else {
          throw new DigestException("couldn't make digest of partial content");
          }
          

          注意如果給定的實現是不可復制的,如果事先知道摘要的數目,仍然能以幾個實例為例計算中間的摘要。

          構造子

          MessageDigest

           protected MessageDigest(String algorithm)
          
          用指定的算法名創建一個消息摘要。

           

          參數:
          algorithm - 摘要算法的標準字符串名。 Java 密碼結構 API 說明書 & 參考 的附錄 A。 -->

          方法

          getInstance

           public static MessageDigest getInstance(String algorithm) throws NoSuchAlgorithmException
          
          生成一個 MessageDigest 對象,它實現指定的摘要算法。 如果缺省的提供者包包含一個實現了該算法 MessageDigest 子類,則返回該子類的一個實例。如果算法在缺省包中是不可用的,將搜索其它的包。

           

          參數:
          algorithm - 申請的算法名。 Java 密碼結構 API 說明書 & 參考 的附錄 A。 -->
          返回值:
          一個實現指定算法的 Message Digest 對象。
          拋出: NoSuchAlgorithmException
          如果算法在調用者環境中是不可用的。

          getInstance

           public static MessageDigest getInstance(String algorithm,
          String provider) throws
          NoSuchAlgorithmException,
          NoSuchProviderException
          
          生成一個 MessageDigest 對象,實現指定的算法,如果提供者的算法是可用的,那么該算法由該提供者提供。

           

          參數:
          algorithm - 申請的算法名。 Java 密碼結構 API 說明書 & 參考 的附錄 A。 -->
          provider - 提供者的名字。
          返回值:
          一個實現指定算法的 Message Digest 對象。
          拋出: NoSuchAlgorithmException
          如果算法在申請的調用者提供的包中是不可用的。
          拋出: NoSuchProviderException
          如果提供者在環境中是不可用的。
          參見:
          Provider

          update

           public void update(byte input)
          
          用指定的字節修改該摘要。

           

          參數:
          input - 用于修改摘要的字節。

          update

           public void update(byte input[],
          int offset,
          int len)
          
          從數組指定的偏移量開始,用指定的字節數組修改摘要。

           

          參數:
          input - 該字節數組。
          offset - 字節數組中開始的偏移量。
          len - 從 offset 開始用的字節數。

          update

           public void update(byte input[])
          
          用指定的字節數組修改該摘要。

           

          參數:
          input - 該字節數組。

          digest

           public byte[] digest()
          
          通過執行最后的諸如填充的操作完成散列碼的計算。 在調用之后復位該摘要。

           

          返回值:
          存放結果散列值的字節數組。

          digest

           public byte[] digest(byte input[])
          
          使用指定的字節數組執行對摘要最后的修改,然后完成摘要計算。 即,這個方法首先對數組調用 update,然后調用 digest()

           

          參數:
          input - 在摘要計算完成之前用于修改的輸入值。
          返回值:
          結果散列值的字節數組。

          toString

           public String toString()
          
          返回該消息摘要對象的字符串表示。

           

          覆蓋:
          Object 中的 toString

          isEqual

           public static boolean isEqual(byte digesta[],
          byte digestb[])
          
          比較兩個摘要是否相同。 進行簡單的比較。

           

          參數:
          digesta - 要比較的一個摘要。
          digestb - 要比較的另一個摘要。
          返回值:
          如果兩個摘要相等則為 true ,否則為 false。

          reset

           public void reset()
          
          為將來的使用復位該摘要。

          一個消息摘要就是一個數據塊的數字指紋。即對一個任意長度的一個數據塊進行計算,產生一個唯一指印(對于SHA1是產生一個20字節的二進制數組)。

          消息摘要有兩個基本屬性:

          兩個不同的報文難以生成相同的摘要
          難以對指定的摘要生成一個報文,而由該報文反推算出該指定的摘要
          代表:美國國家標準技術研究所的SHA1和麻省理工學院Ronald Rivest提出的MD5.

          消息摘要MD5和SHA的使用
          使用方法:

          首先用生成一個MessageDigest類,確定計算方法

          java.security.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1");

          添加要進行計算摘要的信息

          alga.update(myinfo.getBytes());

          計算出摘要

          byte[] digesta=alga.digest();

          發送給其他人你的信息和摘要

          其他人用相同的方法初始化,添加信息,最后進行比較摘要是否相同

          algb.isEqual(digesta,algb.digest())

          相關AIP

          java.security.MessageDigest 類

          static getInstance(String algorithm)

          返回一個MessageDigest對象,它實現指定的算法

          參數:算法名,如 SHA-1 或MD5

          void update (byte input)

          void update (byte[] input)

          void update(byte[] input, int offset, int len)

          添加要進行計算摘要的信息

          byte[] digest()

          完成計算,返回計算得到的摘要(對于MD5是16位,SHA是20位)

          void reset()

          復位

          static boolean isEqual(byte[] digesta, byte[] digestb)

          比效兩個摘要是否相同

          代碼:
          import java.security.*;

          public class myDigest {
          public static void main(String[] args) {

          myDigest my = new myDigest();
          my.testDigest();
          }

          public void testDigest() {
          try {
          String myinfo = "我的測試信息";

          // java.security.MessageDigest
          // alg=java.security.MessageDigest.getInstance("MD5");
          java.security.MessageDigest alga = java.security.MessageDigest
          .getInstance("SHA-1");
          alga.update(myinfo.getBytes());
          byte[] digesta = alga.digest();
          System.out.println("本信息摘要是:" + byte2hex(digesta));
          // 通過某種方式傳給其他人你的信息(myinfo)和摘要(digesta) 對方可以判斷是否更改或傳輸正常
          java.security.MessageDigest algb = java.security.MessageDigest
          .getInstance("SHA-1");
          algb.update(myinfo.getBytes());
          if (algb.isEqual(digesta, algb.digest())) {
          System.out.println("信息檢查正常");
          } else {
          System.out.println("摘要不相同");
          }

          } catch (java.security.NoSuchAlgorithmException ex) {
          System.out.println("非法摘要算法");
          }

          }

          public String byte2hex(byte[] b) // 二行制轉字符串
          {
          String hs = "";
          String stmp = "";
          for (int n = 0; n < b.length; n++) {
          stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
          if (stmp.length() == 1)
          hs = hs + "0" + stmp;
          else
          hs = hs + stmp;
          }

          return hs.toUpperCase();
          }

          }

          b[n] & 0XFF 的作用是將byte轉化為int

          因為0xff是整型, byte[] b; b[index] & 0xff 向大的數據類型靠攏,就是整型了。

          java中的byte sign ,所以 將一個負byte強制轉換成int,就會損壞原來的binary表示,例如:
          byte bb=(byte) 0xf1; //11110001
          printBinary((int)bb);//11111111111111111111111111110001

          printBinary(bb & 0xff);//00000000000000000000000011110001

          運行結果:

          int: -15 binary:

          11111111111111111111111111110001

          int: 241 binary:

          00000000000000000000000011110001

          posted on 2009-01-06 15:55 rogerfan 閱讀(1970) 評論(0)  編輯  收藏 所屬分類: 【Java知識】
          主站蜘蛛池模板: 蒙城县| 衡水市| 铜陵市| 正阳县| 孟津县| 行唐县| 津市市| 北票市| 鸡东县| 尼勒克县| 滨海县| 凌海市| 盘锦市| 苏尼特右旗| 曲麻莱县| 西乡县| 凤冈县| 鲁山县| 七台河市| 大田县| 土默特右旗| 黄骅市| 昌宁县| 广丰县| 额敏县| 汶川县| 泽州县| 古丈县| 兰西县| 万州区| 松桃| 郎溪县| 武功县| 九龙城区| 广南县| 中宁县| 金塔县| 大连市| 黄浦区| 鸡东县| 育儿|