java 密钥工厂 desede_20145212 实验五《Java网络编程》
20145212 實驗五《Java網絡編程》
一、實驗內容1.運行下載的TCP代碼,結對進行,一人服務器,一人客戶端;
2.利用加解密代碼包,編譯運行代碼,一人加密,一人解密;
3.集成代碼,一人加密后通過TCP發送;
4.結對伙伴:20145223楊夢云,我負責服務端,她負責客戶端。
注:加密使用AES或者DES/AES或者DES加密密鑰key并發送,使用服務器的公鑰加密/公鑰算法使用RSA或DH/檢驗發送信息的完整性使用MD5或者SHA3;
5.完成Blog。
二、實驗步驟1.學習TCP
根據如下程序,體會TCP含義。
服務器端:
package chapter9;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerTest
{
public static final int PORT = 8081;
public static void main(String[] args) throws IOException
{
ServerSocket s = new ServerSocket(PORT);
System.out.println("Started:"+s);
try
{
Socket socket = s.accept();
try
{
System.out.println("Connection accepted:"+socket);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
while(true)
{
String str=in.readLine();
if(str.equals("END"))
break;
System.out.print("Echoing:"+str);
out.println(str);
}
}
finally
{
System.out.println("closing...");
socket.close();
}
}
finally
{
s.close();
}
}
}
客戶端:
package chapter9;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;;
public class ClientTest
{
public static void main(String[] args) throws IOException
{
InetAddress addr = InetAddress.getByName("192.168.1.35");
System.out.println("addr ="+addr);
Socket socket = new Socket(addr,ServerTest.PORT);
try
{
System.out.println("socket="+socket);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
for(int i =0;i<0;i++)
{
out.println("howdy"+i);
String str = in.readLine();
System.out.println(str);
}
out.println("END");
}
finally
{
System.out.println("closing...");
socket.close();
}
}
}
2.信息安全傳送:
發送方A——————>接收方B
A加密時,用B的公鑰
B解密時,用B的私鑰
·發送方A對信息(明文)采用DES密鑰加密,使用RSA加密前面的DES密鑰信息,最終將混合信息進行傳遞。同時用hash函數將明文進行用作驗證。
·接收方B接收到信息后,用RSA解密DES密鑰信息,再用RSA解密獲取到的密鑰信息解密密文信息,最終就可以得到我們要的信息(明文)。用hash函數對解出的明文進行驗證。
3.運行加解密包中的程序
·運行DES加密代碼
import java.io.*;
import javax.crypto.*;
public class Skey_DES{
public static void main(String args[]) throws Exception{
KeyGenerator kg=KeyGenerator.getInstance("DESede");
kg.init(168);
SecretKey k=kg.generateKey( );
FileOutputStream f=new FileOutputStream("key1.dat");
ObjectOutputStream b=new ObjectOutputStream(f);
b.writeObject(k);
}
}
import java.io.*;
import java.security.*;
public class Skey_kb{
public static void main(String args[]) throws Exception{
FileInputStream f=new FileInputStream("key1.dat");
ObjectInputStream b=new ObjectInputStream(f);
Key k=(Key)b.readObject( );
byte[ ] kb=k.getEncoded( );
FileOutputStream f2=new FileOutputStream("keykb1.dat");
f2.write(kb);
// 打印密鑰編碼中的內容
for(int i=0;i
System.out.print(kb[i]+",");
}
}
}
String keyString=”abcd”;
byte[]keyData=keyString.getBytes();
secretKey myDeskey=new SecretKeySpec(keyData,”DES”);
·獲取密鑰生成器
KeyGenerator kg=KeyGenerator.getInstance("DESede");
·Java中KeyGenerator類中提供了創建對稱密鑰的方法。Java中的類一般使用new操作符通過構造器創建對象,但KeyGenerator類不是這樣,它預定義了一個靜態方法getInstance(),通過它獲得KeyGenerator類型的對象。這種類成為工廠類或工廠。
·方法getInstance( )的參數為字符串類型,指定加密算法的名稱。可以是 “Blowfish”、“DES”、“DESede”、“HmacMD5”或“HmacSHA1”等。這些算法都可以實現加密,這里我們不關心這些算法的細節,只要知道其使用上的特點即可。
·初始化密鑰生成器
該步驟一般指定密鑰的長度。如果該步驟省略的話,會根據算法自動使用默認的密鑰長度。指定長度時,若第一步密鑰生成器使用的是“DES”算法,則密鑰長度必須是56位;若是“DESede”,則可以是112或168位,其中112位有效;若是“AES”,可以是128, 192或256位。
·生成密鑰SecretKey k=kg.generateKey( );
使用第一步獲得的KeyGenerator類型的對象中generateKey( )方法可以獲得密鑰。其類型為SecretKey類型,可用于以后的加密和解密。
·通過對象序列化方式將密鑰保存在文件中
FileOutputStream f=new FileOutputStream("key1.dat");
ObjectOutputStream b=new ObjectOutputStream(f); b.writeObject(k);
·ObjectOutputStream類中提供的writeObject方法可以將對象序列化,以流的方式進行處理。這里將文件輸出流作為參數傳遞給ObjectOutputStream類的構造器,這樣創建好的密鑰將保存在文件key1.data中。
4.最終,服務器端代碼如下:
package javaapplication40;
import java.net.*;
import java.io.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class MyServer {
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
ServerSocket sc = null;
ServerSocket sc1 = null;
Socket socket=null;
Socket socket1=null;
try {
sc= new ServerSocket(4431);//創建服務器套接字
sc1= new ServerSocket(4430);//創建服務器套接字
System.out.println("端口號:" + sc.getLocalPort());
System.out.println("服務器1已經啟動...");
System.out.println("端口號:" + sc1.getLocalPort());
System.out.println("服務器2已經啟動...");
socket = sc.accept(); //等待客戶端連接
System.out.println("已經建立連接");
socket1 = sc1.accept(); //等待客戶端連接
System.out.println("已經建立1連接");
//獲得網絡輸入流對象的引用
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedReader in1 = new BufferedReader(new InputStreamReader(socket1.getInputStream()));
獲得網絡輸出流對象的引用
System.out.print("已接收\n");
PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
String aline=in.readLine();//讀取客戶端傳送來的數據
String aline1=in1.readLine();
System.out.print("寫入文件中...\n");
byte [] bytes = aline.getBytes("GB2312");
byte [] bytes1 = aline1.getBytes("GB2312");
aline = new String(bytes, "GB2312");
aline1 = new String(bytes1, "GB2312");
FileOutputStream s=new FileOutputStream("key1.dat");
s.write(bytes);
FileOutputStream s1=new FileOutputStream("SEnc.dat");
s1.write(bytes1);
System.out.print("已寫入文件\n");
//生成解密密鑰
FileInputStream f=new FileInputStream("key1.dat");
ObjectInputStream b=new ObjectInputStream(f);
Key k=(Key)b.readObject( );
byte[ ] kb=k.getEncoded( );
FileOutputStream f2=new FileOutputStream("keykb1.dat");
f2.write(kb);
System.out.print("生成解密密鑰\n");
// 打印密鑰編碼中的內容
for(int i=0;i
// System.out.print(kb[i]+",");
}
//解密
FileInputStream a=new FileInputStream("SEnc.dat");
int num=a.available();
byte[ ] ctext=new byte[num];
a.read(ctext);
FileInputStream f1=new FileInputStream("keykb1.dat");
int num2=f1.available();
byte[ ] keykb=new byte[num2];
f1.read(keykb);
SecretKeySpec e=new SecretKeySpec(keykb,"DESede");
Cipher cp=Cipher.getInstance("DESede");
cp.init(Cipher.DECRYPT_MODE, k);
byte []ptext=cp.doFinal(ctext);
String p=new String(ptext,"GB2312");
System.out.print("解密中...\n");
System.out.println(p);
//返回
System.out.println("從客戶端接收到信息為:"+p); //通過網絡輸出流返回結果給客戶端
out.println(p);
out.close();
in.close();
sc.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
三、實驗中遇到的問題及解決方案出現java.net.BindException:Address already in use: JVM_Bind
通過百度原因,我們知道這是因為端口已經被占用,只需要找一個沒有被占用的端口就能解決這個問題。
兩臺電腦無法聯通
1.在實驗室時我們起初是從網絡上搜ip出來的地址,然后顯示連接超時。之后用在命令行中用ipconfig查看地址,找到自己的IPv4地址,但是換上之后還是失敗了——連接超時。
2.我們認為可能是兩臺電腦沒有在同一個網絡里而不發鏈接成功,嘗試著用一臺電腦連接網絡然后wifi給另一臺電腦使用,然后再次連接兩臺電腦,終于連通成功了。
連接成功后出現java.net.SocketException: Connection reset
該異常在客戶端和服務器端均有可能發生,引起該異常的原因有兩個,第一個就是如果一端的Socket被關閉(或主動關閉或者因為異常退出而引起的關閉),另一端仍發送數據,發送的第一個數據包引發該異常(Connect reset by peer)。另一個是一端退出,但退出時并未關閉該連接,另一端如果在從連接中讀數據則拋出該異常(Connection reset)。簡單的說就是在連接斷開后的讀和寫操作引起的。
實驗中出現了問題是因為代碼在運行到讀寫數據的時候鏈接已經失效,通過修改,最終成功。
服務端:
客戶端:
## PSP(Personal Software Process)時間步驟耗時百分比
需求分析20min8.3%
設計60min25.0%
代碼實現80min33.3%
測試40min16.7%
分析總結40min16.7%
總結
以上是生活随笔為你收集整理的java 密钥工厂 desede_20145212 实验五《Java网络编程》的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 上海欢乐谷内有啥吃的
- 下一篇: java人工洗牌窗口程序_求解,用JAV