在android上实现ssl双向通信(https形式)

首先上一篇已经说了,我也就有了不罗嗦了,走起:

public static String Httpsdemo(Context context) throws NoSuchAlgorithmException, KeyStoreException,
	CertificateException, IOException, UnrecoverableKeyException, KeyManagementException, InterruptedException, ExecutionException
	{
		SSLContext sslContext = SSLContext.getInstance("TLS");
		
		KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
		TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
		
		KeyStore kks = KeyStore.getInstance(KeyStore.getDefaultType());
		KeyStore tks = KeyStore.getInstance(KeyStore.getDefaultType());

		InputStream keyStoreStream = HttpClientTest.class.getResourceAsStream("/assets/client.keystore");
		InputStream tkeyStoreStream = HttpClientTest.class.getResourceAsStream("/assets/newtrust.bks");
		
		char[] keyStorePassword = "123456".toCharArray();
		char[] certificatePassword = "123456".toCharArray();
		
		CertificateFactory cf = CertificateFactory.getInstance("X.509");
		
		String cerUrl = Environment.getExternalStorageDirectory().getPath() + "/client.bks";
		InputStream clientInput = new BufferedInputStream(HttpClientTest.class.getResourceAsStream("/assets/client.crt"));
		Certificate clientcer;
		try {
			clientcer = cf.generateCertificate(clientInput);
		} finally {
			clientInput.close();
		}
		
		kks.load(keyStoreStream, keyStorePassword);
		tks.load(tkeyStoreStream,keyStorePassword);

		Key key = kks.getKey("client",keyStorePassword);//这里是你建立keystore时的别名
		kks = KeyStore.getInstance("BKS");
		kks.load(null,null);
		kks.setKeyEntry("client",key,keyStorePassword,new Certificate[]{clientcer});
		kks.store();//这里你就可以用输出流把你生成的keystore给生成文件。
		
		
		kmf.init(kks, certificatePassword);
		tmf.init(tks);
		 
		KeyManager[] keyManagers = kmf.getKeyManagers();
		TrustManager[] TrustManager = tmf.getTrustManagers();
		SecureRandom secureRandom = new SecureRandom();

		sslContext.init(keyManagers, TrustManager, secureRandom);
//		从这里网上的部分就是组织建立ssl通道所需要的sslContext,里面有https需要的证书私钥等。
//		并且单向跟双向的区别可以在这个看到,单项的话是不需要keyManagers的,所以单向的话把这一项填上null

		
		String result = "";
		HttpsURLConnection http = null;
		URL url;
		try 
		{
			url = new URL("https://你要访问的地址/");
//			url = new URL("https://www.google.com.hk/intl/zh-CN/policies/terms/regional.html");
			http = (HttpsURLConnection) url.openConnection();
			((HttpsURLConnection) http).setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);// 不进行主机名确认
			http.setSSLSocketFactory(sslContext.getSocketFactory());
			http.setConnectTimeout(200000);// 设置超时时间
			http.setReadTimeout(200000);
			http.setRequestMethod("POST");// 设置请求类型为post
			http.setDoInput(true);
			http.setDoOutput(true); 
			http.setRequestProperty("connection", "keep-alive");
			http.setRequestProperty("Charsert", "UTF-8");
			http.setRequestProperty("Content-Type", "application/octet-stream");
			DataOutputStream out = new DataOutputStream(http.getOutputStream());
			String postdata = "你的数据";
			out.write(postdata.getBytes());
			out.flush();
			out.close();
			
			BufferedReader in = null;
			if (http.getResponseCode() == 200) 
			{
				in = new BufferedReader(new InputStreamReader(http.getInputStream()));
			} 
			else
			{
				in = new BufferedReader(new InputStreamReader(http.getErrorStream()));
			}
			String line = "";
			while ((line = in.readLine()) != null) {
				result += line + "\n";
			}
//			result = in.readLine();// 得到返回结果
			in.close();
			http.disconnect();
			System.out.println(result);
		}
		catch (Exception e) 
		{
			e.printStackTrace();
		}
}
在这里上面的代码都是没有问题的,现在就说一下问题吧,首先:

这里面的两个BKS文件从哪来?

答:trust.bks,我们把服务器证书和CA证书导入到里面就可以了,注意:用记事本打开,把两个证书合并成一个文件再导入,否则不知道会出现什么错误。。。

xxx.bks,需要我们自己去生成,我的做法是这样的:

首先用keytool工具生成一个BKS类型的keystore,导出证书请求,CA签过名之后,拿到证书文件,在程序里面加载keystore文件,提取出来私钥,然后重新 生成一个全新的BKS类型的keystore把key和证书导入进去,然后导出到文件,至此就拿到了客户端的密钥库。

这里面可能还会有证书类型不对的情况,这可能是由于你的服务器端的证书不是用BC生成的,这些你都可以跟CA的沟通,最后祝大家顺利。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SSL双向认证是指在SSL连接中,不仅客户端要验证服务器的身份,服务器也要验证客户端的身份。Java实现SSL双向认证一般需要以下步骤: 1. 创建KeyStore和TrustStore,分别存储客户端和服务器的证书和私钥。可以使用keytool工具来创建这些文件。 2. 在服务器端,创建SSLContext对象,并为其指定KeyManagerFactory和TrustManagerFactory。这些工厂类可以使用KeyStore和TrustStore来初始化。 3. 在客户端,创建SSLContext对象,并为其指定TrustManagerFactory。这个工厂类可以使用TrustStore来初始化。 4. 在服务器端,创建ServerSocket并开始监听客户端连接。当客户端连接到服务器时,服务器会为客户端创建一个SSLSocket并开始SSL握手。 5. 在客户端,创建SSLSocket并连接到服务器。客户端和服务器会进行SSL握手,包括交换证书和验证身份等步骤。 6. 客户端和服务器建立SSL连接后,可以开始进行安全通信。 下面是一个简单的Java SSL双向认证的示例代码: 服务器端: ```java KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(new FileInputStream("server.jks"), "password".toCharArray()); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(keyStore, "password".toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(keyStore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory(); SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(8443); while (true) { SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); // 处理客户端连接 } ``` 客户端: ```java KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(new FileInputStream("client.jks"), "password".toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(keyStore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, tmf.getTrustManagers(), null); SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket("localhost", 8443); // 发送和接收数据 ``` 需要注意的是,这只是一个简单的示例代码,实际中还需要考虑证书的管理、密码的安全等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值