ぺんぎんさんのおうち

日記です。たまに日記じゃないこともあります。

Golangで暗号化されたsocket通信をする

はじめに

Chacha20-Poly1305の解説と実装 の子記事になります.
上記事ではChacha20-Poly1305をPythonで再実装しましたが, 本記事ではGolangを用いて再再実装しました.

RFCs

  • ChaCha20 and Poly1305 for IETF Protocols
    RFC7539
  • HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
    RFC5869
  • The Transport Layer Security (TLS) Protocol Version 1.3
    RFC8446
test vector
  • HKDFのPRK, OKMの導出
  • chacha20_encrypt
  • poly1305_mac, key_gen
  • chacha20_AEAD

のtest vectorを通してあるので実装としては信用して利用できます. 書き方については信用できませんが.

コードの解説がまだ書ききれていませんが一旦投稿します(ごめんなさい)


やったこと

基本的にはクライアントとサーバー間でデータを送受信してるだけです.
クライアントからの最初の送信(いわゆるClient Hello1)とそれに対するサーバーからの返答(いわゆるServer Hello)で共有鍵を作り, 以降の通信は鍵を使ってChacha20で暗号化しています. 今回は省きましたが, "Chacha20-Poly1305"を実装しているのでもちろんPoly1305を使ってメッセージ認証ができます.

socket通信はこちら(【Golang】Socket通信するプログラムを書いてみた)を参考にしました.

big.Intの扱い方やbig.Int to Bytes (Bytes to big.Int), SHA256やHMAC2など調べることが多くて大変でした.


以下の動画のように動作します.

上がserver, 下がclientになっています.
共有鍵がちゃんと同じであること, サーバーから送られてきた(暗号化されている)メッセージをクライアント側でちゃんと復号して"this is a message"と表示されていることが確認できました.


コードの解説

chacha20に使用するkey, nonceはTLS1.3であればHKDFで導出しますが, まだそこまで実装ができていないので今回は雑にDiffie-Hellmannで共有した鍵の先頭のバイトを使っています.


サーバー


クライアント


おわりに

最終的にはハンドシェイクも実装してTLS1.3サーバとして動くようにしたいと思います.


最終目標



1: 実際にはClient Helloしていない
2: 今回は出てこない HKDFに使う