SSL/TLS 单双向认证代码示例

采用SSL/TLS形式的安全链接,能防止数据传输过程中被截获修改等问题。

SSL算法简短说明:

    对称加密算法:DES 3DES AES 客户端和服务端使用同一个密钥对消息进行加密解密。
    非对称加密算法:RSA, 生成公钥和私钥,采用公钥加密,私钥解密。客户端和服务器端各自持有自己的私钥证书,相互信任对方的证书(证书都导入到了对方的私钥仓库)
    速度上,对称加密算法比非对称加密算法要快。

 

下面使用jdk工具keytool生成服务端和客户端的密钥和证书,采用的是RSA的非对称加密形式。

生成服务器端证书仓库

keytool -genkey -alias serverks -keysize 2048 -validity 365 -keyalg RSA -dname "CN=localhost" -keypass serverpwd -storepass serverpwd -keystore D:/server-keystore.jks

生成服务器端证书(alias与上面生成时指定的要相同)

keytool -export -alias serverks -keystore D:/server-keystore.jks -storepass serverpwd -file D:/server-cert.cer

生成客户端证书仓库

keytool -genkey -alias clientks -keysize 2048 -validity 365 -keyalg RSA -dname "CN=localhost" -keypass clientpwd -storepass clientpwd -keystore D:/client-keystore.jks

生成客户端证书(alias与上面生成时指定的要相同)

keytool -export -alias clientks -keystore D:/client-keystore.jks -storepass clientpwd -file D:/client-cert.cer

上面四个命令就可以生成客户端和服务器端的证书和仓库了。

对于单项认证,客户端验证服务器端,服务器端不做验证情况,只需要将服务器端证书导入到客户端证书仓库。

对于双向认证,除了上面的导入操作外,还需要将客户端证书导入到服务器端证书仓库。

命令如下:

服务器端证书导入客户端证书仓库

keytool -import -trustcacerts -alias servercert2clientks -file D:/server-cert.cer -storepass clientpwd -keystore D:/client-keystore.jks

客户端证书导入到服务器端证书仓库

keytool -import -trustcacerts -alias clientcert2serverks -file D:/client-cert.cer -storepass serverks -keystore D:/server-keystore.jks

上述命令解释:

keytool    //java jdk自带工具

-genkey  //生成key的命令参数

-alias //生成key别名

-keysize // key大小,2048

-validity //有效期,单位天

-keyalg //key的算法,本文采用RSA

-dname //key的信息串,CN=这里是域名,此外还有OU / O / L / S / C=CH 代表拥有者/归属/地区/城市/国家

-keypass // 生成key的密码,

-storepass //存储的密码

-keystore //生成key输出的路径和文件名

-export //导出证书

-import //导入证书

-file //导出的文件

 

下面是Java中SSLContext的生成过程:

单向SSL认证服务端代码(客户端对服务端证书进行验证,服务器端接受所有证书)

 

		//获取X509算法的key管理工厂类
		KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
		//获取keystore类型实例,jks类型
		KeyStore ks = KeyStore.getInstance("JKS");
		//读取服务器端的证书库
		InputStream in = ClassLoader.getSystemResourceAsStream("server-keystore.jks");
		//加载到keystore,第二个参数密码
		ks.load(in, "serverpwd".toCharArray());
		in.close();
		//初始化keymanager通过keystore和密码
		kmf.init(ks, "serverpwd".toCharArray());
		//获取sslcontext,SSL/TLSv1.x
		SSLContext serverContext = SSLContext.getInstance("TLSv1.2");
		//单项认证,客户端认证服务器,trustmanager为空,就是服务器端信任所有客户端证书
		serverContext.init(kmf.getKeyManagers(), null, null);

双向认证相比上面,只是让sslcontext的第二个信任证书参数传递不为空即可,代表服务器端新人的证书对象。

 

 

		//获取X509算法的key管理工厂类
		KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
		//获取keystore类型实例,jks类型
		KeyStore ks = KeyStore.getInstance("JKS");
		//读取服务器端的证书库
		InputStream in = ClassLoader.getSystemResourceAsStream("server-keystore.jks");
		//加载到keystore,第二个参数密码
		ks.load(in, "serverpwd".toCharArray());
		in.close();
		//初始化keymanager通过keystore和密码
		kmf.init(ks, "serverpwd".toCharArray());
		//获取sslcontext,SSL/TLSv1.x
		SSLContext serverContext = SSLContext.getInstance("TLSv1.2");
		//获取x509信任证书工厂,并根据keystore初始化, 服务器端验证客户端证书是否有效
		TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
		tmf.init(ks);
		
		//双向认证,此处多trustManagers参数
		serverContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

