Java加入信任站点_java-在非安全网络上建立可信任安全的通道(1/3)

本文介绍如何仅使用Java JCE在不安全的网络环境中建立一个可信任且安全的通道,通过Diffie-Hellman密钥交换协议实现。详细展示了DHKeyExchanger类的实现,以及客户端和服务器端的数据交互过程。
摘要由CSDN通过智能技术生成

看到标题,几乎所有人都会想到SSL,但SSL比较重量级,我想做的是只利用java的JCE体系(不是JSSE)在非安全网络环境下建立起一个可信任的、安全的通道。

所以这篇博文包括两个主题:可信任和安全。

这一节只考虑如何交互密钥。下一节(2/3)讨论如何建立信任关系,并在可信关系上交换密钥(防止中间人攻击)。

非对称密钥不适合做通道加密,通道加密必然使用对称密钥。既然如此,通信的双方(或多方)如何获取一个共同的密钥呢?

下面的代码使用Java security api在socket通道上面演示密钥交换:

参考《Java security,2nd edition》

核心代码

public class DHKeyExchanger implements KeyExchanger {

protected Pipe pipe;

protected KeyPair dhKeyPair;

protected PublicKey peerDHPublicKey;

private byte[] key;

/**

*

* @param pipe 密钥交互管道

*/

public DHKeyExchanger(Pipe pipe) {

this.pipe = pipe;

}

// 初始化DH密钥对

protected void init() throws SkipException {

try {

// Create a Diffie-Hellman key pair.

KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH");

kpg.initialize(SKIP.DHParameterSpec);

dhKeyPair = kpg.genKeyPair();

} catch (InvalidAlgorithmParameterException e) {

throw new SkipException("Invalid DH algorithm parameter.", e);

} catch (NoSuchAlgorithmException e) {

throw new SkipException("DH algorithm not supported.", e);

}

}

// 发送dh公钥

protected void sendDHPublicKey() throws IOException, SkipException {

byte[] keyBytes = dhKeyPair.getPublic().getEncoded();

write(keyBytes);

}

// 接收对方的dh公钥

protected void receiveDHPublicKey() throws IOException, SkipException {

byte[] publicKeyBytes = read();

KeyFactory kf;

try {

kf = KeyFactory.getInstance("DH");

X509EncodedKeySpec x509Spec = new X509EncodedKeySpec(publicKeyBytes);

peerDHPublicKey = kf.generatePublic(x509Spec);

} catch (NoSuchAlgorithmException e) {

throw new SkipException("DH algorithm not supported.", e);

} catch (InvalidKeySpecException e) {

throw new SkipException("Invalid public key", e);

}

}

// 生成密钥

public byte[] generateKey() throws SkipException {

KeyAgreement ka;

try {

ka = KeyAgreement.getInstance("DH");

ka.init(dhKeyPair.getPrivate());

ka.doPhase(peerDHPublicKey, true);

return ka.generateSecret();

} catch (NoSuchAlgorithmException e) {

throw new SkipException("DH algorithm not supported.", e);

} catch (InvalidKeyException e) {

throw new SkipException("Invalid private key.", e);

}

}

// all in one

public void exchange() throws SkipException, IOException {

this.init();

this.sendDHPublicKey();

this.receiveDHPublicKey();

this.key = generateKey();

}

// read a byte array

protected byte[] read() throws IOException {

return pipe.read();

}

// write a byte array

protected void write(byte[] bytes) throws IOException {

pipe.write(bytes);

}

@Override

public byte[] getKey() {

return key;

}

}

public interface KeyExchanger {

public void exchange() throws SkipException, IOException;

/**

* @return 协商好的密钥

*/

byte[] getKey();

}

public class SKIP {

// SKIP's 1024 DH parameters

private static final String SKIP1024String = "F488FD584E49DBCD20B49DE49107366B336C380D451D0F7C88B31C7C5B2D8EF6"

+ "F3C923C043F0A55B188D8EBB558CB85D38D334FD7C175743A31D186CDE33212C"

+ "B52AFF3CE1B1294018118D7C84A70A72D686C40319C807297ACA950CD9969FAB"

+ "D00A509B0246D3083D66A45D419F9C7CBD894B221926BAABA25EC355E92F78C7";

// Modulus

private static final BigInteger SKIP1024Modulus = new BigInteger(

SKIP1024String, 16);

// Base

private static final BigInteger SKIP1024Base = BigInteger.valueOf(2);

public static final DHParameterSpec DHParameterSpec = new DHParameterSpec(

SKIP1024Modulus, SKIP1024Base);

}

数据交互通道:

public interface Pipe {

byte[] read() throws IOException;

void write(byte[] data) throws IOException;

}

public class DataPipe implements Pipe {

DataInput in;

DataOutput out;

public DataPipe(InputStream in, OutputStream out) {

super();

if (in instanceof DataInputStream) {

this.in = (DataInputStream) in;

} else {

this.in = new DataInputStream(in);

}

if (out instanceof DataOutputStream) {

this.out = (DataOutputStream) out;

} else {

this.out = new DataOutputStream(out);

}

}

@Override

public byte[] read() throws IOException {

byte[] bytes = new byte[in.readInt()];

in.readFully(bytes);

return bytes;

}

@Override

public void write(byte[] data) throws IOException {

out.writeInt(data.length);

out.write(data);

}

}

测试代码:

public class Client {

public static void main(String[] args) throws Exception {

String host = "localhost";

int port =1111;

// Open the network connection.

byte[] key = exchangeFrom(host, port);

System.out.println(Base64.encode(key));

}

public static byte[] exchangeFrom(String host, int port)

throws SkipException, IOException {

Socket s = new Socket(host, port);

Pipe pipe = new DataPipe(s.getInputStream(), s.getOutputStream());

KeyExchanger exchanger = new DHKeyExchanger(pipe);

exchanger.exchange();

s.close();

return exchanger.getKey();

}

}

//

public class Server {

public static void main(String[] args) throws Exception {

System.out.println(Base64.encode(exchangeFrom(1111)));

}

public static byte[] exchangeFrom(int port)

throws SkipException, IOException {

ServerSocket ss = new ServerSocket(port);

// Wait for a connection.

Socket s = ss.accept();

DataOutputStream out = new DataOutputStream(s.getOutputStream());

DataInputStream in = new DataInputStream(s.getInputStream());

Pipe pipe = new DataPipe(in, out);

KeyExchanger exchanger = new DHKeyExchanger(pipe);

exchanger.exchange();

s.close();

ss.close();

return exchanger.getKey();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值