java 密碼學

1. 密碼學簡介 – 加密與解密
加密是一個將欲加密的資料用一些數學運算轉成一團令人看不懂的東西的過程; 解密則是將加密文轉換回原始文字的過程。這個過程中,扮演原始文字與加密文字之間轉換的數學演算法稱為Cipher。

圖1 Cipher的運作

現代的Cipher多半會用Key來加密與解密資料。所謂Key是指一個機密值,我們可將它視為一通行密碼。加密文字必需使用對映的Key才能解密為原始文字。
  A. 對稱型Cipher
對稱型Cipher在傳送端與接收端所用的Key是一樣的,如圖2所示,對稱型Cipher又叫Private Key Cipher,因為Key 的值只有傳送端和接收端知道。如果有第三者知道了Private Key值,也就能解開加密的資料。

圖2 對稱型Cipher的運作

  B. 非對稱型Cipher
非對稱型的Cipher又叫Public Key Cipher,Cipher除了Private Key外,還會引進一可以隨意散發的Public Key。被 Public Key加密的資料只有相對映的Private Key可以解開,同樣的被Private Key加密的資料也只有相對映的Public Key 可以解開。如圖3所示,顯示了非對稱型Cipher的運作過程。

圖3 非對稱型Cipher的運作

  C. 訊息摘要 (Message Digest)
訊息摘要是從一組輸入資料計算所得的一個特別數字,其原理運作就如hash function一般。在密碼學的運用裡,一般是用來驗證資料是否被竄改。

2. JCE下載
因為美國法規的限制,Sun在JDK裡只提供了少數的加密方法,其餘大部份則只在SunJCE裡提供,而且SunJCE的 API限制只有美國、加拿大地區可以下載。表1為Sun及SunJCE分別支援的加密演算法。

名稱
型別

Sun
MD5
訊息摘要

SHA-1
訊息摘要

DSA
簽章

SunJCE
HmacMD5
MAC

HmacSHA1
MAC

DES
對稱型Cipher

DESede
非對稱型Cipher

PBEWithMD5AndDES
對稱型Cipher

DH
Key的交換

表1 Sun及SunJCE支援的加密演算法

雖然美國法規有這樣的限定,但是在美國境外也已經有廠商實作出JCE,並且可以在網路上直接下載,表2就是下載網址的列表。
套件
網址
免費

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軟體下載網址

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 (原來就有的)
security.provider.2=cryptix.jce.provider.Cryptix (加入)

4. 程式範例
在舉例之前,我先完成一個公用類別,用來將字串轉成十六進位表示法。
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為例)
  產生訊息摘要的步驟:

呼叫getInstance取得MessageDigest實體
呼叫update將資料餵給MessageDigest
呼叫digest產生訊息摘要

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. 比較兩個訊息摘要是否相同時,可呼叫isEqual。

6. 訊息認證碼 (MAC, 以HmacSHA1為例)
訊息認證碼只是在產生訊息摘要的過程裡,加進一把key做為保護,目的是使訊息摘要更難被破解。
  產生訊息認證碼的步驟:

利用密碼產生一把key
呼叫getInstance取得Mac實體
呼叫init,初始化Mac
呼叫update餵資料給Mac
呼叫doFinal產生訊息認證碼

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為例)
這裡舉的加密/解密是屬對稱型Cipher; 在金融交易裡,常用對稱型Cipher來加/解密資料。
  加密/解密的步驟:

利用密碼產生一把key
呼叫getInstance產生一個Cipher物件
呼叫init設定為加密或解密
加密/解密

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: Cloak -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. 產生簽章與認證 (以DSA為例)
數位簽章常用在網路上做個人身份確認。
  產生簽章的步驟:

呼叫getInstance取得一個Signature實體
呼叫initSign初始化Signature
呼叫sign產生簽章

  認證的步驟:

呼叫getInstance取得一個Signature實體
呼叫initVerify初始化Signature
呼叫verify認證

Sample1: 產生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: 產生簽章與認證

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

时间: 2024-09-11 06:49:41

java 密碼學的相关文章

透過 ASP 修改 NT 使用者密碼

使用者登入機制在未來的網頁開發會顯得越來越重要, 很簡單的道理, 因為現在的網站很著急的要做好會員管理, 然後向會員收錢, 其實這是很正常的代誌, 台灣的公司法說的很清楚嘛, 『公司以營利為目的』 在 IIS 5.0 的安全性身分驗證機制中, 整合的 Windows 驗證 (在 IIS 4.0 號做 Windows NT 挑戰與回應) 是一個不歹的選擇, 很簡單的一個方法就可以達到一定水準的安全性, 而且可以整合 Windows 2000 的使用者, 不過有一好無兩好, 缺點是沒有一個很好的線上

加密處理使密碼更安全[CFS編碼加密]

