import java.util.*;
import java.io.*;java
public class SortAlgorithm
{
static Random rand = new Random();node
void bubbleSort(int[] numlist) // 冒泡排序算法
{
int temp;
for(int j=1;j<numlist.length;j++)
for(int i=0;i<numlist.length-j;i++)
if(numlist>numlist[i+1])
{
temp = numlist[i+1];
numlist[i+1] = numlist;
numlist = temp;
}
}算法
void selectionSort (int[] numlist) //選擇排序算法
{
int temp;
for(int i=0;i<numlist.length-1;i++)
for(int j=i+1;j<numlist.length;j++)
if(numlist>numlist[j])
{
temp = numlist[j];
numlist[j] = numlist;
numlist = temp;數組
}
}安全
void insertSort (int[] numlist) //插入排序算法
{
int temp,in,out;
for(out=1;out<numlist.length;out++)
{
temp=numlist[out];
in=out;
while(in>0 && numlist[in-1]>=temp)
{
numlist[in]=numlist[in-1];
--in;
}
numlist[in]=temp;
}網絡
}數據結構
void display (int[] num) // 打印出排序結果
{
for(int i = 0;i<num.length;i++)
System.out.print(num+" ");
System.out.println("");併發
}dom
static int pRand(int mod) // 生成隨即數組
{
return Math.abs(rand.nextInt())%mod;
}
public static void main(String args[])throws IOException
{
SortAlgorithm sortAlgorithm = new SortAlgorithm();
int[] numList = new int[10];
for(int i = 0;i<numList.length;i++)
numList = pRand(100); //調用pRand方法,把隨即生成的數據輸入到
// 數組中
System.out.println("隨即生成的數組是:");
// 打印出原數組,
for(int j =0;j<numList.length;j++)
System.out.print(numList[j]+" ");
System.out.println("");
long begin = System.currentTimeMillis(); //排序開始時間,調用系統的當前時間
sortAlgorithm.bubbleSort(numList); //執行冒泡排序
long end = System.currentTimeMillis(); //排序結束時間,調用系統當前時間
System.out.println("冒泡排序用時爲:" + (end-begin)); //排序用時
System.out.println("排序後的數組爲:");
sortAlgorithm.display(numList);
begin = System.currentTimeMillis();
sortAlgorithm.selectionSort(numList);
end = System.currentTimeMillis();
System.out.println("選擇排序用時爲:" +(end-begin));
System.out.println("排序後的數組爲:");
sortAlgorithm.display(numList);
begin = System.currentTimeMillis();
sortAlgorithm.insertSort(numList);
end = System.currentTimeMillis();
System.out.println("插入排序用時爲:" + (end-begin));
System.out.println("排序後的數組爲:");
sortAlgorithm.display(numList);
}
}
題目以下:用一、二、二、三、四、5這六個數字,用java寫一個main函數,打印出全部不一樣的排列,如:51223四、412345等,要求:"4"不能在第三位,"3"與"5"不能相連。
static int[] bits = new int[] { 1, 2, 3, 4, 5 };
/**
* @param args
*/
public static void main(String[] args) {
sort("", bits);
}
private static void sort(String prefix, int[] a) {
if (a.length == 1) {
System.out.println(prefix + a[0]);
}
for (int i = 0; i < a.length; i++) {
sort(prefix + a, copy(a, i));
}
}
private static int[] copy(int[] a,int index){
int[] b = new int[a.length-1];
System.arraycopy(a, 0, b, 0, index);
System.arraycopy(a, index+1, b, index, a.length-index-1);
return b;
}
**********************************************************************
基本思路:
1 把問題歸結爲圖結構的遍歷問題。實際上6個數字就是六個結點,把六個結點鏈接成無向連通圖,對於每個結點求這個圖形的遍歷路徑,全部結點的遍歷路徑就是最後對這6個數字的排列組合結果集。
2 顯然這個結果集還未達到題目的要求。從如下幾個方面考慮:
1. 3,5不能相連:實際要求這個連通圖的結點3,5之間不能連通, 可在構造圖結構時就知足改條件,而後再遍歷圖。
2. 不能有重複: 考慮到有兩個2,明顯會存在重複結果,能夠把結果集放在TreeSet中過濾重複結果
3. 4不能在第三位: 仍舊在結果集中去除知足此條件的結果。
採用二維數組定義圖結構,最後的代碼是:
import java.util.Iterator;
import java.util.TreeSet;
public class TestQuestion {
private String[] b = new String[]{"1", "2", "2", "3", "4", "5"};
private int n = b.length;
private boolean[] visited = new boolean[n];
private int[][] a = new int[n][n];
private String result = "";
private TreeSet set = new TreeSet();
public static void main(String[] args) {
new TestQuestion().start();
}
private void start() {
// Initial the map a[][]
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) {
a[j] = 0;
} else {
a[j] = 1;
}
}
}
// 3 and 5 can not be the neighbor.
a[3][5] = 0;
a[5][3] = 0;
// Begin to depth search.
for (int i = 0; i < n; i++) {
this.depthFirstSearch(i);
}
// Print result treeset.
Iterator it = set.iterator();
while (it.hasNext()) {
String string = (String) it.next();
// "4" can not be the third position.
if (string.indexOf("4") != 2) {
System.out.println(string);
}
}
}
private void depthFirstSearch(int startIndex) {
visited[startIndex] = true;
result = result + b[startIndex];
if (result.length() == n) {
// Filt the duplicate value.
set.add(result);
}
for(int j = 0; j < n; j++) {
if (a[startIndex][j] == 1 && visited[j] == false) {
depthFirstSearch(j);
} else {
continue;
}
}
// restore the result value and visited value after listing a node.
result = result.substring(0, result.length() -1);
visited[startIndex] = false;
}
}
1.寫一個方法,用一個for循環打印九九乘法表
Java code
/**
* 打印九九乘法口訣表
*/
public
void nineNineMulitTable(){
for (int i =
1,j =
1; j <=
9; i++) {
System.out.print(i+"*"+j+"="+i*j+"
");
if(i==j){
i=0;
j++;
System.out.println();
}
}
}
2.給定一個java.util.Date對象,如何轉化爲」2007-3-22 20:23:22」格式的字符串
Java code
/**
* 將某個日期以固定格式轉化成字符串
* @param date
* @return str
*/
public String date2FormatStr(Date date)
{
SimpleDateFormat sdf =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str = sdf.format(date);
return str;
}
3.寫一個方法,可以判斷任意一個整數是否素數
/**
* 判斷任意一個整數是否素數
* @param num
* @return boolean
*/
public boolean isPrimeNumber(int num)
{
for (int i = 2; i <= Math.sqrt(num); i++) {
if(num%i==0)
{
return false;
}
}
return true;
}
4.寫一個方法,輸入任意一個整數,返回它的階乘
Java code
/**
*得到任意一個整數的階乘
*@param n
*@returnn!
*/
public int factorial(int num)
{
//遞歸
if(num == 1)
{
return 1;
}
return num*factorial(num-1);
}
5.寫一個方法,用二分查找法判斷任意整數在任意整數數組裏面是否存在,若存在就返回它在數組中的索引位置,不存在返回-1
Java code
/**
*二分查找特定整數在整型數組中的位置(遞歸)
*@param dataset
*@param data
*@param beginIndex
*@param endIndex
*@return index
*/
public int binarySearch(int[] dataset,int data,int beginIndex,int endIndex){
int midIndex = (beginIndex+endIndex)/2;
//若是查找的數要比開始索引的數據要小或者是比結束索引的書要大,或者開始查找的索引值大於結束的索引值返回-1沒有查到
if(data <dataset[beginIndex]||data>dataset[endIndex]||beginIndex>endIndex){
return -1;
}
if(data <dataset[midIndex]){
return binarySearch(dataset,data,beginIndex,midIndex-1);
}else if(data>dataset[midIndex])
{
return binarySearch(dataset,data,midIndex+1,endIndex);
}else {
return midIndex;
}
}
/**
*二分查找特定整數在整型數組中的位置(非遞歸)
*@param dataset
*@param data
*@return index
*/
public int binarySearch(int[] dataset ,int data)
{
int beginIndex = 0;
int endIndex = dataset.length - 1;
int midIndex = -1;
if(data <dataset[beginIndex]||data>dataset[endIndex]||beginIndex>endIndex){
return -1;
}
while(beginIndex <= endIndex) {
midIndex = (beginIndex+endIndex)/2;
if(data <dataset[midIndex]) {
endIndex = midIndex-1;
} else if(data>dataset[midIndex]) {
beginIndex = midIndex+1;
}else {
return midIndex;
}
}
return -1;
}
JAVA上加密算法的實現用例
常,使用的加密算法 比較簡便高效,密鑰簡短,加解密速度快,破譯極其困難。本文介紹了 MD5/SHA1,DSA,DESede/DES,Diffie-Hellman的使用。
第1章基礎知識
1.1. 單鑰密碼體制
單鑰密碼體制是一種傳統的加密算法,是指信息的發送方和接收方共同使用同一把密鑰進行加解密。
一般,使用的加密算法比較簡便高效,密鑰簡短,加解密速度快,破譯極其困難。可是加密的安全性依靠密鑰保管的安全性,在公開的計算機網絡上安全地傳送和保管密鑰是一個嚴峻的問題,而且若是在多用戶的狀況下密鑰的保管安全性也是一個問題。
單鑰密碼體制的表明是美國的DES
1.2. 消息摘要
一個消息摘要就是一個數據塊的數字指紋。即對一個任意長度的一個數據塊進行計算,產生一個惟一指印(對於SHA1是產生一個20字節的二進制數組)。
消息摘要有兩個基本屬性:
兩個不一樣的報文難以生成相同的摘要
難以對指定的摘要生成一個報文,而由該報文反推算出該指定的摘要
表明:美國國家標準技術研究所的SHA1和麻省理工學院Ronald Rivest提出的MD5
1.3. Diffie-Hellman密鑰一致協議
密鑰一致協議是由公開密鑰密碼體制的奠定人Diffie和Hellman所提出的一種思想。
先決條件,容許兩名用戶在公開媒體上交換信息以生成"一致"的,能夠共享的密鑰
表明:指數密鑰一致協議(Exponential Key Agreement Protocol)
1.4. 非對稱算法與公鑰體系
1976年,Dittie和Hellman爲解決密鑰管理問題,在他們的奠定性的工做"密碼學的新方向"一文中,提出一種密鑰交換協議,容許在不安全的媒體上經過通信雙方交換信息,安全地傳送祕密密鑰。在此新思想的基礎上,很快出現了非對稱密鑰密碼體制,即公鑰密碼體制。在公鑰體制中,加密密鑰不一樣於解密密鑰,加密密鑰公之於衆,誰均可以使用;解密密鑰只有解密人本身知道。它們分別稱爲公開密鑰(Public key)和祕密密鑰(Private key)。
迄今爲止的全部公鑰密碼體系中,RSA系統是最著名、最多使用的一種。RSA公開密鑰密碼系統是由R.Rivest、A.Shamir和L.Adleman俊教授於1977年提出的。RSA的取名就是來自於這三位發明者的姓的第一個字母
1.5. 數字簽名
所謂數字簽名就是信息發送者用其私鑰對從所傳報文中提取出的特徵數據(或稱數字指紋)進行RSA算法操做,以保證發信人沒法抵賴曾發過該信息(即不可抵賴性),同時也確保信息報文在經簽名後末被篡改(即完整性)。當信息接收者收到報文後,就能夠用發送者的公鑰對數字簽名進行驗證。
在數字簽名中有重要做用的數字指紋是經過一類特殊的散列函數(HASH函數)生成的,對這些HASH函數的特殊要求是:
接受的輸入報文數據沒有長度限制;
對任何輸入報文數據生成固定長度的摘要(數字指紋)輸出
從報文能方便地算出摘要;
難以對指定的摘要生成一個報文,而由該報文反推算出該指定的摘要;
兩個不一樣的報文難以生成相同的摘要
表明:DSA
回頁首
第2章在JAVA中的實現
2.1. 相關
Diffie-Hellman密鑰一致協議和DES程序須要JCE工具庫的支持,能夠到 http://java.sun.com/security/index.html 下載JCE,並進行安裝。簡易安裝把 jce1.2.1/lib 下的全部內容複製到 %java_home%/lib/ext下,若是沒有ext目錄自行創建,再把jce1_2_1.jar和sunjce_provider.jar添加到CLASSPATH內,更詳細說明請看相應用戶手冊
2.2. 消息摘要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;
if (n<b.length-1) hs=hs+":";
}
return hs.toUpperCase();
}
}
2.3. 數字簽名DSA
對於一個用戶來說首先要生成他的密鑰對,而且分別保存
生成一個KeyPairGenerator實例
java.security.KeyPairGenerator keygen=java.security.KeyPairGenerator.getInstance("DSA");
若是設定隨機產生器就用如相代碼初始化
SecureRandom secrand=new SecureRandom();
secrand.setSeed("tttt".getBytes()); //初始化隨機產生器
keygen.initialize(512,secrand); //初始化密鑰生成器
不然
keygen.initialize(512);
生成密鑰公鑰pubkey和私鑰prikey
KeyPair keys=keygen.generateKeyPair(); //生成密鑰組
PublicKey pubkey=keys.getPublic();
PrivateKey prikey=keys.getPrivate();
分別保存在myprikey.dat和mypubkey.dat中,以便下次不在生成
(生成密鑰對的時間比較長
java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat"));
out.writeObject(prikey);
out.close();
out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat"));
out.writeObject(pubkey);
out.close();
用他私人密鑰(prikey)對他所確認的信息(info)進行數字簽名產生一個簽名數組
從文件中讀入私人密鑰(prikey)
java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat"));
PrivateKey myprikey=(PrivateKey)in.readObject();
in.close();
初始一個Signature對象,並用私鑰對信息簽名
java.security.Signature signet=java.security.Signature.getInstance("DSA");
signet.initSign(myprikey);
signet.update(myinfo.getBytes());
byte[] signed=signet.sign();
把信息和簽名保存在一個文件中(myinfo.dat)
java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat"));
out.writeObject(myinfo);
out.writeObject(signed);
out.close();
把他的公鑰的信息及簽名發給其它用戶
其餘用戶用他的公共密鑰(pubkey)和簽名(signed)和信息(info)進行驗證是否由他簽名的信息
讀入公鑰
java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat"));
PublicKey pubkey=(PublicKey)in.readObject();
in.close();
讀入簽名和信息
in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat"));
String info=(String)in.readObject();
byte[] signed=(byte[])in.readObject();
in.close();
初始一個Signature對象,並用公鑰和簽名進行驗證
java.security.Signature signetcheck=java.security.Signature.getInstance("DSA");
signetcheck.initVerify(pubkey);
signetcheck.update(info.getBytes());
if (signetcheck.verify(signed)) { System.out.println("簽名正常");}
對於密鑰的保存本文是用對象流的方式保存和傳送的,也可能夠用編碼的方式保存.注意要
import java.security.spec.*
import java.security.*
具休說明以下
public key是用X.509編碼的,例碼以下: byte[] bobEncodedPubKey=mypublic.getEncoded(); //生成編碼
//傳送二進制編碼
//如下代碼轉換編碼爲相應key對象
X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey);
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec);
對於Private key是用PKCS#8編碼,例碼以下: byte[] bPKCS=myprikey.getEncoded();
//傳送二進制編碼
//如下代碼轉換編碼爲相應key對象
PKCS8EncodedKeySpec priPKCS8=new PKCS8EncodedKeySpec(bPKCS);
KeyFactory keyf=KeyFactory.getInstance("DSA");
PrivateKey otherprikey=keyf.generatePrivate(priPKCS8);
經常使用API
java.security.KeyPairGenerator 密鑰生成器類
public static KeyPairGenerator getInstance(String algorithm) throws NoSuchAlgorithmException
以指定的算法返回一個KeyPairGenerator 對象
參數: algorithm 算法名.如:"DSA","RSA"
public void initialize(int keysize)
以指定的長度初始化KeyPairGenerator對象,若是沒有初始化系統以1024長度默認設置
參數:keysize 算法位長.其範圍必須在 512 到 1024 之間,且必須爲 64 的倍數
public void initialize(int keysize, SecureRandom random)
以指定的長度初始化和隨機發生器初始化KeyPairGenerator對象
參數:keysize 算法位長.其範圍必須在 512 到 1024 之間,且必須爲 64 的倍數
random 一個隨機位的來源(對於initialize(int keysize)使用了默認隨機器
public abstract KeyPair generateKeyPair()
產生新密鑰對
java.security.KeyPair 密鑰對類
public PrivateKey getPrivate()
返回私鑰
public PublicKey getPublic()
返回公鑰
java.security.Signature 簽名類
public static Signature getInstance(String algorithm) throws NoSuchAlgorithmException
返回一個指定算法的Signature對象
參數 algorithm 如:"DSA"
public final void initSign(PrivateKey privateKey)
throws InvalidKeyException
用指定的私鑰初始化
參數:privateKey 所進行簽名時用的私鑰
public final void update(byte data)
throws SignatureException
public final void update(byte[] data)
throws SignatureException
public final void update(byte[] data, int off, int len)
throws SignatureException
添加要簽名的信息
public final byte[] sign()
throws SignatureException
返回簽名的數組,前提是initSign和update
public final void initVerify(PublicKey publicKey)
throws InvalidKeyException
用指定的公鑰初始化
參數:publicKey 驗證時用的公鑰
public final boolean verify(byte[] signature)
throws SignatureException
驗證簽名是否有效,前提是已經initVerify初始化
參數: signature 簽名數組
*/
import java.security.*;
import java.security.spec.*;
public class testdsa {
public static void main(String[] args) throws java.security.NoSuchAlgorithmException,java.lang.Exception {
testdsa my=new testdsa();
my.run();
}
public void run()
{
//數字簽名生成密鑰
//第一步生成密鑰對,若是已經生成過,本過程就能夠跳過,對用戶來說myprikey.dat要保存在本地
//而mypubkey.dat給發佈給其它用戶
if ((new java.io.File("myprikey.dat")).exists()==false) {
if (generatekey()==false) {
System.out.println("生成密鑰對敗");
return;
};
}
//第二步,此用戶
//從文件中讀入私鑰,對一個字符串進行簽名後保存在一個文件(myinfo.dat)中
//而且再把myinfo.dat發送出去
//爲了方便數字簽名也放進了myifno.dat文件中,固然也可分別發送
try {
java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat"));
PrivateKey myprikey=(PrivateKey)in.readObject();
in.close();
// java.security.spec.X509EncodedKeySpec pubX509=new java.security.spec.X509EncodedKeySpec(bX509);
//java.security.spec.X509EncodedKeySpec pubkeyEncode=java.security.spec.X509EncodedKeySpec
String myinfo="這是個人信息"; //要簽名的信息
//用私鑰對信息生成數字簽名
java.security.Signature signet=java.security.Signature.getInstance("DSA");
signet.initSign(myprikey);
signet.update(myinfo.getBytes());
byte[] signed=signet.sign(); //對信息的數字簽名
System.out.println("signed(簽名內容)="+byte2hex(signed));
//把信息和數字簽名保存在一個文件中
java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat"));
out.writeObject(myinfo);
out.writeObject(signed);
out.close();
System.out.println("簽名並生成文件成功");
}
catch (java.lang.Exception e) {
e.printStackTrace();
System.out.println("簽名並生成文件失敗");
};
//第三步
//其餘人經過公共方式獲得此戶的公鑰和文件
//其餘人用此戶的公鑰,對文件進行檢查,若是成功說明是此用戶發佈的信息.
//
try {
java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat"));
PublicKey pubkey=(PublicKey)in.readObject();
in.close();
System.out.println(pubkey.getFormat());
in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat"));
String info=(String)in.readObject();
byte[] signed=(byte[])in.readObject();
in.close();
java.security.Signature signetcheck=java.security.Signature.getInstance("DSA");
signetcheck.initVerify(pubkey);
signetcheck.update(info.getBytes());
if (signetcheck.verify(signed)) {
System.out.println("info="+info);
System.out.println("簽名正常");
}
else System.out.println("非簽名正常");
}
catch (java.lang.Exception e) {e.printStackTrace();};
}
//生成一對文件myprikey.dat和mypubkey.dat---私鑰和公鑰,
//公鑰要用戶發送(文件,網絡等方法)給其它用戶,私鑰保存在本地
public boolean generatekey()
{
try {
java.security.KeyPairGenerator keygen=java.security.KeyPairGenerator.getInstance("DSA");
// SecureRandom secrand=new SecureRandom();
// secrand.setSeed("tttt".getBytes()); //初始化隨機產生器
// keygen.initialize(576,secrand); //初始化密鑰生成器
keygen.initialize(512);
KeyPair keys=keygen.genKeyPair();
// KeyPair keys=keygen.generateKeyPair(); //生成密鑰組
PublicKey pubkey=keys.getPublic();
PrivateKey prikey=keys.getPrivate();
java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat"));
out.writeObject(prikey);
out.close();
System.out.println("寫入對象 prikeys ok");
out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat"));
out.writeObject(pubkey);
out.close();
System.out.println("寫入對象 pubkeys ok");
System.out.println("生成密鑰對成功");
return true;
}
catch (java.lang.Exception e) {
e.printStackTrace();
System.out.println("生成密鑰對失敗");
return false;
};
}
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;
if (n<b.length-1) hs=hs+":";
}
return hs.toUpperCase();
}
}
2.4. DESede/DES對稱算法
首先生成密鑰,並保存(這裏並沒的保存的代碼,可參考DSA中的方法)
KeyGenerator keygen = KeyGenerator.getInstance(Algorithm);
SecretKey deskey = keygen.generateKey();
用密鑰加密明文(myinfo),生成密文(cipherByte)
Cipher c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.ENCRYPT_MODE,deskey);
byte[] cipherByte=c1.doFinal(myinfo.getBytes());
傳送密文和密鑰,本文沒有相應代碼可參考DSA
.............
用密鑰解密密文
c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.DECRYPT_MODE,deskey);
byte[] clearByte=c1.doFinal(cipherByte);
相對來講對稱密鑰的使用是很簡單的,對於JCE來說支技DES,DESede,Blowfish三種加密術
對於密鑰的保存各傳送可以使用對象流或者用二進制編碼,相關參考代碼以下
SecretKey deskey = keygen.generateKey();
byte[] desEncode=deskey.getEncoded();
javax.crypto.spec.SecretKeySpec destmp=new javax.crypto.spec.SecretKeySpec(desEncode,Algorithm);
SecretKey mydeskey=destmp;
相關API
KeyGenerator 在DSA中已經說明,在添加JCE後在instance進能夠以下參數
DES,DESede,Blowfish,HmacMD5,HmacSHA1
javax.crypto.Cipher 加/解密器
public static final Cipher getInstance(java.lang.String transformation)
throws java.security.NoSuchAlgorithmException,
NoSuchPaddingException
返回一個指定方法的Cipher對象
參數:transformation 方法名(可用 DES,DESede,Blowfish)
public final void init(int opmode, java.security.Key key)
throws java.security.InvalidKeyException
用指定的密鑰和模式初始化Cipher對象
參數:opmode 方式(ENCRYPT_MODE, DECRYPT_MODE, WRAP_MODE,UNWRAP_MODE)
key 密鑰
public final byte[] doFinal(byte[] input)
throws java.lang.IllegalStateException,
IllegalBlockSizeException,
BadPaddingException
對input內的串,進行編碼處理,返回處理後二進制串,是返回解密文仍是加解文由init時的opmode決定
注意:本方法的執行前若是有update,是對updat和本次input所有處理,不然是本inout的內容
/*
安全程序 DESede/DES測試
*/
import java.security.*;
import javax.crypto.*;
public class testdes {
public static void main(String[] args){
testdes my=new testdes();
my.run();
}
public void run() {
//添加新安全算法,若是用JCE就要把它添加進去
Security.addProvider(new com.sun.crypto.provider.SunJCE());
String Algorithm="DES"; //定義 加密算法,可用 DES,DESede,Blowfish
String myinfo="要加密的信息";
try {
//生成密鑰
KeyGenerator keygen = KeyGenerator.getInstance(Algorithm);
SecretKey deskey = keygen.generateKey();
//加密
System.out.println("加密前的二進串:"+byte2hex(myinfo.getBytes()));
System.out.println("加密前的信息:"+myinfo);
Cipher c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.ENCRYPT_MODE,deskey);
byte[] cipherByte=c1.doFinal(myinfo.getBytes());
System.out.println("加密後的二進串:"+byte2hex(cipherByte));
//解密
c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.DECRYPT_MODE,deskey);
byte[] clearByte=c1.doFinal(cipherByte);
System.out.println("解密後的二進串:"+byte2hex(clearByte));
System.out.println("解密後的信息:"+(new String(clearByte)));
}
catch (java.security.NoSuchAlgorithmException e1) {e1.printStackTrace();}
catch (javax.crypto.NoSuchPaddingException e2) {e2.printStackTrace();}
catch (java.lang.Exception e3) {e3.printStackTrace();}
}
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;
if (n<b.length-1) hs=hs+":";
}
return hs.toUpperCase();
}
}
2.5. Diffie-Hellman密鑰一致協議
公開密鑰密碼體制的奠定人Diffie和Hellman所提出的 "指數密鑰一致協議"(Exponential Key Agreement Protocol),該協議不要求別的安全性先決條件,容許兩名用戶在公開媒體上交換信息以生成"一致"的,能夠共享的密鑰。在JCE的中實現用戶alice生成DH類型的密鑰對,若是長度用1024生成的時間請,推薦第一次生成後保存DHParameterSpec,以便下次使用直接初始化.使其速度加快
System.out.println("ALICE: 產生 DH 對 ...");
KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH");
aliceKpairGen.initialize(512);
KeyPair aliceKpair = aliceKpairGen.generateKeyPair();
alice生成公鑰發送組bob
byte[] alicePubKeyEnc = aliceKpair.getPublic().getEncoded();
bob從alice發送來的公鑰中讀出DH密鑰對的初始參數生成bob的DH密鑰對
注意這一步必定要作,要保證每一個用戶用相同的初始參數生成的
DHParameterSpec dhParamSpec = ((DHPublicKey)alicePubKey).getParams();
KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH");
bobKpairGen.initialize(dhParamSpec);
KeyPair bobKpair = bobKpairGen.generateKeyPair();
bob根據alice的公鑰生成本地的DES密鑰
KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");
bobKeyAgree.init(bobKpair.getPrivate());
bobKeyAgree.doPhase(alicePubKey, true);
SecretKey bobDesKey = bobKeyAgree.generateSecret("DES");
bob已經生成了他的DES密鑰,他現把他的公鑰發給alice,
byte[] bobPubKeyEnc = bobKpair.getPublic().getEncoded();
alice根據bob的公鑰生成本地的DES密鑰
,,,,,,解碼
KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH");
aliceKeyAgree.init(aliceKpair.getPrivate());
aliceKeyAgree.doPhase(bobPubKey, true);
SecretKey aliceDesKey = aliceKeyAgree.generateSecret("DES");
bob和alice能過這個過程就生成了相同的DES密鑰,在這種基礎就可進行安全能信
經常使用API
java.security.KeyPairGenerator 密鑰生成器類
public static KeyPairGenerator getInstance(String algorithm)
throws NoSuchAlgorithmException
以指定的算法返回一個KeyPairGenerator 對象
參數: algorithm 算法名.如:原來是DSA,如今添加了 DiffieHellman(DH)
public void initialize(int keysize)
以指定的長度初始化KeyPairGenerator對象,若是沒有初始化系統以1024長度默認設置
參數:keysize 算法位長.其範圍必須在 512 到 1024 之間,且必須爲 64 的倍數
注意:若是用1024生長的時間很長,最好生成一次後就保存,下次就不用生成了
public void initialize(AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException
以指定參數初始化
javax.crypto.interfaces.DHPublicKey
public DHParameterSpec getParams()
返回
java.security.KeyFactory
public static KeyFactory getInstance(String algorithm)
throws NoSuchAlgorithmException
以指定的算法返回一個KeyFactory
參數: algorithm 算法名:DSH,DH
public final PublicKey generatePublic(KeySpec keySpec)
throws InvalidKeySpecException
根據指定的key說明,返回一個PublicKey對象
java.security.spec.X509EncodedKeySpec
public X509EncodedKeySpec(byte[] encodedKey)
根據指定的二進制編碼的字串生成一個key的說明
參數:encodedKey 二進制編碼的字串(通常能過PublicKey.getEncoded()生成)
javax.crypto.KeyAgreement 密碼一至類
public static final KeyAgreement getInstance(java.lang.String algorithm)
throws java.security.NoSuchAlgorithmException
返回一個指定算法的KeyAgreement對象
參數:algorithm 算法名,如今只能是DiffieHellman(DH)
public final void init(java.security.Key key)
throws java.security.InvalidKeyException
用指定的私鑰初始化
參數:key 一個私鑰
public final java.security.Key doPhase(java.security.Key key,
boolean lastPhase)
throws java.security.InvalidKeyException,
java.lang.IllegalStateException
用指定的公鑰進行定位,lastPhase肯定這是不是最後一個公鑰,對於兩個用戶的
狀況下就能夠屢次定次,最後肯定
參數:key 公鑰
lastPhase 是否最後公鑰
public final SecretKey generateSecret(java.lang.String algorithm)
throws java.lang.IllegalStateException,
java.security.NoSuchAlgorithmException,
java.security.InvalidKeyException
根據指定的算法生成密鑰
參數:algorithm 加密算法(可用 DES,DESede,Blowfish)
*/ import java.io.*; import java.math.BigInteger; import java.security.*; import java.security.spec.*; import java.security.interfaces.*; import javax.crypto.*; import javax.crypto.spec.*; import javax.crypto.interfaces.*; import com.sun.crypto.provider.SunJCE; public class testDHKey { public static void main(String argv[]) { try { testDHKey my= new testDHKey(); my.run(); } catch (Exception e) { System.err.println(e); } } private void run() throws Exception { Security.addProvider(new com.sun.crypto.provider.SunJCE()); System.out.println("ALICE: 產生 DH 對 ..."); KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH"); aliceKpairGen.initialize(512); KeyPair aliceKpair = aliceKpairGen.generateKeyPair(); //生成時間長 // 張三(Alice)生成公共密鑰 alicePubKeyEnc 併發送給李四(Bob) , //好比用文件方式,socket..... byte[] alicePubKeyEnc = aliceKpair.getPublic().getEncoded(); //bob接收到alice的編碼後的公鑰,將其解碼 KeyFactory bobKeyFac = KeyFactory.getInstance("DH"); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec (alicePubKeyEnc); PublicKey alicePubKey = bobKeyFac.generatePublic(x509KeySpec); System.out.println("alice公鑰bob解碼成功"); // bob必須用相同的參數初始化的他的DH KEY對,因此要從Alice發給他的公開密鑰, //中讀出參數,再用這個參數初始化他的 DH key對 //從alicePubKye中取alice初始化時用的參數 DHParameterSpec dhParamSpec = ((DHPublicKey)alicePubKey).getParams(); KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH"); bobKpairGen.initialize(dhParamSpec); KeyPair bobKpair = bobKpairGen.generateKeyPair(); System.out.println("BOB: 生成 DH key 對成功"); KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH"); bobKeyAgree.init(bobKpair.getPrivate()); System.out.println("BOB: 初始化本地key成功"); //李四(bob) 生成本地的密鑰 bobDesKey bobKeyAgree.doPhase(alicePubKey, true); SecretKey bobDesKey = bobKeyAgree.generateSecret("DES"); System.out.println("BOB: 用alice的公鑰定位本地key,生成本地DES密鑰成功"); // Bob生成公共密鑰 bobPubKeyEnc 併發送給Alice, //好比用文件方式,socket.....,使其生成本地密鑰 byte[] bobPubKeyEnc = bobKpair.getPublic().getEncoded(); System.out.println("BOB向ALICE發送公鑰"); // alice接收到 bobPubKeyEnc後生成bobPubKey // 再進行定位,使aliceKeyAgree定位在bobPubKey KeyFactory aliceKeyFac = KeyFactory.getInstance("DH"); x509KeySpec = new X509EncodedKeySpec(bobPubKeyEnc); PublicKey bobPubKey = aliceKeyFac.generatePublic(x509KeySpec); System.out.println("ALICE接收BOB公鑰並解碼成功"); ; KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH"); aliceKeyAgree.init(aliceKpair.getPrivate()); System.out.println("ALICE: 初始化本地key成功"); aliceKeyAgree.doPhase(bobPubKey, true); // 張三(alice) 生成本地的密鑰 aliceDesKey SecretKey aliceDesKey = aliceKeyAgree.generateSecret("DES"); System.out.println("ALICE: 用bob的公鑰定位本地key,並生成本地DES密鑰"); if (aliceDesKey.equals(bobDesKey)) System.out.println("張三和李四的密鑰相同"); //如今張三和李四的本地的deskey是相同的因此,徹底能夠進行發送加密,接收後解密,達到 //安全通道的的目的 /* * bob用bobDesKey密鑰加密信息 */ Cipher bobCipher = Cipher.getInstance("DES"); bobCipher.init(Cipher.ENCRYPT_MODE, bobDesKey); String bobinfo= "這是李四的機密信息"; System.out.println("李四加密前原文:"+bobinfo); byte[] cleartext =bobinfo.getBytes(); byte[] ciphertext = bobCipher.doFinal(cleartext); /* * alice用aliceDesKey密鑰解密 */ Cipher aliceCipher = Cipher.getInstance("DES"); aliceCipher.init(Cipher.DECRYPT_MODE, aliceDesKey); byte[] recovered = aliceCipher.doFinal(ciphertext); System.out.println("alice解密bob的信息:"+(new String(recovered))); if (!java.util.Arrays.equals(cleartext, recovered)) throw new Exception("解密後與原文信息不一樣"); System.out.println("解密後相同"); } }