このドキュメントの内容
PowerShell を使って開発用の自己証明書を生成し、gRPC の通信を SSL 化します。
自己証明書の生成
次のドキュメントを参考にしました。
【Qiita】Windows 10 Pro の PowerShell で自己署名証明書(SHA-2)を作成する
【Qiita】KubernetesのIngressで使うSSL自己署名証明書をPowerShellで作る
【Qiita】RSA鍵、証明書のファイルフォーマットについて
次のスクリプトを PowerShell で実行すると
- localhost.pfx
- localhost_key_cer.pem
- localhost_cer.pem
の三つのファイルが生成されます。
gRPC の SslServerCredentials では PEM 形式(文字列)の証明書と秘密鍵が必要になるのですが、残念ながら PowerShell を使って PEM 形式(文字列)のファイルを生成する方法はわかりませんでした。結局、OpenSSL を使って PEM ファイルを生成することにしました。
以下のスクリプトを使ってサーバー用の証明書ファイルを生成します。スクリプト冒頭のホスト名($dns)に開発マシンのホスト名を指定してください。
# ホスト名
$dns = "localhost"
# 有効期限
$after = (Get-Date).AddYears(100)
# 生成するファイルパス
$pfxfile = "localhost.pfx"
$keycerfile = "localhost_key_cer.pem"
$cerfile = "localhost_cer.pem"
# パスワード
$password = "password"
# 証明書ストアの「個人」に証明書を作成する
$my = "cert:\CurrentUser\My"
$cert = New-SelfSignedCertificate -DnsName $dns -CertStoreLocation $my -NotAfter $after
# pfxファイルをエクスポートする
$sspwd = ConvertTo-SecureString -String $password -Force -AsPlainText
Export-PfxCertificate -Cert $cert -FilePath $pfxfile -Password $sspwd
# 証明書ストア「個人」から証明書を削除する
Remove-Item -Path ($cert.PSPath)
# OpenSSLを使用してpfxファイルから証明書と秘密鍵を含むpemファイルを生成する
# パスワードが要求される
Start-Process -FilePath openssl -ArgumentList "pkcs12 -in", $pfxfile, "-nodes -out", $keycerfile -Wait
# OpenSSLを使用して証明書だけを別のpemファイルとして取り出す
Start-Process -FilePath openssl -ArgumentList "x509 -in", $keycerfile, " -out", $cerfile -Wait
gRPC の通信を SSL 化する
サーバ側では、 localhost_key_cer.pem に証明書と秘密鍵が両方含まれているので、これだけでCA証明書・サーバ証明書・サーバ秘密鍵を兼用できます。
string cacert = System.IO.File.ReadAllText("<localhost_key_cer.pemのパス>"); // サーバ証明書に署名した証明書として、自己署名なのでサーバ証明書を指定
string servercert = cacert; // localhost_key_cer.pem にはサーバ証明書が含まれる
string serverkey = cacert; // localhost_key_cer.pem にはサーバ秘密鍵が含まれる
// Credentials を生成
// 今回は SSL 化だけなのでクライアント証明書は要求しない
KeyCertificatePair keypair = new KeyCertificatePair(servercert, serverkey);
SslServerCredentials credentials = new SslServerCredentials(new[] { keypair }, cacert, SslClientCertificateRequestType.DontRequest);
// Credentials を指定してポートを生成
ServerPort port = new ServerPort("localhost", 55001, credentials);
クライアント側では、サーバ側の秘密鍵を持ってくるわけにいかないので、証明書部分を取り出した localhost_cer.pem をCA証明書としました。
string cacert = System.IO.File.ReadAllText("<localhost_cer.pemのパス>"); // サーバ側ポートで指定したcacertの証明書と同じもの
// Credentials を生成
SslCredentials credentials = new SslCredentials(cacert);
// Credentials を指定してチャネルを生成
Channel channel = new Channel("localhost", 55001, credentials)
参考)X.509 証明書での利用
X509Certificate2 クラスのコンストラクタには証明書ファイルのパスを受け取るものがあります。このとき、pfx, cer ファイルを使用できます。cer ファイルはバイナリ形式、文字列形式のどちらでもよいです。
var cert = new X509Certificate2("pfxファイルのパス", "パスワード");
var cert = new X509Certificate2("cerファイルのパス");