`
OpenMind
  • 浏览: 180236 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

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

阅读更多

在不安全的网络环境下进行密钥交互(1/3,前面那一节),容易遭受中间人攻击,什么是中间人攻击,请google it。

 

通信的双方必须是相互信任的,在这个基础上再进行密钥协商才是可靠的。那么,如何建立信任关系呢?

 

我以前的几篇博文介绍了用如何 用  Java编程方式生成CA证书 以及用CA证书签发客户证书。

 

现在假设,Alice和Bob的证书都是被同一个CA atlas签发的(见我前面的博文),那么他们之间如何安全的交互密钥呢?

 

Alice:

 

  • 发送自己的证书Certa;
  • 发送DH 密钥对的公钥PDa;
  • 发送用自己的私钥 对DH公钥的签名Sa。
Bob与Alice执行相同的步骤,下面是Bob处理Alice发送的东西的步骤:
  • 接收Alice的公钥Certa、DH公钥PDa、和签名Sa
  • 使用CA的证书验证Certa,如果通过,就证明了Alice的证书Certa是合法的。
  • 使用证书Certa验证签名Sa,如果通过,就证明了Certa确实是Alice发送过来的,因为只有Alice用自己的私钥才可以对PDa进行签名。
Alice和Bob是对等的。
经过上面的过程,可以看出Alice和Bob在相互信任的基础上交互了DH算法的公钥,即通过这种方式避免了中间人攻击。

下面该上代码了:

/**
 * 安全的密钥交互类。
 * 这个交互工具可以校验双方的身份,并对发送的DH公钥进行签名,防止中间者攻击。
 * @author atlas
 * @date 2012-9-6
 */
public class SecureKeyExchanger extends DHKeyExchanger {
	/**
	 * 签名算法
	 */
	private static String signAlgorithm = "SHA1withRSA";

	/**
	 * 此方的私钥
	 */
	private PrivateKey privateKey;
	/**
	 * 此方的证书
	 */
	private Certificate certificate;
	/**
	 * 用于校验彼方公钥的CA证书,此证书来自此方的CA或者此方可信任的CA
	 */
	private Certificate caCertificate;
	
	/**
	 * 彼方的证书,在DH公钥交换之前进行交互获取的
	 */
	private Certificate peerCert;
	
	/**
	 * 
	 * @param out
	 * @param in
	 * @param privateKey 此方的私钥
	 * @param certificate 此方的证书
	 * @param caCertificate 用于校验彼方公钥的CA证书,此证书来自此方的CA或者此方可信任的CA
	 */
	public SecureKeyExchanger(Pipe pipe,
			PrivateKey privateKey, Certificate certificate,
			Certificate caCertificate) {
		super(pipe);
		this.privateKey = privateKey;
		this.certificate = certificate;
		this.caCertificate = caCertificate;
	}

	// Send the public key.
	public void sendPublicKey() throws IOException,
			CertificateEncodingException {
		byte[] keyBytes = certificate.getEncoded();
		write(keyBytes);
	}

	public void receivePublicKey() throws IOException, SkipException {
		byte[] keyBytes =read();
		try {
			CertificateFactory cf = CertificateFactory.getInstance("X.509");
			peerCert = cf
					.generateCertificate(new ByteArrayInputStream(keyBytes));
			peerCert.verify(caCertificate.getPublicKey());
		} catch (CertificateException e) {
			throw new SkipException("Unsupported certificate type X.509", e);
		} catch (InvalidKeyException e) {
			throw new SkipException(
					"Peer's certificate was not invlaid or not signed by current CA.",
					e);
		} catch (NoSuchAlgorithmException e) {
			throw new SkipException("Signature algorithm not supported.", e);
		} catch (NoSuchProviderException e) {
			throw new SkipException("No signature Provider.", e);
		} catch (SignatureException e) {
			throw new SkipException(
					"Peer's certificate was not invlaid or not signed by current CA.",
					e);
		}
	}

	@Override
	public void receiveDHPublicKey() throws IOException, SkipException {
		// receiver public key
		receivePublicKey();

		// receive dh public key
		byte[] publicKeyBytes = read();

		// receive signature of dh public key
		byte[] sign = read();
		KeyFactory kf;
		try {
			// verify signature using peer certificate
			Signature sig = Signature.getInstance(signAlgorithm);
			sig.initVerify(peerCert);
			sig.verify(sign);
			kf = KeyFactory.getInstance("DH");
			X509EncodedKeySpec x509Spec = new X509EncodedKeySpec(publicKeyBytes);
			peerDHPublicKey = kf.generatePublic(x509Spec);
		} catch (NoSuchAlgorithmException e) {
			throw new SkipException("Signature algorithm " + signAlgorithm
					+ " not supported.", e);
		} catch (InvalidKeySpecException e) {
			throw new SkipException("Peer's public key invalid.", e);
		} catch (InvalidKeyException e) {
			throw new SkipException("Peer's public key invalid.", e);
		} catch (SignatureException e) {
			throw new SkipException("Invalid signature.", e);
		}
	}

	@Override
	public void sendDHPublicKey() throws IOException, SkipException {
		try {
			// send public key
			sendPublicKey();
			// send dh public key
			byte[] keyBytes = dhKeyPair.getPublic().getEncoded();
			write(keyBytes);
			
			// sign dh public key using my private key and send the signature
			Signature sig;
			sig = Signature.getInstance(signAlgorithm);
			sig.initSign(privateKey);
			sig.update(keyBytes);
			byte[] sign = sig.sign();
			write(sign);
		} catch (NoSuchAlgorithmException e) {
			throw new SkipException("Signature algorithm " + signAlgorithm
					+ " not supported.", e);
		} catch (InvalidKeyException e) {
			throw new SkipException("My private key invalid.", e);
		} catch (SignatureException e) {
			throw new SkipException(
					"Signature exception when sending dh public key.", e);
		} catch (CertificateEncodingException e) {
			throw new SkipException("error when sending dh public key.", e);
		}

	}
}
 

测试代码:

 

public class KeyInfo {
	PrivateKey privateKey;
	Certificate certificate;
	Certificate caCertificate;

	public KeyInfo(PrivateKey privateKey, Certificate certificate,
			Certificate caCertificate) {
		super();
		this.privateKey = privateKey;
		this.certificate = certificate;
		this.caCertificate = caCertificate;
	}

	public Certificate getCaCertificate() {
		return caCertificate;
	}

	public Certificate getCertificate() {
		return certificate;
	}

	public PrivateKey getPrivateKey() {
		return privateKey;
	}
}
public class Server4Alice {
	public static void main(String[] args) throws Exception {
		int port = Integer.parseInt("1111");
		System.out.println(Base64.encode(exchangeFrom(port)));
	}

	public static byte[] exchangeFrom(int port) throws SkipException,
			IOException {
		InputStream file = SkipServer4Alice.class
				.getResourceAsStream("atlas-alice.jks");
		KeyInfo key = Reader.read(file, "alice", "alice");

		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 SecureKeyExchanger(pipe,
				key.getPrivateKey(), key.getCertificate(),
				key.getCaCertificate());
		exchanger.exchange();
		s.close();
		ss.close();
		return exchanger.getKey();
	}
}
public class Client4Bob {
	public static void main(String[] args) throws Exception {
		String host = "localhost";
		int port = Integer.parseInt("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 {
		InputStream file = SkipServer4Alice.class
				.getResourceAsStream("atlas-bob.jks");
		KeyInfo key = Reader.read(file, "bob", "bob");
		Socket s = new Socket(host, port);
		DataOutputStream out = new DataOutputStream(s.getOutputStream());
		DataInputStream in = new DataInputStream(s.getInputStream());
		Pipe pipe = new DataPipe(in, out);
		KeyExchanger exchanger = new SecureKeyExchanger(pipe,
				key.getPrivateKey(), key.getCertificate(),
				key.getCaCertificate());
		exchanger.exchange();
		s.close();
		return exchanger.getKey();
	}
}
 

几个JKS文件:

 

atlas-alice.jks:包含一个alice的私钥和证书,证书是用atlas的CA签发的

 

atlas-bob.jks:包含一个bob的私钥和证书,证书是用atlas的CA签发的

 

CA atlas的证书分别在alice和bob的信任证书列表里面有一个copy

 

Reader.read()是个工具方法,负责把jks文件里面的证书信息读取出来:

 

public class Reader {

	public static KeyInfo read(InputStream file, String alias, String password) {
		try {
			KeyStore store = KeyStore.getInstance("JKS");
			store.load(file, password.toCharArray());
			PrivateKeyEntry ke = (PrivateKeyEntry) store.getEntry(alias,
					new PasswordProtection(password.toCharArray()));
			KeyInfo info = new KeyInfo(ke.getPrivateKey(), ke.getCertificate(),
					ke.getCertificateChain()[1]);
			return info;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}
分享到:
评论
1 楼 OpenMind 2012-11-07  
test1

相关推荐

    java网络编程源码

    5. **NIO(非阻塞I/O)**:Java NIO提供了选择器(Selector)、通道(Channel)和缓冲区(Buffer)等机制,可以提高网络编程的效率。源码中可能会有NIO相关的例子,如使用Selector监听多个Socket通道的事件。 6. **...

    javaSSL.zip

    Java SSL(Secure Socket Layer)和TLS(Transport Layer Security)是网络安全通信的重要组成部分,主要用于加密传输数据,确保网络上的敏感信息不被窃取或篡改。Java平台提供了对SSL/TLS协议的支持,使得开发者...

    基于SOCKET的数据传输安全技术研究——以JAVA SOCKET为例.zip

    本文将深入探讨基于Socket的数据传输安全技术,以Java Socket为例,阐述如何确保在网络中传输数据时的安全性。 一、Socket基础知识 Socket在计算机网络中扮演着客户端与服务器端通信的角色。它允许两台计算机通过...

    Java中的SSL及HTTPS协议实例源码.7z

    - 在安全通道上进行加密的数据传输。 在实际开发中,我们可能会遇到一些常见问题,例如证书不受信任、握手失败等。这时,我们需要根据具体情况调整`TrustManager`和`KeyManager`的配置,或者修改JVM的信任存储库。 ...

    SSL介绍与Java实例

    SSL(Secure Sockets Layer)是安全套接字层的缩写,它是一种广泛使用的网络通信安全协议,主要用于在客户端和服务器之间建立加密的、安全的数据传输通道。SSL能够确保在网络中传输的数据不被窃取或篡改,为互联网...

    Java安全通信

    SSL是一种用于在网络上传输数据的安全协议,最初由网景公司开发,后来演变为TLS(Transport Layer Security)。SSL位于TCP/IP协议之上,应用层协议之下,提供数据加密、身份验证和数据完整性保护功能。 ##### 2.1 ...

    Java中的SSL及HTTPS协议实例源码.rar

    Java中的SSL(Secure Socket Layer)和HTTPS(Hypertext Transfer Protocol Secure)协议是网络通信安全的重要组成部分,尤其在处理敏感信息如用户登录凭证、支付信息等时,它们扮演着至关重要的角色。SSL是一种用于...

    java源码:Java中的SSL及HTTPS协议实例源码.rar

    握手完成后,我们就可以在安全的通道上进行数据传输了。 HTTPS协议是HTTP协议与SSL/TLS的结合,主要用于提供安全的网页浏览服务。当一个网站使用HTTPS时,浏览器会通过SSL/TLS与服务器建立加密连接,确保用户的登录...

    SSL及HTTPS协议_world_java_https客户端_ssl_distancemiy_

    SSL是一种用于网络通信的安全协议,它通过在客户端和服务器之间建立加密通道来保护数据的传输。SSL协议主要包括握手协议、记录协议、密钥交换协议和证书协议等组件。在握手过程中,客户端和服务器会协商加密算法、...

    基于java NIO的http代理,支持https.zip

    Java NIO(New IO)是Java 1.4版本引入的一个新特性,它为Java应用程序提供了非阻塞I/O操作的能力,与传统的IO模型(基于流的IO)相比,NIO具有更高的性能和更好的可扩展性。在本项目中,“基于java NIO的http代理,...

    javamail收发邮件加密和不加密

    在使用JavaMail时,了解如何进行加密和非加密通信对于确保数据安全至关重要。 1. **POP3(Post Office Protocol version 3)**: - POP3是一种较老的协议,主要用于从邮件服务器下载邮件。在不加密的情况下,使用...

    Java Web之高级应用.ppt Java Web之高级应用.ppt

    4. **SSL/TLS的工作原理**:SSL/TLS协议在客户端和服务器之间建立安全通道。它们通过握手协议确定加密算法,交换证书,然后生成一个对称密钥用于数据传输。这个过程确保了数据的完整性和机密性,防止中间人攻击。 5...

    php mysql安全机制

    在部署MySQL时,减少其在网络上的可见度,例如放置在DMZ(非军事区)中,可以降低被恶意攻击的风险。 #### 11. 更新与补丁 及时安装MySQL的最新更新和安全补丁,修复已知的安全漏洞,是维护数据库安全的基础。 ##...

    python基于openssl的安全聊天系统源码.zip

    SSL(Secure Socket Layer)和TLS(Transport Layer Security)是互联网上广泛采用的加密和身份验证标准,它们为网络通信提供了一个安全通道。 该安全聊天系统的实现主要包括以下几个关键知识点: 1. **SSL/TLS...

    安全元件和基于白盒技术的综合防护在车联网中的应用

    在安全元件的防护能力方面,可以从非侵入式、半侵入式和侵入式三个层面进行评估。例如,可以通过侧信道攻击、干扰攻击、随机数验证等手段来测试安全元件的安全性能。此外,对于芯片可能受到的光、放射线等干扰,以及...

    https单项认证总结

    这些协议负责在客户端和服务器之间建立安全通道,包括身份验证、密钥交换和数据加密等步骤。 1. 握手过程:客户端发送一个“ClientHello”消息,包含支持的加密套件和随机数;服务器回应“ServerHello”,选择最佳...

    用于ssh文件同步,kotlin

    在IT行业中,SSH(Secure Shell)是一种广泛使用的网络协议,用于在不安全的网络上提供安全的远程登录和其他服务。Kotlin,作为一种现代、类型安全的编程语言,被越来越多的开发者用于构建各种应用程序,包括系统...

    https 在weblogic应用

    HTTPS是HTTP的安全版本,它通过SSL或TLS(Transport Layer Security)协议在客户端和服务器之间建立安全通道。SSL/TLS协议主要负责以下几个关键任务: 1. **密钥交换**:客户端和服务器通过非对称加密算法(如RSA)...

    IIS6.0 IIS,互联网信息服务

    除了匿名访问用户(Anonymous)外,IIS中的FTP将使用Windows 2000自带的用户库(可在“开始→程序→管理工具→计算机管理”中找到“用户”一项来进行用户库的管理)。 最后,关键一步还有就是将你的电脑变为网络中的...

Global site tag (gtag.js) - Google Analytics