0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

C# SslStream で簡易HTTPSサーバを立てる

Posted at

目的

OpenSSLを用いて秘密鍵付きの自己署名証明書を作り、C# の SslStream を用いて簡易HTTPSサーバを立てます。

この記事の目的はとりあえず適当なHTTPSサーバを立てることであり、セキュリティは考慮していません。
例えば、クラウドサービス上で秘密鍵を作る手順がありますが、実際に運用する場合は秘密鍵はローカル (サーバを動かすコンピュータ上) で生成するべきです。

証明書の作成

OpenSSLを用い、以下の手順で秘密鍵付きの自己署名証明書を作ります。

  1. 秘密鍵を作る
  2. 署名要求ファイルを作る
  3. 証明書を作る
  4. 秘密鍵と証明書を合体する

ブラウザでプログラミング・実行ができる「オンライン実行環境」| paiza.IO
の Bash で以下のコードを実行することで、秘密鍵付きの証明書を作成できます。

openssl genrsa -out server.key 2048
openssl req -utf8 -new -key server.key -out server.csr -subj "/C=JP/ST=Test-State/L=Test-City/O=Test/OU=/CN=localhost:8080"
openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt
openssl pkcs12 -export -password pass:password -inkey server.key -in server.crt -out certificate.pfx

zip -q certificate.zip server.* certificate.pfx
base64 certificate.zip

最初の4行で上に挙げた手順をそれぞれ実行し、最後の2行で作成したデータをBase64エンコードしたZIP形式で取り出します。
取り出したBase64データは、例えばCyberChefでデコードし、ファイル化することができます。

From Base64 - CyberChef

デコードしたZIPファイルを展開すると、以下のファイルが得られます。

  • server.key : 秘密鍵
  • server.csr : 署名要求データ
  • server.crt : 証明書
  • certificate.pfx : 秘密鍵付きの証明書

簡易HTTPSサーバを立てる

C# で SslStream を用うと、TLS通信を行うことができます。

まず、以下のように X509Certificate2 クラスを用いて作成した秘密鍵付きの証明書を読み込みます。
第1引数に秘密鍵付きの証明書のファイル名、第2引数に秘密鍵付きの証明書を作る時に設定したパスワードを指定します。

X509Certificate2 cert = new X509Certificate2("certificate.pfx", "password");

2 が付かない X509Certificate を用いた場合、
後述の AuthenticateAsServer で以下のエラーが出てしまいました。

System.NotSupportedException: サーバー モード SSL は関連付けられた秘密キーを使用した証明書を使用しなければなりません。

通常のTCPサーバを立て、接続されたら、以下のように SslStream を作成し、サーバとして初期化します。

SslStream stream = new SslStream(client.GetStream(), false);
stream.AuthenticateAsServer(cert, false, SslProtocols.Tls12 | SslProtocols.Tls13, false);

TLSのバージョンを明示的に指定しないと、TLSv1になってしまい、Google Chromeで接続できませんでした。

以降、この stream を通じてクライアントとの通信ができます。

以下がコード全体です。

SslServerTest.cs
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;

namespace Test
{
	public class SslServerTest
	{
		public static void Main(string[] args)
		{
			X509Certificate2 cert = new X509Certificate2("certificate.pfx", "password");
			TcpListener listener = new TcpListener(IPAddress.Any, 8080);
			listener.Start();
			for(;;)
			{
				Console.WriteLine("listening");
				TcpClient client = listener.AcceptTcpClient();
				Console.WriteLine("accepted");
				SslStream stream = new SslStream(client.GetStream(), false);
				try
				{
					stream.AuthenticateAsServer(cert, false, SslProtocols.Tls12 | SslProtocols.Tls13, false);
					StreamReader sr = new StreamReader(stream);
					string line;
					while ((line = sr.ReadLine()) != null && !line.Equals(""))
					{
						Console.WriteLine("received: " + line);
					}
					StreamWriter sw = new StreamWriter(stream);
					sw.Write("HTTP/1.0 200 OK\r\n");
					sw.Write("Conenction: close\r\n");
					sw.Write("Content-Type: text/plain\r\n");
					sw.Write("Content-Length: 5\r\n");
					sw.Write("\r\n");
					sw.Write("hello");
					sw.Flush();
				}
				catch (Exception e)
				{
					Console.WriteLine(e);
				}
				finally
				{
					stream.Close();
				}
			}
		}
	}
}

このコードを、最近のWindowsに標準付属しているC#コンパイラでコンパイルします。

"C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc" SslServerTest.cs

コンパイルした結果の実行ファイルを実行すると、Google Chrome で接続することができました。

Google Chrome で接続した様子

参考サイト

証明書の作成

簡易HTTPSサーバを立てる

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?