java开发工具包(jdk)对加密和安全性有很好的支持。其中一个优势就是其内置的对socket通信的支持。因此,很容易做到在服务器和客户之间建立安全的数据流。
java streams 是一个强大的编程工具。java.io包提供了很多标准的流类型,并能很容易的建立自己的流类型。流的一个有用的特点是和链表一样的简单处理过程。表a是一个用链表读取文本的例子:
ufferedreader br =
new bufferedreader(
new filereader(“c:/foo.txt”));
string line = null;
while((line =
br.readline()) != null)
{
system.out.println(line);
}
这段代码将 filereader和 bufferedreader链接起来。我们在用客户机/服务器应用程序的时候也会用到类似的概念。
关键字
对于验证来说,关键字很重要,表b(keygen.java)提供了一个称为getsecretkey的标准方法。通过运行keygen来产生一个关键字。因为我们采用同步方法,所以客户机和服务器必须用相同的关键字。
isting b?keygen.java
/*
* created by intellij idea.
* user: jbirchfield
* date: mar 19, 2002
* time: 9:33:22 am
*/
import com.sun.crypto.provider.sunjce;
import javax.crypto.keygenerator;
import java.io.fileinputstream;
import java.io.filenotfoundexception;
import java.io.fileoutputstream;
import java.io.ioexception;
import java.io.objectinputstream;
import java.io.objectoutputstream;
import java.security.key;
import java.security.nosuchalgorithmexception;
import java.security.security;
public class keygen
{
public static final string
key_file = "secret.key";
public static final string
algorithm = "des";
public static void main(string[] args)
{
security.addprovider(new sunjce());
new keygen();
}
public keygen()
{
keygenerator kg = null;
try {
kg = keygenerator.
getinstance(algorithm);
key key = kg.generatekey();
writekey(key_file, key);
}
catch (nosuchalgorithmexception e)
{
e.printstacktrace();
}
}
private void writekey(string
filename, object o)
{
try {
fileoutputstream fos =
new fileoutputstream(filename);
objectoutputstream oos =
new objectoutputstream(fos);
oos.writeobject(o);
oos.flush();
fos.close();
}
catch (ioexception e) {
e.printstacktrace();
}
}
public static key getsecretkey()
{
security.addprovider(new sunjce());
fileinputstream fis = null;
try
{
fis = new fileinputstream(key_file);
}
catch (filenotfoundexception e)
{
e.printstacktrace();
}
key key = null;
try {
objectinputstream ois = null;
ois = new objectinputstream(fis);
key = null;
key = (key) ois.readobject();
}
catch (ioexception e)
{
e.printstacktrace();
}
catch (classnotfoundexception e)
{
e.printstacktrace();
}
system.out.println("key = " + key);
return key;
}
}
安全socket
我们从一个简单的类开始,它提供我们在普通socket对象之上的加密。表c(secretsocket.java)包含了两段代码-socket和key对象。我们的构造器创建了变量并初始化了密码:
outcipher = cipher.getinstance(algorithm);
outcipher.init(cipher.encrypt_mode, key);
incipher = cipher.getinstance(algorithm);
incipher.init(cipher.decrypt_mode, key);
isting c?secretsocket.java
/*
* created by intellij idea.
* user: jbirchfield
* date: mar 20, 2002
* time: 9:07:51 am
*/
import org.bouncycastle.
jce.provider.bouncycastleprovider;
import javax.crypto.cipher;
import javax.crypto.cipherinputstream;
import javax.crypto.cipheroutputstream;
import javax.crypto.keygenerator;
import javax.crypto.nosuchpaddingexception;
import java.io.ioexception;
import java.io.inputstream;
import java.io.outputstream;
import java.net.socket;
import java.net.unknownhostexception;
import java.security.invalidkeyexception;
import java.security.key;
import java.security.nosuchalgorithmexception;
import java.security.nosuchproviderexception;
import java.security.security;
public class secretsocket
{
private key key = null;
private cipher outcipher = null;
private cipher incipher = null;
private cipherinputstream cis = null;
private cipheroutputstream cos = null;
private socket socket = null;
private string algorithm = "des";
public secretsocket
(socket socket, key key)
{
this.socket = socket;
this.key = key;
algorithm = key.getalgorithm();
initializecipher();
}
private void initializecipher()
{
try
{
outcipher = cipher.getinstance
(algorithm);
outcipher.init(cipher.encrypt_mode, key);
incipher = cipher.getinstance
(algorithm);
incipher.init(cipher.decrypt_mode, key);
}
catch (nosuchalgorithmexception e)
{
e.printstacktrace();
}
catch (nosuchpaddingexception e)
{
e.printstacktrace();
}
catch (invalidkeyexception e)
{
e.printstacktrace();
}
}
public inputstream getinputstream()
throws ioexception {
inputstream is =
socket.getinputstream();
cis = new cipherinputstream
(is, incipher);
return cis;
}
public outputstream getoutputstream()
throws ioexception {
outputstream os
= socket.getoutputstream();
cos = new cipheroutputstream
(os, outcipher);
return cos;
}
}
因为socket是双向的通信,所以我们采用两个密码。加密输出的数据并解密输入的数据。我们使用getinputstream()和getoutputstream(),这两种方法来加密合解密通用的输入和输出的经过包装的数据流。见表d。
isting d
public inputstream getinputstream()
throws ioexception
{
inputstream is = socket.getinputstream();
cis = new cipherinputstream(is, incipher);
return cis;
}
public outputstream getoutputstream()
throws ioexception {
outputstream os = socket.getoutputstream();
cos = new cipheroutputstream(os, outcipher);
return cos;
}
在jce的javax.crypto包中包含cipherinputstream和cipheroutputstream这两种流类型。他们接收输入输出的流对象和密码对象。
socket 服务器
开始写我们的socket服务器类吧。表e(secretsocketserver.java)是一个完整的列表。secretsocketserver在一个端口打开serversocket,当接收到连接时,使用sockethandler产生一个线程来操作连接。
isting e?secretsocketserver.java
/*
* created by intellij idea.
* user: jbirchfield
* date: mar 20, 2002
* time: 9:32:17 am
*/
import java.net.serversocket;
import java.net.socket;
import java.io.ioexception;
public class secretsocketserver
{
public static void
main(string[] args)
{
new secretsocketserver();
}
public secretsocketserver()
{
serversocket ss = null;
try {
ss = new serversocket(4444);
}
catch (ioexception e)
{
e.printstacktrace();
}
while(true) {
try {
system.out.println
("waiting...");
socket s = ss.accept
闽公网安备 35060202000074号