安全|加密 你是怎麼把密碼儲存到資料庫裡?是以純文字的方式?你可知道這對安全的危險性?當攻擊你網站的人能開啟資料庫瀏覽,以純文字方式存在資料庫裡的密碼一覽無疑,基於安全上的考量,你想這樣適當嗎?有什麼辦法能夠讓別人看到資料庫裡的資料,也沒辦法知道儲存在其中的密碼? 以上問題你是否知道如何解決?本文要告訴你,如何將你的密碼做加密處理,處理過後的密碼字串,就算是公開出來也沒人猜得到原來的密碼!首先我們來看看一組字串: 27B827277C70E88DD87E3057BFBE8F 這是將密碼加密後的結

加密處理使密碼更安全

安全|加密 你是怎麼把密碼儲存到資料庫裡?是以純文字的方式?你可知道這對安全的危險性?當攻擊你網站的人能開啟資料庫瀏覽,以純文字方式存在資料庫裡的密碼一覽無疑,基於安全上的考量,你想這樣適當嗎?有什麼辦法能夠讓別人看到資料庫裡的資料,也沒辦法知道儲存在其中的密碼? 以上問題你是否知道如何解決?本文要告訴你,如何將你的密碼做加密處理,處理過後的密碼字串,就算是公開出來也沒人猜得到原來的密碼!首先我們來看看一組字串: 27B827277C70E88DD87E3057BFBE8F 這是將密碼加密後的結

75 套頂尖的開放源碼安全防禦應用 – Part I

原文地址: http://nicaliu.info/2010/04/14/2841/   譯者:Nica < nicaliu at gmail dot com > . 建議參考:26 套提供付費技術支援的開放源碼安全防禦應用 與 2008:75 套頂尖開放源碼安全防禦應用 . FBI 指出,2009 年電腦犯罪率成長了 20%.造成 5億5仟9百萬的損失,遠超過過去兩年的總合. 隨著線上犯罪日益增長,系統防護的任務也就更加重要了.其實你不需要在安全性防護上花太多錢:開放源碼社群不斷製造與持續維

学习JAVA的第一方案 (转贴)

发信人: linuxandjava (linuxANDjava), 信区: Java 标  题: 學習JAVA的第一方案 发信站: 网易虚拟社区北京站 (Thu Apr 20 09:59:51 2000), 站内信件 國內雖然商品化的JAVA作品不多,但是學習JAVA的人數卻扶搖直上. 為了幫助更多的人能夠少走彎路,花最少的錢,用最少的時間, 最大限度的掌握Java, 本人提出如下方案,供初學者參考: 1. 第一階段; 入門    這個時候,最主要的任務是對Java有一個大致的了解,掌握基本的語

JAVA国际化DEMO

目录结构: 所有的文件都在包demo下. MlLogin.java package demo; import java.util.ListResourceBundle; public class MlLogin extends ListResourceBundle { public MlLogin() { } static final java.lang.Object[][] contents = { { "lblUserName", "lblUserName" }

菜鳥關於JAVA開發模式問題請教

问题描述 背景:因為最近公司要求,未來部分專案轉向JAVA開發,脫離微軟,盡量使用開源東西,降低成本(公司是製造業集團,開發的軟件也都是公司內部使用),而之前公司幾個事業部都是使用(.NET + Oracle)現在集體在學習JAVA開發,而技術是由總公司決定的,使用ZK框架開發,目前在學習過程中,自己感覺到一些疑問,平時都會來論壇,知道大神非常多,所以在這裡開個帖子請教.首先我的.NET開發模式歷程:03-04年:asp 05-06年:asp.net (使用.net服務器控件開發,感覺很像現在學

Oracle9i 資料庫管理實務講座(一)

oracle Oracle 9i 資料庫管理實務講座(一)如何安裝Oracle 9i Enterprise Edition for Linux 原文出處 : 2001年11月Linuxer雜誌作者: 何致億下載 PDF 檔 前言 Oracle 9i資料庫系統可算是近幾年來Oracle公司一項殺手級的產品,其功能與應用面之廣,連研究Oracle多年的我在第一次接觸到產品規格時也不禁嚇了一跳!突然間一大堆的技術文件與白皮書排山倒海而來,一時之間還不知道該從何著手.所以我花了幾個月的時間在各種平台上進

數据庫加密与解密技術之一 FOXPRO篇

加密|解密      數据庫加密与解密技術之一 FOXPRO篇作者:  CCBZZP       在現實的應用中, 數据的安全是很重要的, 特別是象銀行等保密性非常重要的部門,所以對數据的加密就特別重要, 筆者在長期的應用中總結出各种數据庫的加密和解密的寫法, 希望對大家有幫助, 同時也和大家一起探討, 一起學習, 共同進步!       FOXPRO為用戶提供一些低級的文件操作函數,利用這些低級的操作函數用戶可以實現對低級文件的操作,這些低級的函數主要有: FCLOSE(),FCREATE()