JAVA—咖啡館

          ——?dú)g迎訪問(wèn)rogerfan的博客,常來(lái)《JAVA——咖啡館》坐坐,喝杯濃香的咖啡,彼此探討一下JAVA技術(shù),交流工作經(jīng)驗(yàn),分享JAVA帶來(lái)的快樂(lè)!本網(wǎng)站部分轉(zhuǎn)載文章,如果有版權(quán)問(wèn)題請(qǐng)與我聯(lián)系。

          BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
            447 Posts :: 145 Stories :: 368 Comments :: 0 Trackbacks

          Java 加密技術(shù):消息摘要。

          一個(gè)消息摘要就是一個(gè)數(shù)據(jù)塊的數(shù)字指紋。即對(duì)一個(gè)任意長(zhǎng)度的一個(gè)數(shù)據(jù)塊進(jìn)行計(jì)算,產(chǎn)生一個(gè)唯一指印(對(duì)于SHA1是產(chǎn)生一個(gè)20字節(jié)的二進(jìn)制數(shù)組)。

          消息摘要有兩個(gè)基本屬性:

          兩個(gè)不同的報(bào)文難以生成相同的摘要
          難以對(duì)指定的摘要生成一個(gè)報(bào)文,而由該報(bào)文反推算出該指定的摘要
          代表:美國(guó)國(guó)家標(biāo)準(zhǔn)技術(shù)研究所的SHA1和麻省理工學(xué)院Ronald Rivest提出的MD5


          類 java.security.MessageDigest

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

          public abstract class MessageDigest
          extends Object

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

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

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

          MessageDigest 對(duì)象在啟動(dòng)時(shí)被初始化。使用 update 方法處理數(shù)據(jù)。在任何地方都可調(diào)用 reset 復(fù)位摘要。一旦所有需要修改的數(shù)據(jù)都被修改了,將調(diào)用一個(gè) digest 方法完成散列碼的計(jì)算。

          對(duì)于給定次數(shù)的修改,只能調(diào)用 digest 方法一次。在調(diào)用 digest 之后,MessageDigest 對(duì)象被復(fù)位為初始化的狀態(tài)。

          可以自由的實(shí)現(xiàn) Cloneable 接口,這樣做將會(huì)使客戶應(yīng)用在復(fù)制前用 instanceof Cloneable 測(cè)試可復(fù)制性:

           

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

          注意如果給定的實(shí)現(xiàn)是不可復(fù)制的,如果事先知道摘要的數(shù)目,仍然能以幾個(gè)實(shí)例為例計(jì)算中間的摘要。

          構(gòu)造子

          MessageDigest

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

           

          參數(shù):
          algorithm - 摘要算法的標(biāo)準(zhǔn)字符串名。 Java 密碼結(jié)構(gòu) API 說(shuō)明書(shū) & 參考 的附錄 A。 -->

          方法

          getInstance

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

           

          參數(shù):
          algorithm - 申請(qǐng)的算法名。 Java 密碼結(jié)構(gòu) API 說(shuō)明書(shū) & 參考 的附錄 A。 -->
          返回值:
          一個(gè)實(shí)現(xiàn)指定算法的 Message Digest 對(duì)象。
          拋出: NoSuchAlgorithmException
          如果算法在調(diào)用者環(huán)境中是不可用的。

          getInstance

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

           

          參數(shù):
          algorithm - 申請(qǐng)的算法名。 Java 密碼結(jié)構(gòu) API 說(shuō)明書(shū) & 參考 的附錄 A。 -->
          provider - 提供者的名字。
          返回值:
          一個(gè)實(shí)現(xiàn)指定算法的 Message Digest 對(duì)象。
          拋出: NoSuchAlgorithmException
          如果算法在申請(qǐng)的調(diào)用者提供的包中是不可用的。
          拋出: NoSuchProviderException
          如果提供者在環(huán)境中是不可用的。
          參見(jiàn):
          Provider

          update

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

           

          參數(shù):
          input - 用于修改摘要的字節(jié)。

          update

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

           

          參數(shù):
          input - 該字節(jié)數(shù)組。
          offset - 字節(jié)數(shù)組中開(kāi)始的偏移量。
          len - 從 offset 開(kāi)始用的字節(jié)數(shù)。

          update

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

           

          參數(shù):
          input - 該字節(jié)數(shù)組。

          digest

           public byte[] digest()
          
          通過(guò)執(zhí)行最后的諸如填充的操作完成散列碼的計(jì)算。 在調(diào)用之后復(fù)位該摘要。

           

          返回值:
          存放結(jié)果散列值的字節(jié)數(shù)組。

          digest

           public byte[] digest(byte input[])
          
          使用指定的字節(jié)數(shù)組執(zhí)行對(duì)摘要最后的修改,然后完成摘要計(jì)算。 即,這個(gè)方法首先對(duì)數(shù)組調(diào)用 update,然后調(diào)用 digest()

           

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

          toString

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

           

          覆蓋:
          Object 中的 toString

          isEqual

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

           

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

          reset

           public void reset()
          
          為將來(lái)的使用復(fù)位該摘要。

          一個(gè)消息摘要就是一個(gè)數(shù)據(jù)塊的數(shù)字指紋。即對(duì)一個(gè)任意長(zhǎng)度的一個(gè)數(shù)據(jù)塊進(jìn)行計(jì)算,產(chǎn)生一個(gè)唯一指印(對(duì)于SHA1是產(chǎn)生一個(gè)20字節(jié)的二進(jìn)制數(shù)組)。

          消息摘要有兩個(gè)基本屬性:

          兩個(gè)不同的報(bào)文難以生成相同的摘要
          難以對(duì)指定的摘要生成一個(gè)報(bào)文,而由該報(bào)文反推算出該指定的摘要
          代表:美國(guó)國(guó)家標(biāo)準(zhǔn)技術(shù)研究所的SHA1和麻省理工學(xué)院Ronald Rivest提出的MD5.

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

          首先用生成一個(gè)MessageDigest類,確定計(jì)算方法

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

          添加要進(jìn)行計(jì)算摘要的信息

          alga.update(myinfo.getBytes());

          計(jì)算出摘要

          byte[] digesta=alga.digest();

          發(fā)送給其他人你的信息和摘要

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

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

          相關(guān)AIP

          java.security.MessageDigest 類

          static getInstance(String algorithm)

          返回一個(gè)MessageDigest對(duì)象,它實(shí)現(xiàn)指定的算法

          參數(shù):算法名,如 SHA-1 或MD5

          void update (byte input)

          void update (byte[] input)

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

          添加要進(jìn)行計(jì)算摘要的信息

          byte[] digest()

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

          void reset()

          復(fù)位

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

          比效兩個(gè)摘要是否相同

          代碼:
          import java.security.*;

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

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

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

          // 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));
          // 通過(guò)某種方式傳給其他人你的信息(myinfo)和摘要(digesta) 對(duì)方可以判斷是否更改或傳輸正常
          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) // 二行制轉(zhuǎn)字符串
          {
          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轉(zhuǎn)化為int

          因?yàn)?/span>0xff是整型, byte[] b; b[index] & 0xff 向大的數(shù)據(jù)類型靠攏,就是整型了。

          java中的byte sign ,所以 將一個(gè)負(fù)byte強(qiáng)制轉(zhuǎn)換成int,就會(huì)損壞原來(lái)的binary表示,例如:
          byte bb=(byte) 0xf1; //11110001
          printBinary((int)bb);//11111111111111111111111111110001

          printBinary(bb & 0xff);//00000000000000000000000011110001

          運(yùn)行結(jié)果:

          int: -15 binary:

          11111111111111111111111111110001

          int: 241 binary:

          00000000000000000000000011110001

          posted on 2009-01-06 15:55 rogerfan 閱讀(1970) 評(píng)論(0)  編輯  收藏 所屬分類: 【Java知識(shí)】
          主站蜘蛛池模板: 筠连县| 建平县| 华宁县| 长治市| 任丘市| 兴海县| 上栗县| 东乌| 东明县| 昔阳县| 永新县| 潜江市| 台东市| 吐鲁番市| 齐河县| 丹巴县| 夹江县| 兴宁市| 龙门县| 望谟县| 沙坪坝区| 中江县| 高唐县| 石楼县| 行唐县| 泸水县| 信丰县| 曲麻莱县| 始兴县| 九江市| 贵德县| 枞阳县| 顺义区| 将乐县| 富顺县| 安龙县| 沿河| 广西| 苏州市| 郁南县| 安岳县|