ステップ1:自己署名証明書を生成する:
- DougCookによって投稿されたCertificate.csクラスをダウンロードしました
このコードを使用して、.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つの警告がありました。私はそれらすべてを提案された代替品と交換しました。
Server Program.csファイルのこの行を、手順2の行に置き換えました。
X509Certificate cert = getServerCert();
Client Program.csファイルで、serverName = yourhostname.comを設定していることを確認してください(証明書の名前と一致していることを確認してください)。
- Client Program.csでは、sslPolicyErrorsにRemoteCertificateChainErrorsが含まれているため、CertificateValidationCallback関数が失敗します。もう少し深く掘り下げると、これは、証明書に署名した発行機関が信頼されたルートではないためです。
- ユーザーに証明書をルートストアなどにインポートさせたくないので、特別なケースを作成し、certificate.GetPublicKeyString()がファイルにある公開鍵と等しいことを確認します。そのサーバー用。一致する場合は、その関数からTrueを返します。それはうまくいくようです。
ステップ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が1つの証明書だけでなく、証明書のコレクションを取得する方法に注意してください。したがって、次のようにLocalCertificateSelectionCallbackを追加する必要があります(この場合、クライアント証明書は1つしかないため、コレクションの最初の証明書を返すだけです)。
static X509Certificate CertificateSelectionCallback(object sender,
string targetHost,
X509CertificateCollection localCertificates,
X509Certificate remoteCertificate,
string[] acceptableIssuers)
{
return localCertificates[0];
}