처음에는 ...이 프로그램은 단지 4 개 재미 일 뿐이며 게시되지 않습니다. 소켓 테스트 전용이므로이 연결의 보안에 대해 신경 쓰지 마십시오. 텍스트 상자에 메시지를 입력 할 수있는 작은 메신저를 코딩하면 서버로, 서버에서 모든 클라이언트로 전송됩니다. 여태까지는 그런대로 잘됐다. 재미로이 연결에 SSL을 사용하고 싶었습니다. 하지만 서버 소켓에 연결하려고 할 때 ValidateServerCertificate에서 RemoteCertificateNameMismatch를 반환합니다. 디버그 메시지를 추가 한 후 Sslstream.LocalCertificate가 null임을 발견했습니다. 이 누락 된 인증서를 어떻게 수정할 수 있습니까? 자체 서명 된 인증서를 사용하고 있습니다.
제발 도와주세요, 여기 내 코드가 있습니다 ... 그리고 예 ... 내 나쁜 영어에 대해 죄송합니다 : / :
[...]
public bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
//sslPolicyErrors returns RemoteCertificateNameMismatch
return true; //Code shortened
}
public X509CertificateCollection getCertificates()
{
X509CertificateCollection cCollection = new X509CertificateCollection();
cCollection.Add(getCertificate());
return cCollection;
}
private X509Certificate getCertificate()
{
string Certificate = "D:/Wlad/Programmierung/Zertifikat/CA/CertificateAuthority.crt";
string ClientCertificatePassword = "...";
return new X509Certificate(Certificate, ClientCertificatePassword);
}
public X509Certificate SelectLocalCertificate(
object sender,
string targetHost,
X509CertificateCollection localCertificates,
X509Certificate remoteCertificate,
string[] acceptableIssuers)
{
foreach(X509Certificate cer in localCertificates) {
return cer;
}
return getCertificate();
}
public void connect(String username)
{
XMLConfigManager xml = XMLConfigManager.getInstance();
String ip = xml.get("ip");
tc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ;
tc.Connect(ip, int.Parse(xml.get("port")));
networdstream = new NetworkStream(tc);
using(sslstream = new SslStream(networdstream, false, new RemoteCertificateValidationCallback(ValidateServerCertificate), new LocalCertificateSelectionCallback(SelectLocalCertificate)))
{
sslstream.AuthenticateAsClient(ip, getCertificates(), SslProtocols.Default, true);
}
sendMessage(username);
t = new Thread(new ThreadStart(checkInput));
t.Start();
tm.addThread(t);
th = new Thread(new ThreadStart(userTimer));
th.Start();
tm.addThread(th);
}
public void disconnect()
{
if(sslstream != null) {
sslstream.Close();
}
if(tc != null) {
tc.Close();
}
}
[...]
static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
public void sendMessage(String s)
{
try
{
if ((s != null) && (s.Length > 0))
{
try
{
sslstream.Write(GetBytes(s));
}
catch (Exception)
{
}
}
}
catch (Exception ex)
{
endError(ex);
return;
}
}
public void userTimer()
{
Thread.Sleep(2000);
sendCommand("usercount");
th = new Thread(new ThreadStart(userTimer));
th.Start();
tm.addThread(th);
}
[...]
static String ReadMessage(SslStream sslStream)
{
byte[] buffer = new byte[2048];
StringBuilder messageData = new StringBuilder();
int bytes = -1;
do
{
bytes = sslStream.Read(buffer, 0, buffer.Length);
// Use Decoder class to convert from bytes to UTF8
// in case a character spans two buffers.
Decoder decoder = Encoding.UTF8.GetDecoder();
char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
decoder.GetChars(buffer, 0, bytes, chars, 0);
messageData.Append(chars);
} while (bytes != 0);
return messageData.ToString();
}
public void checkInput()
{
try
{
Form2 f2 = f1.f;
if(!isConnected()) {
t.Abort();
return;
}
String s = ReadMessage(sslstream);
if(s == null) {
t.Abort();
return;
}
CommandHandler ch = new CommandHandler();
Boolean handle = ch.handle(s, f1.f);
if (!handle) {
if (s == "Der Benutzername ist schon vergeben.")
{
endDuplicatename();
return;
}
f2.Invoke(new Action(() => f2.chat.Items.Add(s)));
f2.Invoke(new Action(() => f2.select_newest()));
}
}
finally
{
t = new Thread(new ThreadStart(checkInput));
t.Start();
tm.addThread(t);
}
}
package de.wladhd.server;
import java.net.Socket;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import de.wladhd.client.Client;
import de.wladhd.client.ClientManager;
import de.wladhd.logs.Log;
import de.wladhd.logs.LogType;
public class DateServer {
private SSLServerSocket server;
private boolean running = true;
private String keyStore = "D:/Wlad/Programmierung/Zertifikat/CA/CertificateAuthority.pfx";
private String keyStorePassword = "...";
private String keyStoreType = "PKCS12";
private String trustStore = "D:/Wlad/Programmierung/Zertifikat/CA/CertificateAuthority.pfx";
private String trustStorePassword = "...";
private String trustStoreType = "PKCS12";
public void execute() throws Exception {
//System.setProperty("javax.net.debug","all");
System.setProperty("javax.net.ssl.keyStoreType", keyStoreType);
System.setProperty("javax.net.ssl.keyStore", keyStore);
System.setProperty("javax.net.ssl.keyStorePassword", keyStorePassword);
System.setProperty("javax.net.ssl.trustStoreType", trustStoreType);
System.setProperty("javax.net.ssl.trustStore", trustStore);
System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
//System.setProperty("javax.net.ssl.trustStore", "de.wladhd.server.Trusting");
SSLServerSocketFactory serverFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
if(serverFactory == null) {
new Log("Error occured... Server Factory == null!", LogType.ERROR);
return;
}
server = (SSLServerSocket) serverFactory.createServerSocket(9090);
running = true;
new Log("Server now running on query: " + server.getInetAddress().getHostAddress() + ":" + server.getLocalPort(), LogType.INFO);
while (running) {
try {
if(server.isClosed()) {
return;
}
new Log("Client connecting...", LogType.DEBUG);
final Socket rawsocket = server.accept();
if(!(rawsocket instanceof SSLSocket)) {
new Log("Client isnt an instance of SSLSocket!", LogType.DEBUG);
return;
}
final SSLSocket socket = (SSLSocket) rawsocket;
try {
socket.startHandshake();
} catch (Exception ex) {
}
new Log("Client - Connected: " + socket.isConnected(), LogType.DEBUG);
new Log("Client - Protocol: " + socket.getSession().getProtocol(), LogType.DEBUG);
new Log("Client - Session valid: " + socket.getSession().isValid(), LogType.DEBUG);
new Log("Client - CipherSuite: " + socket.getSession().getCipherSuite(), LogType.DEBUG);
new Log("Client - NeedClientAuth: " + socket.getNeedClientAuth(), LogType.DEBUG);
new Log("Client - WantClientAuth: " + socket.getWantClientAuth(), LogType.DEBUG);
Client c = new Client(socket);
//socket.getHandshakeSession() returns null and peer not authenticated exception...
} catch (Exception ex) {
ex.printStackTrace();
continue;
}
}
}
public void disconnect() throws Exception {
new Log("Server disconnecting...", LogType.INFO);
setRunning(false);
ClientManager.getInstance().disconnectClients();
if(server != null) {
server.close();
}
new Log("Server successfully disconnected!", LogType.INFO);
}
public boolean isRunning() {
return running;
}
public void setRunning(boolean state) {
running = state;
}
}
필요한 것이 있으면 알려주세요 ...
RemoteCertificateNameMismatch 정책 오류는 누락 된 로컬 인증서와 관련이 없습니다. 이 오류는 수신 된 서버 인증서의 SAN (주체 대체 이름) 또는 SAN이없는 경우 수신 된 서버 인증서의 주체 이름의 일반 이름이 연결하는 호스트 이름과 일치하지 않음을 나타냅니다. 이 두 위치 중 하나에서 인증서의 호스트 이름이 표시되지 않을 것으로 예상되는 경우이 오류를 무시할 수 있습니다.
파일에서 인증서를로드하고 Windows 개인 키 저장소에이 인증서에 해당하는 개인 키가 없기 때문에 로컬 인증서가 없다고 생각합니다.
MMC를 사용하여 인증서와 개인 키 (예 : 인증서와 개인 키가 모두있는 PFX 파일에서)를 로컬 컴퓨터 개인 인증서 저장소로 가져온 다음 .NET 인증서 저장소 API를 사용하여 여기에서 해당 인증서 를로드 합니다 . 만큼 당신이 (당신이 경우 개인 키에 액세스 할 수 있습니다로 당신이 PFX를 수입하는 Windows 사용자입니다)를, 당신이 클라이언트 인증서로 연결할 수 있어야합니다.
코드에서 파일에서 인증서를 읽는 대신 다음과 같이 인증서 저장소에서로드합니다.
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
try
{
X509Certificate2Collection collection = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
return TakeFirstCertificate(collection);
}
finally
{
store.Close();
}
다른 지문을 사용하여 찾을 수 있습니다. 이것은 단지 예일뿐입니다. 이것이 SelectLocalCertificate가 반환하는 것입니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다