GalaxyPilot —— D.S


                  生命不熄,戰(zhàn)斗不止
          數(shù)據(jù)加載中……

          Java密碼學(xué)

          ( 史帝芬 , idealist@gcn.net.tw)


          1.
          密碼學(xué)簡(jiǎn)介 加密與解密?
          ??? 加密是一個(gè)將欲加密的資料用一些數(shù)學(xué)運(yùn)算轉(zhuǎn)成一團(tuán)令人看不懂的東西的過(guò)程 ; 解密則是將加密文轉(zhuǎn)換回原始文字的過(guò)程。這個(gè)過(guò)程中,扮演原始文字與加密文字之間轉(zhuǎn)換的數(shù)學(xué)算法稱為 Cipher 。

          ??? 現(xiàn)代的 Cipher 多半會(huì)用 Key 來(lái)加密與解密資料。所謂 Key 是指一個(gè)機(jī)密值,我們可將它視為一通行密碼。加密文字必需使用對(duì)映的 Key 才能解密為原始文字。
             A. 對(duì)稱型 Cipher
          對(duì)稱型 Cipher 在傳送端與接收端所用的 Key 是一樣的, 對(duì)稱型 Cipher 又叫 Private Key Cipher ,因?yàn)?/span> Key 的值只有傳送端和接收端知道。如果有第三者知道了 Private Key 值,也就能解開(kāi)加密的資料。

             B. 非對(duì)稱型 Cipher
          非對(duì)稱型的 Cipher 又叫 Public Key Cipher , Cipher 除了 Private Key 外,還會(huì)引進(jìn)一可以隨意散發(fā)的 Public Key 。被 Public Key 加密的資料只有相對(duì)映的 Private Key 可以解開(kāi),同樣的被 Private Key 加密的資料也只有相對(duì)映的 Public Key 可以解開(kāi)。 ?

             C. 訊息摘要 (Message Digest)
          訊息摘要是從一組輸入資料計(jì)算所得的一個(gè)特別數(shù)字,其原理運(yùn)作就如 hash function 一般。在密碼學(xué)的運(yùn)用里,一般是用來(lái)驗(yàn)證資料是否被竄改。

          2. JCE
          下載
          因?yàn)槊绹?guó)法規(guī)的限制, Sun JDK 里只提供了少數(shù)的加密方法,其余大部份則只在 SunJCE 里提供,而且 SunJCE API 限制只有美國(guó)、加拿大地區(qū)可以下載。表 1 Sun SunJCE 分別支持的加密算法。

          ?

          名稱

          型別

          Sun

          MD5

          訊息摘要

          SHA-1

          訊息摘要

          DSA

          簽章

          SunJCE

          HmacMD5

          MAC

          HmacSHA1

          MAC

          DES

          對(duì)稱型 Cipher

          DESede

          非對(duì)稱型 Cipher

          PBEWithMD5AndDES

          對(duì)稱型 Cipher

          DH

          Key 的交換

          1 Sun SunJCE 支持的加密算法

          雖然美國(guó)法規(guī)有這樣的限定,但是在美國(guó)境外也已經(jīng)有廠商實(shí)作出 JCE ,并且可以在網(wǎng)絡(luò)上直接下載,表 2 就是下載網(wǎng)址的列表。

          套件

          網(wǎng)址

          免費(fèi)

          JCE

          http://java.sun.com/products/jdk/1.2/jce/

          Cryptix

          http://www.cryptix.org/

          IAIK

          http://wwwjce.iaik.tu-graz.ac.at/

          2 JCE 軟件下載網(wǎng)址

          3. JCE 安裝

          • 解壓縮到 JDK 目錄下
          • Set ClassPath= C:\JDK\bin\cryptix-jce-api.jar;C:\JDK\bin\cryptix-jce-compat.jar;C:\JDK\bin\cryptix-jce-provider.jar …
          • JDK/lib/security/java.security 中加入
            security.provider.1=sun.security.provider.Sun (
            原來(lái)就有的 )
            security.provider.2=cryptix.jce.provider.Cryptix (
            加入 )


          4.
          程序范例
          在舉例之前,我先完成一個(gè)公用類別,用來(lái)將字符串轉(zhuǎn)成十六進(jìn)制表示法。
          public class Msg {
            public static String toHexString(byte[] b) {
             StringBuffer hexString = new StringBuffer();
             String plainText;

             for (int i = 0; i < b.length; i++) {
              plainText = Integer.toHexString(0xFF & b[i]);
              if (plainText.length() < 2) {
               plainText = "0" + plainText;
              }
              hexString.append(plainText);
             }
             return hexString.toString();
            }
          }

          5.
          訊息摘要 (message digest, SHA1 為例 )
            產(chǎn)生訊息摘要的步驟 :

          • 呼叫 getInstance 取得 MessageDigest 實(shí)體
          • 呼叫 update 將資料喂給 MessageDigest
          • 呼叫 digest 產(chǎn)生訊息摘要


          import java.security.*;

          public class SHA extends Object {
            public static void main(String[] args) throws Exception
            {
             MessageDigest md = MessageDigest.getInstance("SHA");
             md.update(args[0].getBytes());
             byte[] digest = md.digest();
             System.out.println(Msg.toHexString(digest));
            }
          }

          ps.
          比較兩個(gè)訊息摘要是否相同時(shí),可呼叫 isEqual

          6.
          訊息認(rèn)證碼 (MAC, HmacSHA1 為例 )
          訊息認(rèn)證碼只是在產(chǎn)生訊息摘要的過(guò)程里,加進(jìn)一把 key 做為保護(hù),目的是使訊息摘要更難被破解。
            產(chǎn)生訊息認(rèn)證碼的步驟 :

          • 利用密碼產(chǎn)生一把 key
          • 呼叫 getInstance 取得 Mac 實(shí)體
          • 呼叫 init ,初始化 Mac
          • 呼叫 update 喂資料給 Mac
          • 呼叫 doFinal 產(chǎn)生訊息認(rèn)證碼


          import java.security.*;
          import javax.crypto.*;
          import javax.crypto.spec.*;

          public class MacSHA {
            public static void main(String[] args)
            {
             SecureRandom sr = new SecureRandom();
             byte[] keyBytes = new byte[20];
             sr.nextBytes(keyBytes);
             SecretKey key = new SecretKeySpec(keyBytes, "HmacSHA");

             try {
              Mac m = Mac.getInstance("HmacSHA");
              m.init(key);
              m.update(args[0].getBytes());
              byte[] mac = m.doFinal();
              System.out.println(Msg.toHexString(mac));
             }
             catch (Exception e) {
              System.out.println("Exception!!");
             }
            }
          }


          7.
          加密與解密 ( DES 為例 )
          這里舉的加密 / 解密是屬對(duì)稱型 Cipher; 在金融交易里,常用對(duì)稱型 Cipher 來(lái)加 / 解密資料。
            加密 / 解密的步驟 :

          • 利用密碼產(chǎn)生一把 key
          • 呼叫 getInstance 產(chǎn)生一個(gè) Cipher 對(duì)象
          • 呼叫 init 設(shè)定為加密或解密
          • 加密 / 解密


          import java.io.*;
          import java.security.*;
          import javax.crypto.*;

          public class PwdDES {
            public static final int kBufferSize = 8192;

            public static void main(String[] args) throws Exception {
             if (args.length < 4) {
              System.out.println("Usage: java PwdDES -e|-d passwd inputfile outputfile");
              return;
             }

             //Get or create key.

             Key key;

             KeyGenerator generator = KeyGenerator.getInstance("DES");
             generator.init(new SecureRandom(args[1].getBytes()));
             key = generator.generateKey();

             //Get a cipher object
             Cipher cipher = Cipher.getInstance("DES/ECB/PKCS#5");

             //Encrypt or decrypt
             if (args[0].indexOf("e") != -1)
              cipher.init(Cipher.ENCRYPT_MODE, key);
             else
              cipher.init(Cipher.DECRYPT_MODE, key);

             FileInputStream in = new FileInputStream(args[2]);
             FileOutputStream fileOut = new FileOutputStream(args[3]);
             CipherOutputStream out = new CipherOutputStream(fileOut, cipher);
             byte[] buffer = new byte[kBufferSize];
             int length;
             while ((length = in.read(buffer)) != -1)
              out.write(buffer, 0, length);
             in.close();
             out.close();
            }

          }


          8.
          產(chǎn)生簽章與認(rèn)證 ( DSA 為例 )
          數(shù)字簽章常用在網(wǎng)絡(luò)上做個(gè)人身份確認(rèn)。
            產(chǎn)生簽章的步驟 :

          • 呼叫 getInstance 取得一個(gè) Signature 實(shí)體
          • 呼叫 initSign 初始化 Signature
          • 呼叫 sign 產(chǎn)生簽章


            認(rèn)證的步驟 :

          • 呼叫 getInstance 取得一個(gè) Signature 實(shí)體
          • 呼叫 initVerify 初始化 Signature
          • 呼叫 verify 認(rèn)證


          Sample1:
          產(chǎn)生 Private/Public Key

          import java.security.*;
          import java.security.KeyPairGenerator;
          import java.security.KeyPair;
          import java.io.*;

          public class KeyPair1 {

            public static void main(String[] args)
            {
             try {
              KeyPairGenerator genKeyPair = KeyPairGenerator.getInstance("DSA");
              genKeyPair.initialize(1024, new SecureRandom());
              KeyPair kpKey = genKeyPair.genKeyPair();
              PrivateKey prKey = kpKey.getPrivate();
              PublicKey puKey = kpKey.getPublic();

              ObjectOutputStream osPrivate = new ObjectOutputStream(new FileOutputStream("D:\\Private.Key"));
              ObjectOutputStream osPublic = new ObjectOutputStream(new FileOutputStream("D:\\Public.Key"));
              osPrivate.writeObject(prKey);
              osPublic.writeObject(puKey);

              osPrivate.close();
              osPublic.close();
             }
             catch (Exception e) {
              System.out.println("Error");
             }
            }
          }

          Sample2:
          產(chǎn)生簽章與認(rèn)證

          import java.io.*;
          import java.security.*;
          import java.security.Signature;
          import java.security.cert.*;

          public class GenSign {

            public static void main(String[] args) throws Exception {
             String options = args[0];
             String messagefile = args[1];
             String signaturefile = args[2];

             Signature signature = Signature.getInstance("DSA");
             if (options.indexOf("s") != -1) {
              ObjectInputStream is = new ObjectInputStream(new FileInputStream("D:\\Private.key"));
              PrivateKey priKey = (PrivateKey) is.readObject();
              signature.initSign(priKey);
              is.close();
             }
             else {
              ObjectInputStream is = new ObjectInputStream(new FileInputStream("D:\\Public.key"));
              PublicKey pubKey = (PublicKey) is.readObject();
              signature.initVerify(pubKey);
              is.close();
             }

             FileInputStream in = new FileInputStream(messagefile);
             byte[] buffer = new byte[8192];
             int length;
             while ((length = in.read(buffer))!= -1)
              signature.update(buffer, 0, length);
             in.close();

             if (options.indexOf("s") != -1) {
              FileOutputStream out = new FileOutputStream(signaturefile);
              byte[] raw = signature.sign();
              out.write(raw);
              out.close();
             }
             else {
              FileInputStream sigIn = new FileInputStream(signaturefile);
              byte[] raw = new byte[sigIn.available()];
              sigIn.read(raw);
              sigIn.close();
              if (signature.verify(raw))
               System.out.println("The signature is good.");
              else
               System.out.println("The signature is bad.");
             }
            }
          }

          posted on 2006-04-14 09:11 舵手 閱讀(2453) 評(píng)論(0)  編輯  收藏


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 吴忠市| 台北市| 迁西县| 郯城县| 土默特右旗| 新建县| 昭觉县| 云龙县| 托克托县| 孟州市| 沂源县| 招远市| 唐河县| 香港 | 上杭县| 松阳县| 宁国市| 漳浦县| 朝阳区| 汉寿县| 额敏县| 广饶县| 清涧县| 资溪县| 甘洛县| 积石山| 灌云县| 景泰县| 大同市| 东源县| 金秀| 南汇区| 盐津县| 乳源| 宣化县| 合阳县| 香格里拉县| 新平| 教育| 和政县| 察隅县|