openssl
Too hot so ..
梅雨入り前の数日、糞みたいに暑かった。これはかなわんと、Debian機を持って涼しい所に避難。そこでWebサーフィンするも、日本語の設定をしてなかったものだから、やるはめに。
ググル様のなすがままに、流行り系を入れてみた。エンジンがMozcで、インプットメソッドがFcitxって事になるのかな。
英語、日本語の切り替えは、元から定義されてた、Ctl-SPC に加えて、Win-SPCも登録しておいた。
調子に乗って、emacsも設定する。
を取り入れてみた。切り替えは、Ctl-\ になってた。本来なら、init.elをごにょごにょしてみたいんだけど、面倒なのデフォなまま。まあ、余り入力する事もないから、そのままでいいか。
QRコード
近頃、やけにQRコードが眼につく。毎日見せられるNHKの、コロナ特設サイトとか、某パンの梱包袋に掲載されてる、懸賞応募とか、etc,etc …
また、某国では、公共機関に入場する時、スマホをかざして、連絡方法をQRコードにより登録するとか。そういう時代なんですかねぇ。日本もまねして、図書館に行く時はスマホを持参してくださいってならないかねぇ。ああ、図書カードがデフォだから、大丈夫か。
まて、飛行機の搭乗券は、便利さのため、スマホでQRコードだけで運用します、とかなったら、原始人はどうしたらいいの?
時代に乗り遅れないように、少し調査。スマホは無いけど、3Gのガラケー携帯はかろうじて持ってるぞ。これでQRコードのオペレーションって出来るの?
カメラのメニューに、バーコードとQRコードの読み取りがあった。ああ良かった。試してみるか。
役場から以前に貰ってきておいた、マイナンバーカードのお勧めパンフレットにQRコードが付いてた。読んでみると、URLに変換されて、いざ飛ぼうとすると、認証に失敗しましただと。
ガラケーには理解出来ない、認証方式が使われているのかな?
コロナが落ち着いたら、役場で申請してこよう。総務のおばちゃんが、口座登録を義務化するなんて、ほざいているよ。それがプチ気になるけど。
openssl(本家)
で、ふと、前からやってる鍵の元締めのopensslに触ってみたくなった。debian機では
debian:~$ openssl version OpenSSL 1.0.2l 25 May 2017
なんか、ちょっと古いみたい。新しいのを取り寄せて、入れてみた。コンパイルに5分。インストールはマニュアルが膨大だったので、随分と時間がかかった。
debian:~$ /usr/local/openssl/1_1_1g/bin/openssl version OpenSSL 1.1.1g 21 Apr 2020 (Library: OpenSSL 1.1.1d 10 Sep 2019)
1.1系では一番新しいっぽい。次は1.3系とか。OpenBSDの人達と連携するのかな?
openssl(分家)
山のようにコマンドが用意されてて、容易に踏み込めないので、ガイドを探してみた。 opensslコマンドの使い方
s_client
httpsなサーバーに接続して、鍵の扱いを調べてくれるとな。マイナンバーカードの情報を探ってみるか。
ob$ openssl s_client -connect www.kojinbango-card.go.jp:443 CONNECTED(00000003) depth=2 C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA verify return:1 depth=1 C = BE, O = GlobalSign nv-sa, CN = GlobalSign CloudSSL CA - SHA256 - G3 verify return:1 depth=0 C = US, ST = Delaware, L = Dover, O = Incapsula Inc, CN = incapsula.com verify return:1 write W BLOCK --- Certificate chain 0 s:/C=US/ST=Delaware/L=Dover/O=Incapsula Inc/CN=incapsula.com i:/C=BE/O=GlobalSign nv-sa/CN=GlobalSign CloudSSL CA - SHA256 - G3 1 s:/C=BE/O=GlobalSign nv-sa/CN=GlobalSign CloudSSL CA - SHA256 - G3 i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA --- : SSL handshake has read 3193 bytes and written 343 bytes --- New, TLSv1/SSLv3, Cipher is AEAD-AES128-GCM-SHA256 Server public key is 2048 bit Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.3 Cipher : AEAD-AES128-GCM-SHA256 Session-ID: Session-ID-ctx: Master-Key: Start Time: 1591850037 Timeout : 7200 (sec) Verify return code: 0 (ok)
メッセージのやり取りは、下記のようにしてモニターするとな。
ob$ openssl s_client -connect www.kojinbango-card.go.jp:443 -msg |grep -e ">>>" -e "<<<" >>> TLS 1.3 Handshake [length 0118], ClientHello <<< TLS 1.3 Handshake [length 007a], ServerHello <<< TLS 1.3 Handshake [length 0006], EncryptedExtensions <<< TLS 1.3 Handshake [length 0a6a], Certificate depth=2 C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA verify return:1 depth=1 C = BE, O = GlobalSign nv-sa, CN = GlobalSign CloudSSL CA - SHA256 - G3 verify return:1 depth=0 C = US, ST = Delaware, L = Dover, O = Incapsula Inc, CN = incapsula.com verify return:1 <<< TLS 1.3 Handshake [length 0108], CertificateVerify <<< TLS 1.3 Handshake [length 0024], Finished >>> TLS 1.3 Handshake [length 0024], Finished
いきなり TLS 1.3 が出て来るじゃ、10年以上前のガラケーが太刀打ち出来る訳はない。携帯屋のおねーちゃんが言ってたように、早く機種変更しろよ。
ciphers
これが、多分、共通鍵暗号の種類
ob$ openssl list-cipher-commands| cut -f1 -d'-' | sort | uniq aes base64 bf camellia cast cast5 chacha des des3 desx idea rc2 rc4 sm4
それらを、公開鍵暗号、署名と組み合わせると、実際にWebで使えるものになるって事かな。
ob$ openssl ciphers -v AEAD-AES256-GCM-SHA384 TLSv1.3 Kx=TLSv1.3 Au=TLSv1.3 Enc=AESGCM(256) Mac=AEAD ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384 AES256-GCM-SHA384 TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(256) Mac=AEAD
-V を付けるともっと詳しく表示され
-V Verbose. List ciphers with cipher suite code in hex format, cipher name, and a complete description of protocol version, key exchange, authentication, encryption, and mac algorithms.
と言う事らしい。
public-key-algorithms
公開鍵にも色々有りまして、、、
ob$ openssl list-public-key-algorithms Name: OpenSSL RSA method Type: Builtin Algorithm OID: rsaEncryption PEM string: RSA Name: rsa Type: Alias to rsaEncryption Name: OpenSSL EC algorithm Type: Builtin Algorithm OID: id-ecPublicKey PEM string: EC
ここで出ているPEMってのは、バイナリー値をBase64エンコードした(一応)文字列になったやつ。これに対してDERは、バイナリー値で表現されるファイル形式。 こういうのが、いきなり出て来るので、面喰らうぞ。
ssl(3)
に、Web用の秘密鍵とサーバー証明書の作り方が解説されてた。OpenBSDは、ここまで親切なドキュメントが用意されてるんですねぇ。いち早くこれを見つけられなかったオイラーはアホだな。
RSAの特許まみれの話とか、それをかいくぐる為にECDSAを用意したとか、歴史の話が出て来て興味深い。
SSL/TLS session
まあ、大変な手間をかけて、安全対策をやってるのね、ぐらいが分かれば宜しいかなと。
毎度お馴染みのウィキペディアに、Transport Layer Security が解説されてて、よく網羅されてた(上から目線って、どうよ)。RSAによる鍵交換は、サツに踏み込まれて秘密鍵を押収されるとヤバいんで、余りお勧めしない。 ディフィー・ヘルマン鍵共有 が、例のスノーデン事件後に、注目されるようになった。スパイな世界の話である。
lib{ssl,tls}
折角なので、OpenBSDでopensslのコードを鑑賞してみる。
ob$ cd /usr/src/usr.bin/openssl/ ob$ ls Makefile dh.c nseq.c progs.h smime.c apps.c dhparam.c ocsp.c rand.c speed.c apps.h dsa.c openssl.1 req.c spkac.c apps_posix.c dsaparam.c openssl.c rsa.c testdsa.h asn1pars.c ec.c passwd.c rsautl.c testrsa.h ca.c ecparam.c pkcs12.c s_apps.h timeouts.h certhash.c enc.c pkcs7.c s_cb.c ts.c ciphers.c errstr.c pkcs8.c s_client.c verify.c cms.c gendh.c pkey.c s_server.c version.c crl.c gendsa.c pkeyparam.c s_socket.c x509.c crl2p7.c genpkey.c pkeyutl.c s_time.c dgst.c genrsa.c prime.c sess_id.c
これって、openssl xxx の、xxx相当なのね。いわゆるサブコマンドって奴だ。本家の方では、appsって表現してたけどね。
ソースを紐解いてみると、冒頭にこれでもかと言う程、クレジットが表示されている。大変な世界なんですなあ。
で、例によってgdbにかけられるようにコンパイルしてってやってもいいんだけど、毎回代わり映えしないとクレームになりそうなので、切口をちょいと変えてみる。
これらのアプリが共通に使っているライブラリィーに、眼をつけた(目の付け所が違うのだ)。 /usr/src/lib/の下をざっと見すると、当たり前のように、libcryptoが有る。中身は各種暗号とかハッシュアルゴリズムのソース類の詰め合わせセット。
これには、うんざりしたんで、他の部分に眼を凝らすと、libsslが有る。大分ソースが詰め合わせてある。ssl2とかに混じってtls13とかも置いてあった。そうか、通信規約を表現してるんだな。doc/standards.txt に、参照したRFCが山のように列挙されてた。日々進化中。
libssl/に並置して、興味深いlibtls/も有った。 tls_server.c
とか tls_client.c
なんてのが置いてあるって事は、tlsなサーバーを作る為の材料なんだな。
どんな所で、このlibtlsが使われているのかな? 直ぐに思い付くのは、あれだ。
ob$ ldd /usr/sbin/httpd | awk '{print $7}' Name /usr/sbin/httpd /usr/lib/libevent.so.4.1 /usr/lib/libtls.so.20.1 /usr/lib/libssl.so.48.1 /usr/lib/libcrypto.so.46.1 /usr/lib/libutil.so.15.0 /usr/lib/libc.so.96.0 /usr/libexec/ld.so
前回やったOpenBSDに備え付けのWebサーバーの成分表をlddで取り出して、ぐたぐた並べられているフィールドから、ライブラリィー名だけを、拾い出してみた。暗号とsslとtlsが合有されてて、思った通りだ。
早速ご対面するか。まて、httpdって見るには巨大過ぎないか。openssl(1)のSEE ALSOにnc(1)が列挙されたぞ。 成分表を調べてみたら、httpdと同じように使われていた。
How to use nc
ネットワーク界のアイドルじゃなくて、アーミーナイフと称されるアプリである。まずは、Webクライアント(要するブラウザーね)の真似。
ob$ printf "GET / HTTP/1.0\r\n\r\n" | nc localhost 80 HTTP/1.0 200 OK Connection: close :
これぐらいなら、他のやつでも、簡単に出来るぞ。
Open a TCP connection to port 443 of www.example.com, and negotiate TLS with any supported TLS protocol version and "compat" ciphers: $ nc -cv -T protocols=all -T ciphers=compat www.example.com 443
こんな例が載ってた。
ob$ printf "GET / HTTP/1.0\r\n\r\n" | > nc -cv -T protocols=all -T ciphers=compat localhost 443 Connection to localhost (127.0.0.1) 443 port [tcp/https] succeeded! nc: tls handshake failed (certificate verification failed: self signed certificate)
オレオレ証明書は駄目よと、nc がブレーキをかけてくれたぞ。そんじゃ、オイラーがご厄介になってるSAKURAさんの所へ繋いでみるか。
ob$ printf "GET / HTTP/1.0\r\n\r\n" | > nc -cv -T protocols=all -T ciphers=compat hamesspam.sakura.ne.jp 443 Connection to hamesspam.sakura.ne.jp (219.94.129.63) 443 port [tcp/https] succeeded! TLS handshake negotiated TLSv1.2/ECDHE-RSA-AES256-GCM-SHA384 with host hamesspam.sakura.ne.jp Peer name: hamesspam.sakura.ne.jp Subject: /OU=Domain Control Validated/CN=*.sakura.ne.jp Issuer: /C=JP/ST=Tokyo/L=Chiyoda-ku/O=Gehirn Inc./CN=Gehirn Managed Certification Authority - RSA DV Valid From: Thu Jun 28 09:00:00 2018 Valid Until: Sun Jun 28 08:59:59 2020 Cert Hash: SHA256:d80293e0830658934cad245ea6aa8690dbdd6008c9127575ef214559691a9232 OCSP URL: http://ocsp.usertrust.com HTTP/1.1 403 Forbidden Server: nginx Date: Thu, 11 Jun 2020 23:27:07 GMT Content-Type: text/html Connection: close <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html lang="ja"> :
今度は大丈夫。ちゃんと証明書の確認が出来た。もうすぐ証明書の有効期限が満了になるけど、ちゃんと更新してね。
detect fail point
オレオレ証明書なサーバーに接続した時、どんな風にブレーキがかかるか調べてみる。エラーになった時に、errxを使って表示してるようなので、それを頼りにbreakさせる。
(gdb) b errx Function "errx" not defined. Breakpoint 1 (errx) pending. (gdb) r -cv -T protocols=all -T ciphers=compat localhost 443 Starting program: /tmp/nc/a.out -cv -T protocols=all -T ciphers=compat localhost 443 Breakpoint 1, _libc_errx (eval=1, fmt=0x44e8e256026 "tls handshake failed (%s)") at /usr/src/lib/libc/gen/errx.c:39 39 va_start(ap, fmt); gdb) bt #0 _libc_errx (eval=1, fmt=0xb1f0aab9026 "tls handshake failed (%s)") at /usr/src/lib/libc/gen/errx.c:39 #1 0x00000b1f0aabfaa7 in tls_setup_client (tls_ctx=0xb216eae0a00, s=3, host=0x7f7fffff2f45 "localhost") at netcat.c:834 #2 0x00000b1f0aabd9be in main (argc=2, argv=0x7f7fffff2de8) at netcat.c:740
巨大なmainから呼ばれている。
if (timeout_tls(s, tls_ctx, tls_handshake) == -1) { if ((errstr = tls_error(tls_ctx)) == NULL) errstr = strerror(errno); => errx(1, "tls handshake failed (%s)", errstr); }
こんな所で、検出された。大事な内容は tls_ctx
に入っている。
(gdb) p *tls_ctx $4 = { config = 0x95ce9343a00, keypair = 0x95c1cec6d80, error = { msg = 0x95c67637d80 "certificate verification failed: self signed certificate", num = -1, tls = 1 }, flags = 1, state = 10, servername = 0x95c93860710 "localhost", socket = -1, :
この構造体のどれかが関数アドレスを保持してて、ハンドシェイクを実行してるはず。詳しくはソース嫁。
強引にやる
ob$ printf "GET / HTTP/1.0\r\n\r\n" | nc -cv -T protocols=all -T ciphers=compat -T noverify -T noname localhost 443 Connection to localhost (127.0.0.1) 443 port [tcp/https] succeeded! TLS handshake negotiated TLSv1.2/ECDHE-RSA-AES256-GCM-SHA384 with host localhost Peer name: localhost Subject: /C=JP/ST=Tokyo/L=edo/O=Yama/OU=devel/CN=ob.local.jp/emailAddress=hoge@openbsd.org Issuer: /C=JP/ST=Tokyo/L=edo/O=Yama/OU=devel/CN=ob.local.jp/emailAddress=hoge@openbsd.org Valid From: Mon Jun 8 09:01:17 2020 Valid Until: Tue Jun 8 09:01:17 2021 Cert Hash: SHA256:660197768a246a858731cdd46f0ec5c451afedd17305eba1da764ba140c37861 HTTP/1.0 200 OK Connection: close Content-Length: 33 Content-Type: text/html Date: Fri, 12 Jun 2020 07:51:09 GMT Last-Modified: Sun, 07 Jun 2020 21:05:02 GMT Server: OpenBSD httpd Hello, world. from OpenBSD httpd
証明書をチェックしない、名前も無視って言う、オレオレな人には嬉しいオプションを付けてあげたら、認証書を表示しつつ、Webにアクセス出来たよ(さっぱり嬉しくは無いけど)。
curl
普通なら、この辺でPythonどうよってなるんだろうけど、へそ曲がりなんで、カールおじさんです。
ob$ curl https://localhost curl: (60) SSL certificate problem: self signed certificate More details here: https://curl.haxx.se/docs/sslcerts.html curl failed to verify the legitimacy of the server and therefore could not establish a secure connection to it. To learn more about this situation and how to fix it, please visit the web page mentioned above.
やっぱりブレーキがかかりましたねぇ。
ob$ curl -k https://localhost Hello, world. from OpenBSD httpd
でも、ちゃんと抜け道は用意されてるよ。これって、オレオレほう助罪にならないかなあ?
gnutls
opensslと同族っぽいのにGNU系の、gnutlsが有る。訳も分からずに試してみた。
ob$ gnutls-cli -p 443 localhost Processed 135 CA certificate(s). Resolving 'localhost:443'... Connecting to '127.0.0.1:443'... - Certificate type: X.509 - Got a certificate list of 1 certificates. - Certificate[0] info : - Status: The certificate is NOT trusted. The certificate issuer is unknown. The name in the certificate does not match the expected. *** PKI verification of server certificate failed... *** Fatal error: Error in the certificate.