피어에서 피어 인증을 위해 SSL 및 SSLStream을 사용하십니까?
-
22-08-2019 - |
문제
통신을 위해 TCP/IP 소켓을 사용하는 다양한 프로세스간에 안전한 커뮤니케이션을 제공해야합니다. 인증과 암호화를 원합니다. 휠을 재발 명하지 않고 SSL과 SSLStream 클래스 및 자체 서명 된 인증서를 사용하고 싶습니다. 내가하고 싶은 것은 로컬 응용 프로그램의 알려진 사본에 대해 원격 프로세스의 인증서를 검증하는 것입니다. (인증서를 수동으로 복사 할 계획이므로 인증 기관이 필요하지 않습니다).
이를 위해 응용 프로그램이 처음 실행될 때 새 인증을 자동으로 생성 할 수 있기를 원합니다. makecert.exe 외에도 마찬가지입니다 이 링크 자체 서명 된 인증서를 자동으로 생성하는 방법을 보여 주므로 시작입니다.
SSLStream의 authenticateasserver 및 authenticateasclient 방법을 보았습니다. 검증을 위해 콜백을 제공 할 수 있으므로 가능해 보입니다. 그러나 이제 나는 그것의 세부 사항에 들어서서, 나는 이것을 할 수 있다고 생각하지 않습니다.
내가 올바른 방향으로 가고 있습니까? 더 나은 대안이 있습니까? 누구든지 이전에 이와 같은 일을 한 사람이 있습니까 (기본적으로 클라이언트 서버보다는 피어 투 피어 SSL)?
해결책
1 단계: 자체 서명 된 인증서 생성 :
- 나는 그것을 다운로드했다 인증서 .CS 클래스 Doug Cook에 의해 게시되었습니다
이 코드를 사용하여 .pfx 인증서 파일을 생성했습니다.
byte[] c = Certificate.CreateSelfSignCertificatePfx( "CN=yourhostname.com", //host name DateTime.Parse("2000-01-01"), //not valid before DateTime.Parse("2010-01-01"), //not valid after "mypassword"); //password to encrypt key file using (BinaryWriter binWriter = new BinaryWriter( File.Open(@"testcert.pfx", FileMode.Create))) { binWriter.Write(c); }
2 단계: 인증서로드
X509Certificate cert = new X509Certificate2(
@"testcert.pfx",
"mypassword");
3 단계 : : 그것을 합친다
- 나는 그것을 기반으로한다 이 매우 간단한 sslstream 예제
- SSLProtocoltype 열거에 대한 컴파일 타임 오류가 발생합니다. sslprotocoltype.default에서 sslprotocols.default로 변경하십시오
- 더 이상 사용되지 않은 기능에 대한 3 가지 경고가있었습니다. 나는 그들 모두를 제안 된 교체품으로 교체했습니다.
서버 프로그램 에서이 줄을 교체했습니다 .CS 파일은 2 단계에서 라인으로 대체했습니다.
x509certificate cert = getervercert ();
Client Program.cs 파일에서 ServerName = YourHostName.com을 설정하고 인증서의 이름과 일치해야합니다)
- client program.cs에서 sslpolicyerrors에는 remotecertificatechainerrors가 포함되어 있기 때문에 CertificateValidationCallback 함수가 실패합니다. 당신이 조금 더 깊이 파고 들면, 이것은 인증서에 서명 한 발행 기관이 신뢰할 수있는 루트가 아니기 때문입니다.
- 사용자 가져 오기 인증서를 루트 스토어 등으로 가져 오지 않으려 고하지 않으므로 특별한 경우를 만들었고 해당 증명서를 확인합니다. getPublicKeyString ()은 파일에있는 공개 키와 같습니다. 그 서버의 경우. 그것이 일치하면, 나는 그 기능에서 true를 반환합니다. 그것은 효과가있는 것 같습니다.
Step 4: 클라이언트 인증
내 클라이언트가 인증하는 방법은 다음과 같습니다 (서버와 약간 다릅니다).
TcpClient client = new TcpClient();
client.Connect(hostName, port);
SslStream sslStream = new SslStream(client.GetStream(), false,
new RemoteCertificateValidationCallback(CertificateValidationCallback),
new LocalCertificateSelectionCallback(CertificateSelectionCallback));
bool authenticationPassed = true;
try
{
string serverName = System.Environment.MachineName;
X509Certificate cert = GetServerCert(SERVER_CERT_FILENAME, SERVER_CERT_PASSWORD);
X509CertificateCollection certs = new X509CertificateCollection();
certs.Add(cert);
sslStream.AuthenticateAsClient(
serverName,
certs,
SslProtocols.Default,
false); // check cert revokation
}
catch (AuthenticationException)
{
authenticationPassed = false;
}
if (authenticationPassed)
{
//do stuff
}
CertificateValidationCallback은 서버 케이스와 동일하지만 AuthenticateAsclient가 하나의 인증서가 아니라 인증서 모음을 어떻게 취하는지 주목하십시오. 따라서 LocalCertificatesElectionCallback을 추가해야합니다 (이 경우 클라이언트 인증서가 하나만 있으므로 컬렉션에서 첫 번째 클라이언트를 반환합니다).
static X509Certificate CertificateSelectionCallback(object sender,
string targetHost,
X509CertificateCollection localCertificates,
X509Certificate remoteCertificate,
string[] acceptableIssuers)
{
return localCertificates[0];
}
다른 팁
이 예제 샘플 비동기 SSLStream 클라이언트/서버 구현을 볼 수 있습니다.http://blogs.msdn.com/joncole/archive/2007/06/13/sample-asynchronous-sslstream-mient-server-meplementation.aspx
인증서가 올바르게 생성되지 않으면 예외를 얻을 수 있습니다. 서버 모드 SSL은 관련 개인 키와 함께 인증서를 사용해야합니다.
기본 인증서 예
makecert -sr localmachine -ss my -n cn = test -sky exchange -sk 123456
또는
외부 파일로
makecert -sr localmachine -ss my -n cn = test -sky exchange -sk 123456 c : test.cer
인증서 생성 도구 (makecert.exe)
http://msdn.microsoft.com/en-us/library/bfsktky3%28vs.80%29.aspx
당신이 제안하는 것은 인증서를 생성하기 위해 콜백이 호출 될 때까지 기다리는 것처럼 들린다는 점을 제외하고는 나에게 괜찮습니다. 나는 그것이 날아갈 것이라고 생각하지 않습니다. Afaik, 호출 할 때 유효한 인증서를 제공해야합니다. AuthenticateAsX
.
그러나이 클래스는 우선적입니다. 따라서 이론적으로, 인증서를 생성 해야하는지 확인하기 위해 첫 번째 검사를받은 파생 클래스를 만들 수 있습니다. 필요한 경우 생성 한 다음 부모를 호출 할 수 있습니다. AuthenticateAsX
방법.