2011-03-07 2 views
2

나는 이것의 작동 구현을하고 있지만 그것이 안전한지 확인하고자합니다. 목표는 SSLStream을 사용하고 특정 RSA 키로 서명 된 서버의 SSL 인증서 만 수락하는 것입니다. 여기 특정 공개 키로 서명 된 인증서 만 받아들이도록 SslStream에 요청하기

내 접속 코드 :

 var client = new TcpClient("server_address", port_number); 
     var sslStream = new SslStream(client.GetStream(), false, 
      new RemoteCertificateValidationCallback(ValidateServerCertificate), null); 
     sslStream.AuthenticateAsClient("SpeechGrid"); 

그리고 여기 내 ValidateServerCertificate의 구현 : 때문에 내가하지 않도록해야 할 X509Chain 객체의 풍요 로움의

private static bool ValidateServerCertificate(object sender, X509Certificate certificate, 
      X509Chain chain, SslPolicyErrors sslPolicyErrors) { 

     // Only accept our specific key pair 
     foreach (var cert in chain.ChainElements) { 
      if (cert.Certificate.GetPublicKeyString() == k_prodPublicKey) { 
       return true; 
      } 
     } 

     return false; 
    } 

X509ChainStatusFlags.NotSignatureValid 등과 같은 항목을 확인해야합니다.

예를 들어, 공격자가 내 술집에서 서명하도록 요청할 수 있습니까? lic 키, 잘못된 서명을 보내면 .NET에서 모든 플래그를 확인한다고 가정하기 때문에이 공격이 작동합니다.

감사합니다.

업데이트 : 좋아, 지금까지 나는 원래 foreach 위에 다음 검사를하기로 결정했습니다. 이것은 다소 응용 프로그램에 따라 다릅니다. 예를 들어 내가 당신 같은 인증서가 신뢰할 수없는 만료 된 경우, 또는 같은 추가 오류에 대해 sslPolicyErrors 매개 변수를 확인하실 수 있습니다

 foreach (var status in chain.ChainStatus) { 
      switch (status.Status) { 
       case X509ChainStatusFlags.Cyclic: 
       case X509ChainStatusFlags.NotSignatureValid: 
       case X509ChainStatusFlags.PartialChain: 
        return false; 
      } 
     } 
+0

** public ** 키는 일반 대중을 위해 사용됩니다 ... 당신 (개인 키를 가진 사람)만이 해독 할 수 있습니다 암호화 된 메시지. 데이터가 실제로 제 3 자의 데이터인지 확인하려면 공개 키를 가져옵니다 (키를 사용하여 데이터를 암호화합니다). –

답변

0

등 NotTimeValid을 확인 할 만료 된 인증서를 원하는 경우. 모든 것이 정상이면 SslPolicyErrors.None을 반환해야합니다. 공용 키에서 개인 키를 파생시키는 것은 계산 상으로 불가능합니다. 따라서 동일한 키 쌍을 만들고 서명하는 다른 사람에 대해 걱정할 필요가 없습니다.

+0

제 경우에는 "System.Net.Security.SslPolicyErrors.RemoteCertificateNameMismatch | System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors"로 SslPolicyErrors를 표시합니다. 체인 상태에서 UntrustedRoot가 표시됩니다. 내 인증서는 CA에 의해 서명되지 않습니다. UntrustedRoot가 유일한 체인 상태인지 확인해야합니까? –

+2

RemoteCertificateNameMismatch는 클라이언트가 인증서의 내용과 일치하지 않는 호스트 이름에 연결하고 있음을 의미합니다. "www.myapp.com"에 연결하는 경우 인증서의 이름도 일치해야합니다. 인증서가 클라이언트 컴퓨터의 인증서 저장소에 신뢰할 수있는 루트 CA로 설치되지 않았기 때문에 얻을 수있는 untrustedRoot 오류입니다. 저장소에 해당 CA를 설치하거나 공개 키에 대한 또 다른 명시적인 확인이있을 때 해당 오류를 무시할 수 있습니다. –

1

질문에 대한 업데이트에서 추가 한 수표의 논리를 취소합니다.

foreach (thing that I can think of that might be wrong) 
return false; 

if (public key matches regardless of other policy errors) 
return true; 

... 내가 대신 아직 허용 잘못 될 일을 찾아, 그리고 다른 정책 오류를 거부 할 것입니다 :

if (policy errors) 
{ 
foreach (error that is acceptable: remote name mismatch, untrusted root, etc.) 
    policy errors -= that particular error 
} 

if (any policy errors left) 
return false; 
else if (public key matches) 
return true; 
else 
return false; 

뭔가 대신 잘못 될 일을 찾고 그 외 모든 것을 수용 (테스트하지 않았거나 컴파일하지 않았습니다.) :

if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) == SslPolicyErrors.RemoteCertificateNameMismatch) 
{ 
    sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateNameMismatch; 
} 

if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) == SslPolicyErrors.RemoteCertificateChainErrors) 
{ 
    var otherFlagsFound = 
     from i in chain.ChainStatus 
     where (i.Status & ~X509ChainStatusFlags.UntrustedRoot) != X509ChainStatusFlags.NoError 
     select i; 

    if (otherFlagsFound.Count() == 0) 
    { 
     sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateChainErrors; 
    } 
} 
관련 문제