对于TrustManager可以自己实现,但是一般很少自己实现,实现方式如下:

 

 

		//获取X509算法的key管理工厂类
		KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
		//获取keystore类型实例,jks类型
		KeyStore ks = KeyStore.getInstance("JKS");
		//读取服务器端的证书库
		InputStream in = ClassLoader.getSystemResourceAsStream("server-keystore.jks");
		//加载到keystore,第二个参数密码
		ks.load(in, "serverpwd".toCharArray());
		in.close();
		//初始化keymanager通过keystore和密码
		kmf.init(ks, "serverpwd".toCharArray());
		//获取sslcontext,SSL/TLSv1.x
		SSLContext serverContext = SSLContext.getInstance("TLSv1.2");
		//自定义实现证书验证
		X509TrustManager x509 = new X509TrustManager() {
			
			public X509Certificate[] getAcceptedIssuers() {
				return null;
			}
			
			/**
			 * 服务器端检查
			 */
			public void checkServerTrusted(X509Certificate[] chain, String authType)
					throws java.security.cert.CertificateException {
				if (chain == null || chain.length == 0) {
					throw new IllegalArgumentException("X509Certificate chain cannot be null");
				}
				if (authType == null || authType.equals("")) {
					throw new IllegalArgumentException("X509Certificate authType cannot be null");
				}
				boolean isSucc = false;
				Principal p = null;
				for (X509Certificate x : chain) {
					p = x.getSubjectDN();
					//Principal getName 为keytool 中的-dname参数对应的值
					if (p != null && p.getName().contains("localhost")) {//这里只验证了-dName那个参数是否能识别
						isSucc = true;
						return ;
					}
				}
				if (!isSucc) {
						throw new  java.security.cert.CertificateException("no authorizication");
				}
			}
			
			/**
			 * 客户端检查
			 */
			public void checkClientTrusted(X509Certificate[] chain, String authType)
					throws java.security.cert.CertificateException {
				if (chain == null || chain.length == 0) {
					throw new IllegalArgumentException("X509Certificate chain cannot be null");
				}
				if (authType == null || authType.equals("")) {
					throw new IllegalArgumentException("X509Certificate authType cannot be null");
				}
				boolean isSucc = false;
				Principal p = null;
				for (X509Certificate x : chain) {
					p = x.getSubjectDN();
					if (p != null && p.getName().contains("localhost")) {
						isSucc = true;
						return ;
					}
				}
				if (!isSucc) {
						throw new  java.security.cert.CertificateException("no authorizication");
				}
			}
		};
		
		//双向认证,自定义x509验证实现
		serverContext.init(kmf.getKeyManagers(), new TrustManager[]{x509}, null);
		
 

 

 

 

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
mbedtls是一个开源的加密库,提供了双向认证的功能。以下是mbedtls进行双向认证的一般代码示例: 1. 初始化mbedtls库并配置客户端和服务器端的身份验证参数。 ``` mbedtls_ssl_config client_config; mbedtls_ssl_config server_config; mbedtls_ssl_config_init(&client_config); mbedtls_ssl_config_init(&server_config); // 配置客户端和服务器端的身份验证参数 mbedtls_ssl_conf_authmode(&client_config, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_authmode(&server_config, MBEDTLS_SSL_VERIFY_REQUIRED); // 配置CA证书和私钥 mbedtls_ssl_conf_ca_chain(&client_config, ca_cert, NULL); mbedtls_ssl_conf_ca_chain(&server_config, ca_cert, NULL); mbedtls_ssl_conf_own_cert(&client_config, client_cert, client_key); mbedtls_ssl_conf_own_cert(&server_config, server_cert, server_key); ``` 2. 创建一个mbedtlsTLS上下文。 ``` mbedtls_ssl_context ssl_ctx; mbedtls_ssl_init(&ssl_ctx); ``` 3. 设置TLS上下文的配置。 ``` mbedtls_ssl_setup(&ssl_ctx, &client_config); mbedtls_ssl_setup(&ssl_ctx, &server_config); ``` 4. 在客户端和服务器端分别进行握手。 ``` // 客户端握手 mbedtls_ssl_set_hostname(&ssl_ctx, server_hostname); mbedtls_ssl_set_bio(&ssl_ctx, sockfd, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout); mbedtls_ssl_handshake_client(&ssl_ctx); // 服务器端握手 mbedtls_ssl_set_bio(&ssl_ctx, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL); mbedtls_ssl_handshake_server(&ssl_ctx); ``` 5. 进行双向验证。 ``` // 客户端验证服务器端证书 if (mbedtls_ssl_get_verify_result(&ssl_ctx) != 0) { // 验证失败 } // 服务器端验证客户端证书 if (mbedtls_ssl_get_verify_result(&ssl_ctx) != 0) { // 验证失败 } ``` 以上代码示例演示了mbedtls进行双向认证的基本步骤。在实际应用中,还需根据具体需求进行适当的配置和处理。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* *2* [Mbedtls随笔](https://blog.csdn.net/qq_44455716/article/details/102790232)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值