在本文中,我们将带你了解Java:带有自签名证书的SSL客户端身份验证在这篇文章中,我们将为您详细介绍Java:带有自签名证书的SSL客户端身份验证的方方面面,并解答java自签名证书常见的疑惑,同时
在本文中,我们将带你了解Java:带有自签名证书的SSL客户端身份验证在这篇文章中,我们将为您详细介绍Java:带有自签名证书的SSL客户端身份验证的方方面面,并解答java 自签名证书常见的疑惑,同时我们还将给您一些技巧,以帮助您实现更有效的Android Xamarin C#:带有ServiceStack和自签名证书的Https、Android中的SSL客户端身份验证、c# – 带有客户端身份验证的.Net和Java之间的SSL套接字、Flutter中自签名证书的SSL握手错误。
本文目录一览:- Java:带有自签名证书的SSL客户端身份验证(java 自签名证书)
- Android Xamarin C#:带有ServiceStack和自签名证书的Https
- Android中的SSL客户端身份验证
- c# – 带有客户端身份验证的.Net和Java之间的SSL套接字
- Flutter中自签名证书的SSL握手错误
Java:带有自签名证书的SSL客户端身份验证(java 自签名证书)
我正在尝试确保通过Internet进行通信的Java客户端/服务器应用程序的连接安全。我的想法是将SSL套接字与自签名证书和客户端身份验证一起使用。我做了以下事情:
- 服务器:包含新的自签名证书的密钥库。
keytool -genkey -kelalg RSA ...
- 客户端:包含新的自签名证书的密钥库。
keytool -genkey -kelalg RSA ...
- 服务器:包含导出的客户端证书的信任库(来自上面的项目符号)。
keytool -export
导出客户端证书并将keytool -import -v -trustcacerts
其导入服务器的信任库 - 客户端:包含导出的服务器证书的信任库(从第一个项目点开始)。
keytool -export
导出服务器证书并将keytool -import -v -trustcacerts
其导入到客户端的信任库中
信任库和密钥库正确连接到服务器/客户端。我可以看到正在加载的证书(SSL调试信息)。但是整个事情是行不通的。在SSL握手期间,出现以下错误(SSL调试信息):
main, WRITE: TLSv1 Handshake, length = 897main, READ: TLSv1 Handshake, length = 141*** Certificate chain***main, SEND TLSv1 ALERT: fatal, description = bad_certificatemain, WRITE: TLSv1 Alert, length = 2main, called closeSocket()main, handling exception: javax.net.ssl.SSLHandshakeException: null cert chainmain, IOException in getSession(): javax.net.ssl.SSLHandshakeException: null cert chainjavax.net.ssl.SSLPeerUnverifiedException: peer not authenticated at com.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificateChain(Unknown Source) at sslsocket.Server.getClientDistinguishedName(Server.java:86) at sslsocket.Server.main(Server.java:37)
当我禁用客户端身份验证时,它可以完美工作。
非常感谢您的帮助。非常感谢你!
在下面,您可以找到服务器的完整但匿名输出:
Initializing SSL***found key for : serverchain [0] = [[ Version: V3 Subject: CN=xxxxxx Server, OU=communication, O=xxxxxx, L=Zuerich, ST=ZH, C=CH Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5 Key: Sun RSA public key, 1024 bits modulus: 9487726xxxxxx15617628447913191 public exponent: 65537 Validity: [From: Thu Dec 09 17:04:05 CET 2010, To: Wed Jul 03 18:04:05 CEST 2109] Issuer: CN=xxxxxx Server, OU=communication, O=xxxxxx, L=Zuerich, ST=ZH, C=CH SerialNumber: [ 4dxxxxxx5]] Algorithm: [SHA1withRSA] Signature:0000: 6F 06 1D EA E9 DC 5B 5D EC EB 33 D4 47 01 94 1A o.....[]..3.G...xxxxxx0070: 99 78 C4 31 5F 84 8F 7B C1 2F 10 A1 9F 50 72 A1 .x.1_..../...Pr.]***adding as trusted cert: Subject: CN=xxxxxx Client, OU=communication, O=xxxxxx, L=Zuerich, ST=ZH, C=CH Issuer: CN=xxxxxx Client, OU=communication, O=xxxxxx, L=Zuerich, ST=ZH, C=CH Algorithm: RSA; Serial number: 0x4xxxxxx0 Valid from Thu Dec 09 17:06:56 CET 2010 until Wed Jul 03 18:06:56 CEST 2109trigger seeding of SecureRandomdone seeding SecureRandomOpening socketWaiting for clients...Allow unsafe renegotiation: falseAllow legacy hello messages: trueIs initial handshake: trueIs secure renegotiation: falsematching alias: servermain, called closeSocket()Allow unsafe renegotiation: falseAllow legacy hello messages: trueIs initial handshake: trueIs secure renegotiation: false[read] MD5 and SHA1 hashes: len = 30000: 01 03 01 ...[read] MD5 and SHA1 hashes: len = 980000: 00 3C 00 00 00 20 00 00 04 01 00 80 00 00 05 00 .<... ..........xxxxxx0060: 26 51 &Qmain, READ: SSL v2, contentType = Handshake, translated length = 75*** ClientHello, TLSv1RandomCookie: GMT: 1292088238 bytes = { 223,xxxxxx, 81 }Session ID: {}Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]Compression Methods: { 0 }***%% Created: [Session-1, SSL_RSA_WITH_RC4_128_MD5]*** ServerHello, TLSv1RandomCookie: GMT: 1292088238 bytes = { 222,xxxxxx, 241 }Session ID: {77,xxxxxx, 235}Cipher Suite: SSL_RSA_WITH_RC4_128_MD5Compression Method: 0Extension renegotiation_info, renegotiated_connection: <empty>***Cipher suite: SSL_RSA_WITH_RC4_128_MD5*** Certificate chainchain [0] = [[ Version: V3 Subject: CN=xxxxxx Server, OU=communication, O=xxxxxx, L=Zuerich, ST=ZH, C=CH Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5 Key: Sun RSA public key, 1024 bits modulus: 948772xxxxxx17628447913191 public exponent: 65537 Validity: [From: Thu Dec 09 17:04:05 CET 2010, To: Wed Jul 03 18:04:05 CEST 2109] Issuer: CN=xxxxxx Server, OU=communication, O=xxxxxx, L=Zuerich, ST=ZH, C=CH SerialNumber: [ 4d00fdf5]] Algorithm: [SHA1withRSA] Signature:0000: 6F 06 1D EA E9 DC 5B 5D EC EB 33 D4 47 01 94 1A o.....[]..3.G...xxxxxx0070: 99 78 C4 31 5F 84 8F 7B C1 2F 10 A1 9F 50 72 A1 .x.1_..../...Pr.]****** CertificateRequestCert Types: RSA, DSSCert Authorities:<CN=xxxxxx Client, OU=communication, O=xxxxxx, L=Zuerich, ST=ZH, C=CH>*** ServerHelloDone[write] MD5 and SHA1 hashes: len = 8970000: 02 00 00 4D 03 01 4D 04 B4 AE DE E4 AF 62 FA 48 ...M..M......b.H0xxxxxx0380: 00 .main, WRITE: TLSv1 Handshake, length = 897main, READ: TLSv1 Handshake, length = 141*** Certificate chain***main, SEND TLSv1 ALERT: fatal, description = bad_certificatemain, WRITE: TLSv1 Alert, length = 2main, called closeSocket()main, handling exception: javax.net.ssl.SSLHandshakeException: null cert chainmain, IOException in getSession(): javax.net.ssl.SSLHandshakeException: null cert chainjavax.net.ssl.SSLPeerUnverifiedException: peer not authenticated at com.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificateChain(Unknown Source) at sslsocket.Server.getClientDistinguishedName(Server.java:86) at sslsocket.Server.main(Server.java:37)
答案1
小编典典第一个SSL跟踪似乎是第二个SSL跟踪的一部分,显示在服务器上。请确认。
第二个跟踪显示服务器请求由“ CN = xxxxxx客户端,OU =通信,O = xxxxxx,L = Zuerich,ST = ZH,C =
CH”签名的RSA或DSS证书,并且客户端通过发送一个空证书链。这仅意味着客户端的密钥库中没有这样的证书,或者客户端未使用正确的密钥库。
Android Xamarin C#:带有ServiceStack和自签名证书的Https
因此,我正在使用自签名证书将所有Http Web服务更改为Https进行测试(对于我正在制作的android应用),并且它们在服务器端都可以正常运行,我知道这是因为我可以将证书添加到PC的证书存储中,并且完美访问该网站,涉及到我的android应用对其进行调用时,我在客户端遇到了什么麻烦.
我的Servicestack调用看起来像这样:
var client = new JsonServiceClient(stubServicesBaseUrl);
return client.Get(new GetLastStatusUpdate()).StatusUpdates.Last();
并且这些曾经在只有http的情况下工作,但是自从我添加了将自签名证书添加到android受信任的凭据存储中的代码以来,调用已停止工作,而请求似乎超时了.
byte[] certificate;
using (var streamReader = new StreamReader(Assets.Open("ScoutTestCert.crt")))
{
using (var byteStream = new MemoryStream())
{
streamReader.BaseStream.copyTo(byteStream);
certificate = byteStream.ToArray();
}
}
var installCertificate = KeyChain.CreateInstallIntent();
installCertificate.PutExtra(KeyChain.ExtraCertificate, certificate);
StartActivity(installCertificate);
上面的代码将证书添加到“用户”部分中的android可信存储中,并允许我通过androidEmulator上的Internet应用程序导航到该站点而不会出现问题,因此看来问题仅在尝试在我的ServiceStack中进行调用时出现应用程式程式码.
我是否在代码中缺少某些内容,例如服务堆栈需要的额外设置或类似内容?几天来,我一直在为这个问题而苦苦挣扎!
我试图将webservice调用保留为servicestack,因为我希望它是PCL而不是android特定代码.
谢谢.
解决方法:
ServiceStack的.NET Service Clients使用.NET的BCL内置的HttpWebRequest来使自签名证书与.NET HTTP客户端一起使用,您需要注册custom Certificate Validation Callback,例如下面的回调将使所有证书成功:
ServicePointManager.ServerCertificateValidationCallback +=
(sender, certificate, chain, sslPolicyErrors) => true;
但是您可能希望将验证范围限制为与您的自签名证书一起使用.
使用ServiceStack的基于HttpWebRequest的Service Client的替代方法是使用PCL HttpClient-based JsonHttpClient,这具有以下优点:可以将其配置为使用ModernHttpClient并具有以下功能:
JsonHttpClient.GlobalHttpMessageHandlerFactory = () =>
new NativeMessageHandler()
哪个代替使用.NET HTTP Client堆栈,而是使用基础iOS和Android平台上可用的本机HTTP库.然后,您应该可以使用在Android上注册的所有证书.
为了使用通过ModernHttpClient在.NET中注册的不受信任的自签名证书,您将需要使用pro version of ModernHttpClient作为mentioned on this thread.
Android中的SSL客户端身份验证
我需要编写将与.Net服务通信的Android应用.我必须进行服务器/客户端身份验证.我发现了一些有用的主题(this blog和this blog),但是它们都显示了如何进行服务器身份验证.如何进行客户端身份验证?我找到了一个有用的discussion,但是作者使用了Sockets,但是我需要通过HttpClient来实现.
解决方法:
以下内容使我可以使用自己的rootca和客户端服务器证书.即,安全而不用付钱给任何人:-)
使用openssl创建rootca以及客户端和服务器密钥以及证书(网络上的许多教程)
使用bouncycastle作为提供者和-importcert使用keytool创建rootcacert.bks
使用openssl pkcs12 -export创建clientcertandkey.p12 …
HttpClient httpClient = null;
try {
HttpParams httpParameters = new BasicHttpParams();
KeyStore rootca = KeyStore.getInstance("BKS");
rootca.load(getResources().openRawResource(R.raw.rootcacert),"bkskeystorepass".tochararray());
KeyStore mycert = KeyStore.getInstance("pkcs12");
mycert.load(getResources().openRawResource(R.raw.clientcertandkey),"pkcs12storepass".tochararray());
SSLSocketFactory sockfact = new SSLSocketFactory(mycert,null,rootca);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("https",sockfact , 443));
httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager(httpParameters, registry), httpParameters);
} catch (Exception e) {
e.printstacktrace();
}
c# – 带有客户端身份验证的.Net和Java之间的SSL套接字
在.net中我使用sslStream建立连接,在Java上我使用的是标准的SSLSocket.下面是一些代码片段,但这是我到目前为止的内容:
在服务器端(Windows),我在MMC下的Personal / Certificates文件夹中有一个私有证书.我在“受信任的人/证书”中拥有来自客户的公共证书.两个证书都是由同一个CA颁发的.两个证书的证书链都有多个级别,但两者都相同.链中的根级证书也安装在受信任的证书颁发机构/证书文件夹中.
在客户端(Linux),我有一个密钥库,其中包含与服务器上安装的公共证书匹配的私有证书.我有一个信任存储,它包含来自服务器的公共证书,与服务器的私有证书匹配.
在服务器端(.net)我使用的是一个执行异步读取的Socket,然后它被包装到SSLStream中,代码片段如下所示:
NetworkStream ns = new NetworkStream(socket,false); SslStream ssl = new SslStream(ns,true); ssl.AuthenticateAsServer(serverCertificate,true,SslProtocols.Default,true);
客户端代码几乎是标准代码:
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); InetAddress addr = InetAddress.getByName(servername); SSLSocket socket = (SSLSocket) factory.createSocket(addr,port); socket.setUseClientMode(true); socket.setNeedClientAuth(true); socket.setWantClientAuth(true); socket.startHandshake(); os = new DataOutputStream(socket.getoutputStream()); is = new DataInputStream(socket.getInputStream()); byte[] outBuf = new byte[50]; os.write("SEND SOMETHING".getBytes("UTF-8")); is.read(outBuf);
在java中,我设置了适当的varialbes以指向信任和密钥存储区及其密码.
现在,遵循标准SSL握手,这是发生的事情:
> ClientHello
> ServerHello
>服务器发送公共证书
>客户端将公共证书与信任存储上的证书进行匹配
>服务器发送证书请求
>使用证书请求,服务器发送有效CA列表,在此列表中仅发送我的根CA(在其他众所周知的CA的长列表中).
>客户端证书为空.
>服务器从客户端收到空证书,从而关闭连接.
就是这样,客户端不会将有效证书发送回服务器.我对此有一些疑问:
有没有人经历过这样的事情?
关于服务器发送的CA列表(Windows),.net如何确定要发送给客户端的内容?有没有办法修改该列表?
我是否需要发送用于在CA列表中签署证书的链中的所有权限?或根够了吗?
我在代码的两边都遗漏了什么吗?
任何帮助将不胜感激.
在
解决方法
socket.setNeedClientAuth(true); socket.setWantClientAuth(true);
您看到证书请求消息和客户端证书消息的事实表明服务器配置正确.
在客户端证书消息中缺少证书的最可能原因是密钥库(在客户端)可能未正确配置.您可能对this answer感兴趣,以确保正确配置了客户端密钥库.更具体地说,您需要确保将客户端证书的私钥导入到与证书链相同的别名中(并且它是链回到证书请求消息中公布的CA).
(关于你的其余问题,我不确定在C#中使用SslStream时如何修改服务器发送的CA列表.This earlier question似乎表明没有解决方案,尽管.Net的新版本可能解决了这个问题因为这个问题被问到了.通过查看SslStream api文档和相关类,我找不到任何可以做到的事情,但这并不意味着它不存在.)
Flutter中自签名证书的SSL握手错误
我正在尝试使用自签名证书连接服务器,但出现错误:
E / flutter(3781):HandshakeException:客户端中的握手错误(操作系统错误:
E / flutter(3781):CERTIFICATE_VERIFY_FAILED:主机名不匹配(ssl_cert.c :345))
代码,我在此设置证书:
String path = ''/storage/sdcard0/server.crt'';SecurityContext context = new SecurityContext();context.setTrustedCertificates(path, password: ''hello'');_client = new HttpClient(context: context);
我做错了什么?
如果未设置SecurityContext,则会收到SSL握手错误。
答案1
小编典典我使用了HttpClient.badCertificateCallback,
这是接受任何证书的代码:
_client = new HttpClient();_client.badCertificateCallback = (X509Certificate cert, String host, int port) => true;
今天关于Java:带有自签名证书的SSL客户端身份验证和java 自签名证书的介绍到此结束,谢谢您的阅读,有关Android Xamarin C#:带有ServiceStack和自签名证书的Https、Android中的SSL客户端身份验证、c# – 带有客户端身份验证的.Net和Java之间的SSL套接字、Flutter中自签名证书的SSL握手错误等更多相关知识的信息可以在本站进行查询。
本文标签: