首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 开源软件 >

java-在非安全网络下建立可信任安全的通道(1/3)

2012-10-13 
java-在非安全网络上建立可信任安全的通道(1/3)? ? ? 看到标题,几乎所有人都会想到SSL,但SSL比较重量级,我

java-在非安全网络上建立可信任安全的通道(1/3)

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

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

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

?

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

?

? ? ? DH算法(Diffie-Hellman)是一种密钥协商算法,不理解原理的可以看这里:http://zh.wikipedia.org/wiki/Diffie-Hellman%E5%AF%86%E9%92%A5%E4%BA%A4%E6%8D%A2

?

下面的代码使用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 onepublic void exchange() throws SkipException, IOException {this.init();this.sendDHPublicKey();this.receiveDHPublicKey();this.key = generateKey();}// read a byte arrayprotected byte[] read() throws IOException {return pipe.read();}// write a byte arrayprotected void write(byte[] bytes) throws IOException {pipe.write(bytes);}@Overridepublic byte[] getKey() {return key;}}
public interface KeyExchanger {public void exchange() throws SkipException, IOException;/** * @return 协商好的密钥 */byte[] getKey();}
public class SKIP {// SKIP's 1024 DH parametersprivate static final String SKIP1024String = "F488FD584E49DBCD20B49DE49107366B336C380D451D0F7C88B31C7C5B2D8EF6"+ "F3C923C043F0A55B188D8EBB558CB85D38D334FD7C175743A31D186CDE33212C"+ "B52AFF3CE1B1294018118D7C84A70A72D686C40319C807297ACA950CD9969FAB"+ "D00A509B0246D3083D66A45D419F9C7CBD894B221926BAABA25EC355E92F78C7";// Modulusprivate static final BigInteger SKIP1024Modulus = new BigInteger(SKIP1024String, 16);// Baseprivate 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);}}@Overridepublic byte[] read() throws IOException {byte[] bytes = new byte[in.readInt()];in.readFully(bytes);return bytes;}@Overridepublic 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();}}
?

?

1 楼 OpenMind 2012-10-05   数据交互通道采用接口方式设计,是与通信协议无关的,实例使用的是socket,其实http连接的双方也可以通过不同的Pipe的实现做到交互密钥的。

热点排行