SVX日記

2004|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|

2024-01-06(Sat) 改めて「Maverick」に移行

  Gmailの「簡易HTML形式」を使い続けたいということで、自作のメーラ「Maverick」を実際に使い出したところ、これが思いのほか具合がいい。ただし「メールの削除機能がない」のが困る。ということで、モソモソと追加してみた。上にDeleteボタン、左にチェックボックスというUI。

  画像の説明

  だいぶ大きなプログラムなのだが、本体に手を入れずとも割と簡単に機能追加ができてしまう。かなり前に書いたコードなんで、既に自分のコードではないほどなのだが、割とキレいに実装してあるな。我ながら悪くない。

  メールの削除ができるようになってしばらくすると、もはやGmailのタブを開かなくなってしまっている自分に気づく。想像以上に移行できてしまった感じだ。

  まぁ、Gmailがクソとまでは言わんが、UIというものは、足すことがあっても、変えることがあってはいけない、と思う。やはり、どうにでもできる自作は至高だな。


2024-01-08(Mon) 続・Maveでデジタル署名付きメールを検証する

  先日、改めて「Maverick」に移行したのだが、早速新しいメールを読み出さなくなってしまっていた。OSサポートという仕事柄、何か障害が起こると、瞬時に頭の中に思い当たる点がリストアップされてしまう性分である。そして案の定、リフレッシュトークンの期限切れであった。アクセストークンの有効期限は1時間だが、リフレッシュトークンの有効期限は7日間らしい。むー、そういうのヤメようよ。

  結局、自分で先日の記事を読み返し、リフレッシュトークンを再発行して対処したが、週に一度くらいなら我慢するかなぁ。それとも、もう少し手順を簡略化できる方法もありそうなので、来週までにそれをやってみるかな。また、面白そうな課題が出てきたな。他に取り組みたい課題もあるのだけれどな。ウキウキ。

  そういう一方で、また気になる点を見つけてしまった。署名付きメールの署名が検証できなかった(署名が不正である)という「?」マークが出ている。どちらも銀行のメールだ。

.. 300 住信SBIネット銀  Fri, 29 Dec 20:01   9K w? +出金のお知らせ
.. 650 service@smbctb.c Sat, 14 Oct 17:18  11K .? +SMBC信託銀行 カードご利用のお知らせ

  先日、Maveでデジタル署名付きメールを検証する機能はガッチリと作ったはずなのだが、何がおかしいのだろうか。検証をやりなおす手順を実行してみると「送信元が署名者と一致していない」というエラーが出た。

Digital Signature is NOT Valid. reason=[Sender does not match Signer.]

  まったくしょーがないなー、などと呟きつつ原因調査に取り組み始める自分である。ウキウキ。早速、署名の検証部分の処理を抜き出して現象を再現してみる。

require 'openssl'
mail = 'xxxxxxxx.eml'
pkcs7 = OpenSSL::PKCS7.read_smime(open(mail).read)
pkcs7.certificates.each {|cert|
    print(cert.to_text)
    puts('-' * 80)
    cert.subject.to_a.each {|name|
        name[0] == 'emailAddress' and p ['emailAddress', name[1]]
    }
    puts('=' * 80)
}

  以下のような結果が得られた。

$ ./smime_dec.rb
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            3f:07:9c:34:1b:03:0c:e0:bd:b0:42:f1:93:43:b2:a4:17:30:b1:50
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=JP, O=Cybertrust Japan Co., Ltd., CN=Cybertrust Japan SureMail CA G4
        Validity
            Not Before: May 15 07:55:52 2023 GMT
            Not After : Jun  9 07:55:16 2024 GMT
        Subject: C=JP, ST=Tokyo, L=Minato-ku, O=SBI Sumishin Net Bank, Ltd.,, OU=System Department02, CN=SBI Sumishin Net Bank post_master
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
        X509v3 extensions:
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Certificate Policies: 
                Policy: 1.2.392.200081.1.24.1
                  CPS: https://www.cybertrust.ne.jp/ssl/repository/index.html
            X509v3 Subject Alternative Name: 
                email:post_master@netbk.co.jp
            Authority Information Access: 
                CA Issuers - URI:http://crl.cybertrust.ne.jp/SureMail/smcag4/smcag4.crt
--------------------------------------------------------------------------------
================================================================================

  やはり、メールアドレスが検出されない。と、思ったら「SubjectAlternative Name」というところに入っているようだ。

            X509v3 Subject Alternative Name: 
                email:post_master@netbk.co.jp

  SBI銀行だけでなく、SMBC銀行も同様だった。

            X509v3 Subject Alternative Name: 
                email:service@smbctb.co.jp

  オレオレ証明書は「SubjectのemailAddress」の側にだけ入っている。

        Subject: C=JP, ST=Aichi, L=Nagoya, O=ITLine Inc., CN=Furutanian/emailAddress=furutanian@itline.jp

  が、会社から支給されている証明書は両方に入っているので、どっちも間違いというわけではなさそうだ。

        Subject: C=JP, ST=Tokyo, L=Minato, O=xxx, OU=xxx/emailAddress=xxxxxx@xxx.xxx
            X509v3 Subject Alternative Name: 
                email:xxxxxx@xxx.xxx, othername:<unsupported>

  よくわからんが、両方に対応しときゃいいだろう。やや雑だが以下のコードを追加した。

            begin
                pkcs7 = OpenSSL::PKCS7.read_smime(File.open(path).read)
                addrs = []; pkcs7.certificates.each {|cert|
+                   cert.extensions.each {|ext|
+                       ext.to_h['oid'] == 'subjectAltName' and ext.to_h['value'] =~ /mail:([^,]+)/ and addrs << $1
+                   }
                    cert.subject.to_a.each {|name|
                        name[0] == 'emailAddress' and addrs << name[1]
                    }

  改めて、検証をやりなおす手順を実行してみると「Message is Signed.」と表示され、「?」マークが「C」マークに変わった。

.. 300 住信SBIネット銀  Fri, 29 Dec 20:01   9K wC +出金のお知らせ
.. 650 service@smbctb.c Sat, 14 Oct 17:18  11K .C +SMBC信託銀行 カードご利用のお知らせ

  と、いうわけで、今回の盆栽の剪定作業はこれにて完了である。


2024-01-12(Fri) 深谷ドライブ

  なんつうか、自分にとってロードスターはペットのようなもので、一緒に遊んで楽しいが、相手をするのが面倒だと思う時もないわけではない。実際にはマシンなので、年単位で放っておかなければ問題はないのだけれど、それでも週末に2連続で乗らないと気が咎めてしまうのだ。さらに時々はどーんと遠出しなければ「ならない」と思えてしまう。別の言い方をすればある種の呪いなのかもしれない。とはいえ、走り出してしまえばそれは全編に渡って楽しい時間なのだけれど。

  で、冬なのにもかかわらず遠出したくなり、目的地にレトロゲーセンを選んでしまう。だいぶ前に行ったことがあるのだが、自分にとって定期的なレトロゲニウム補給は必須なのである。事前にライブカメラでチェックしていたものの心配だった雪は皆無で、布チェーンは所持していたものの、使わずにノーマルタイヤでスコンと到着してしまった。350kmチョイを9時間だ。

  早速、ロボットへ。おー、ひさびさ、と思ったが、節電のために都度電源を切る運用となっていて、イマイチ心が盛り上がらず。暗い店内で都度インストカードをノゾき込まないと、何のゲームなのかわからない。料理の写真がなくて「ウマそっ!」ってならない、字面だけのメニューを渡された気分。しゃーないんだろうけど。

  とりあえずグラディウス。1面の噴火で事故って2ミスしたが、サクッと1周クリア。師匠に倣って6面ボス以外は全編レーザーだ。と、グラミネラルが満たされたところで、腹が減ったので隣のアリオに飯を食いに行く。なんでもバナナジャングルという店があると聞いて食いに行きたくなってしまったのだ。あまりバナナは好きではないのだが、削りチーズ満載のホットドッグと併せ、なかなか美味しくいただけた。

  画像の説明

  印象的だったのは、食器の返却時。女の子店員に「美味しかったですか?」と聞かれたこと。いま「ごちそうさまでした」と言ったやんか、とは思ったが、その言葉が形骸化してるのも確かなので、笑顔で「美味しかったです」と答える。いや、そういう意識はすごく大事だと思う。例えバイトであれ報酬や上司ではなく、仕事は「客を向いて」するべきなのだ。気分がいい。

  ロボットに戻って、ガントレット(ウィザードでソーサラまで)、19XX(2ボス)、エリア88(7後半まで)、ロストワールド(バリアボールまで)。実にオッサンの魂百までっぽい。後ふたつは何度もクリアしてるのだがさすがに忘れてるな。ロストワールドで鉄クサくなった手を嗅いで悔しさを紛らせる。

  画像の説明

  次いで、遊んだ記憶のない、赤ずきんx2、なめんなよ、SNKバトルフィールドあたりをプレイ。赤ずきんはなかなか秀逸なアイデアなのに、作りが粗いな。ヘンな配置にハマると、連続して死んでしまう。

  画像の説明

  最後、ドラゴンスピリット。調子が悪いとダメなのだが、調子がイイ。オマケに全編タマゴ祭、スモール祭、ワイド祭。2,3ミスでエンディングへ。フフン、どんなもんや。最後、外のガチャガチャでエアロシティ筐体を引く。できればテーブル筐体のがよかったが、これはこれで。

  画像の説明

  まだ準備中のようだったが、ギャラクシアン3があった。メタルホークとスターブレードも。ナムコの超新星爆発的な作品群。どれも大好物だ。稼働を開始したらまた来たいな。

  画像の説明

  コンビニで買い物して、格安のホテルに戻って、風呂に入ってノンビリしながら、グラIIをプレイするのを忘れたことに気づく。あー、もー、と、思いつつ、そういうのを忘れてしまうのも、また今度でいいかと考えられるのも、実にオッサン的な思考である。


2024-01-13(Sat) 秩父ドライブ

  九四ドライブ東北ドライブの時の習慣で、宿の朝食は開始早々に摂り、冷たい空気の中を走り出す、ということになっているので、今回もそうするのであった。6時半過ぎに朝食、7時半前に出発である。

  帰りは行きのように塩尻経由ではなく、秩父を抜ける。最初の経由地は長瀞。「MOTER MAN 秩父鉄道」の「長瀞だけにトロトロ走っております」とか「イジらないで、長瀞さん」とかで、妙に心が惹かれる地名なんだよな。「岩畳」という案内が気になってそれに向かってクルマを走らせる。朝早いので道はスカスカだ。「岩畳」とは道路ではなくて、河岸が石のカタマリになっているという意味なんだな。寝覚の床みたいな場所だ。近くまで行ったもののどこも有料駐車場なので降りずに雰囲気だけ楽しんで後にする。そのうち改めて訪れたい場所だな。

  秩父の町を抜けて先へ。以前から「三峰口」って不思議な終端駅だな、と思っていたのだが、神社への観光用の駅だったのだな。雰囲気のいい山岳道路を進み、国道140号を南ルートへ向かう。今回のメーンイベントは故駒ヶ滝隧道なのだ。手前の駐車場に駐めて周囲を散策する。隧道の入り口は塞がれていて、道路はごく普通に先に伸びているが、GoogleMapで事前にチェックしていた自分にはその道路がなかった頃の景色が重なって見える。ちょっと横から見ればだいぶ無理して作られた道路だということが見て取れる。うーん、この隧道は通ってみたかったなぁ。2013年に閉鎖じゃ、通るチャンスはなかったけれど。

  画像の説明 画像の説明

  さらに旧道を抜けて雁坂トンネルへ向かう。すごく立派なトンネルなのにほとんど交通量がない。青函トンネルを思い出させるな。手前のパーキングエリアでも「実は雁坂トンネルはお得!使って!」的なチラシを見かけたが、ETCも使えないし、なんか負け戦的なヤケクソを感じさせる。通ってみると何てことはない普通のトンネル。いや、線形が直線過ぎて半分くらいからもう出口の光が見えてしまうのは珍しいかもな。

  雁坂トンネルを抜けたところにある「道の駅みとみ」で小休止。まだ11時前だったので、先に進んでから飯にしようかと思ったが、6時過ぎに食ってるんだからちょっと早めでも悪くない。「ほうとう」を出す店もあるし、空いてるからここで食ってしまうか、と早い昼飯にすることにした。

  ここは「ほうとう」に「宝刀」という字を当てているが、これは諸説あるうちのひとつらしい。カッコイイけどカッコよすぎるなぁw。とか考えているとブツがきた。デカい。具も多い。が、普段から燃費の悪い生活をしている胃袋持ちなのでペロリである。特段の感動もなかったが、ウマかったな。

  その後は甲府を抜けるのだが新しいバイパスができていてスルリと通過。山道を楽しみつつ、富士の裾野を抜けていく。敢えて富士宮から狭めの峠道を抜けると、ストンと由比に着く。別に観光地でも何でもないのだが、由比も好きな場所なんだよな。

  残りの何度も通った道なので「大崩海岸」を通ってみようと思っていたのだが、経路のチェック不足もあり気づくと通り過ぎてしまっていた。1号って複数あるんだよな。まぁ、時間の都合もあったし、次回で。

  蒲郡ICは工事中のはず、と思って蒲郡西ICから乗ったのだが、既に工事は終わっていたようだ。19時前に帰宅。総走行距離770km。あー、今回も楽しかった。

  画像の説明


2024-01-16(Tue) マイナンバーカードで遊んでみる

  カミさんがふるさと納税の手続きのため、マイナンバーカードをスマホに読ませてアレコレしてほしいといわれ、パスワードを失念していることに気づいた。確か短いのと長いののふたつがあったような気がするのだが。

  正直に「パスワードを覚えていない」というと「そうなると手続きが面倒なのよねぇ」とのこと。フムン。いや、たぶんアレとアレなんだが、長い方が特に自信がない。なんとかならんかと思ってググると、短い方がわかるなら、コンビニで長い方を再設定することができるらしい。短い方は割と自信がある。試してみるか。で、無事に再設定することができ、ふるさと納税の手続きも完了した。よっしゃよっしゃ。

  画像の説明

  と、そこでフトだいぶ前に買ったカードリーダが手元にあることに気づいた。もしかすると、これで読んだりできるのかしらん。早速、やってみた。

$ pkcs15-tool --dump
Using reader with a card: NTT Communications Corp. SCR3310-NTTCom USB SmartCard Reader [Vendor Interface] 00 00
PKCS#15 Card [JPKI]:
	Version        : 0
	Serial number  : 00000000
	Manufacturer ID: JPKI
	Flags          : 
 
PIN [User Authentication PIN]
	Object Flags   : [0x12], modifiable
	ID             : 01
	Flags          : [0x12], local, initialized
	Length         : min_len:4, max_len:4, stored_len:0
	Pad char       : 0x00
	Reference      : 1 (0x01)
	Type           : ascii-numeric
	Tries left     : 3
 
PIN [Digital Signature PIN]
	Object Flags   : [0x12], modifiable
	ID             : 02
	Flags          : [0x12], local, initialized
	Length         : min_len:6, max_len:16, stored_len:0
	Pad char       : 0x00
	Reference      : 2 (0x02)
	Type           : ascii-numeric
	Tries left     : 5
 
Private RSA Key [User Authentication Key]
	Object Flags   : [0x1], private
	Usage          : [0x4], sign
	Access Flags   : [0x1D], sensitive, alwaysSensitive, neverExtract, local
	ModLength      : 2048
	Key ref        : 1 (0x1)
	Native         : yes
	Auth ID        : 01
	ID             : 01
	MD:guid        : c5a0a252-9d2d-eb60-fec0-41b4fbd722a2
 
Private RSA Key [Digital Signature Key]
	Object Flags   : [0x1], private
	Usage          : [0x204], sign, nonRepudiation
	Access Flags   : [0x1D], sensitive, alwaysSensitive, neverExtract, local
	ModLength      : 2048
	Key ref        : 2 (0x2)
	Native         : yes
	Auth ID        : 02
	ID             : 02
	MD:guid        : e1bc1dae-59f1-16ab-b43f-9dafbb2acc9b
 
Public RSA Key [User Authentication Public Key]
	Object Flags   : [0x0]
	Usage          : [0x0]
	Access Flags   : [0x2], extract
	Key ref        : 1 (0x1)
	Native         : yes
	Path           : 000a
	ID             : 01
 
Public RSA Key [Digital Signature Public Key]
	Object Flags   : [0x0]
	Usage          : [0x0]
	Access Flags   : [0x2], extract
	Key ref        : 2 (0x2)
	Native         : yes
	Path           : 0001
	ID             : 02
 
X.509 Certificate [User Authentication Certificate]
	Object Flags   : [0x0]
	Authority      : no
	Path           : 000a
	ID             : 01
	Encoded serial : xx xx xxxxxxxx
 
X.509 Certificate [Digital Signature Certificate]
	Object Flags   : [0x1], private
	Authority      : no
	Path           : 0001
	ID             : 02
 
X.509 Certificate [User Authentication Certificate CA]
	Object Flags   : [0x0]
	Authority      : yes
	Path           : 000b
	ID             : 03
	Encoded serial : 02 04 0133C349
 
X.509 Certificate [Digital Signature Certificate CA]
	Object Flags   : [0x0]
	Authority      : yes
	Path           : 0002
	ID             : 04
	Encoded serial : 02 04 0132C4AB

  えらくゾロソロと出てくるが、わからんようなわかるようなで面白い。特に冒頭の「PIN」「Tries left」なんて、どう見てもパスワードの失敗許容回数だ。当たり前だがカード内で管理されてるんだな。なかなか高機能なカードであるといえよう。

  そのほか「Private RSA Key」「Public RSA Key」「X.509 Certificate」なんてのも、普段からSSLをガチャガチャしているオイラには見慣れた概念だ。証明書の内容を読み出してみる。

$ pkcs15-tool --read-certificate 1
-----BEGIN CERTIFICATE-----
XXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxx
xxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXX
 :
XXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxx
xxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXX
-----END CERTIFICATE-----

  完全にpem形式である。opensslで読めそうだ。ちな、2番目の証明書だけはPINコードでロックされているので、以下の指定が必要になる。指定すると入力を促されるので、入力してやると出力される。

$ pkcs15-tool --read-certificate 2 --auth-id 2 --verify-pin
Please enter PIN [Digital Signature PIN]: 
-----BEGIN CERTIFICATE-----
XXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxx
xxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXX
 :
XXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxx
xxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXXxxXX
-----END CERTIFICATE-----

  自分の環境では公開鍵は読み出せなかった。PINコードが正しくてもダメ。

$ pkcs15-tool --read-public-key 1
Public key enumeration failed: Required ASN.1 object not found
$ pkcs15-tool --read-public-key 2 --auth-id 1 --verify-pin
Please enter PIN [User Authentication PIN]: 
Public key enumeration failed: Security status not satisfied

  さらに秘密鍵にもなると読み出すコマンドすらない。そもそも「neverextract」だから読み出せなくて正しそう。カードに暗号文を渡し、カード内で(秘密鍵を使って)復号して平文を返してもらう、という形なんだろう。実に高機能なカードである。いくらすんだろね、これ。

  以上をまとめると以下のようになる。

カード情報 JPKI
(PIN1) PIN ユーザ認証PIN 4桁 残3回
(PIN2) PIN デジタル署名PIN 6-16桁 残5回
(秘密鍵1) 秘密RSA鍵 ユーザ認証鍵 署名用 機密 2048桁
 →読み出し不可
 →カード内で復号させる、PIN1で保護されている
(秘密鍵2) 秘密RSA鍵 デジタル署名鍵 署名用 非否認 機密 2048桁
 →読み出し不可
 →カード内で復号させる、PIN2で保護されている
(公開鍵1) 公開RSA鍵 ユーザ認証鍵
 →読み出し失敗
(公開鍵2) 公開RSA鍵 デジタル署名鍵
 →PIN2で保護されている、読み出し失敗
(証明書1) X.509 証明書 ユーザ認証証明書
(証明書2) X.509 証明書 デジタル署名証明書
 →PIN2で保護されている
(証明書3) X.509 証明書 ユーザ認証認証局証明書
(証明書4) X.509 証明書 デジタル署名認証局証明書

  pem形式の証明書が読み出せたので、デコードして可視化してみる。

require 'openssl'
cert = OpenSSL::X509::Certificate.new($stdin.read)
puts(cert.to_text)
$ ./pem_dec.rb < UserAuthenticationCertificateCA.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 20169545 (0x133c349)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=JP, O=JPKI, OU=JPKI for user authentication, OU=Japan Agency for Local Authority Information Systems
        Validity
            Not Before: Sep 14 23:41:59 2019 GMT
            Not After : Sep 14 14:59:59 2029 GMT
        Subject: C=JP, O=JPKI, OU=JPKI for user authentication, OU=Japan Agency for Local Authority Information Systems
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Certificate Sign, CRL Sign
            X509v3 Subject Alternative Name: 
                DirName:/C=JP/O=\xE5\x85\xAC\xE7\x9A\x84\xE5\x80\x8B\xE4\xBA\xBA\xE8\xAA\x8D\xE8\xA8\xBC\xE3\x82\xB5\xE3\x83\xBC\xE3\x83\x93\xE3\x82\xB9
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 CRL Distribution Points: 
                Full Name:
                  DirName:C = JP, O = JPKI, OU = JPKI for user authentication, OU = Japan Agency for Local Authority Information Systems
            X509v3 Subject Key Identifier: 
                8C:D5:58:6A:89:14:85:E5:59:37:9B:7E:29:D4:10:CF:D2:8B:35:93

  上記は「(証明書3) X.509 証明書 ユーザ認証認証局証明書」の抜粋だ。いわば、日本国の(オレオレ)証明書であり、日本国民なら共通の情報であるから、内容を公開しても問題ない。

  公開するとマズいのは、(私自身の)個人情報を含んでいる「(証明書1) X.509証明書 ユーザ認証証明書」「(証明書2) X.509 証明書 デジタル署名証明書」の方だが、前者は(おそらく)マイナンバーの番号だけで、直接的な情報は後者に含まれているはずだ。

  んが、上記のスクリプトで後者を読み出してみても、たいした内容が出てこない。せいぜい、以下の「区」くらいで、これは証明書の発行元の情報である。

            X509v3 CRL Distribution Points: 
                Full Name:
                  DirName:C = JP, O = JPKI, OU = JPKI for digital signature, OU = CRL Distribution Points, OU = Aichi-ken, CN = Nagoya-shi-Xxxx-ku CRLDP

  クサイのは以下。デコードができていないっぽい。そういえば、「othername:<unsupported>」って、先日の自分に会社から支給されている証明書でも出てたな。その時は深く考えなかったけれど。

            X509v3 Subject Alternative Name: 
                othername:<unsupported>, othername:<unsupported>, othername:<unsupported>, othername:<unsupported>, othername:<unsupported>, othername:<unsupported>

  で、調べていくと、これは「ASN.1」という形式らしく、まさにソコに情報が入っているようなのだが、opensslのtext出力ではその中身までデコードしてくれないようなのである。

  そんならRubyのOpenSSL::ASN1クラスを使ってデコードすりゃええか……と、思ったらその中身がムチャクチャに複雑で、ちっとも意図した結果が得られない。結局、どうにかこうにか再帰を使って出力に成功したが、実際にその中身はムチャクチャに複雑だった。これは再帰なしで書いたら日が暮れるな。文字列なのに、それがデコードできる場合と、単なる文字列の場合があるって、どういう構造なんだよ。

def asn_decode(value, n)
    puts('%sdecode[%s]' % [(indent = '  ') * n, value.class])
    if(value.is_a?(Array))
        value.each {|v|
            asn_decode(v, n + 1)
        }
    else
        begin
            asn = OpenSSL::ASN1.decode(value)
            asn_decode(asn.value, n + 1)
        rescue
            puts('%smay be string[%s]' % [indent * n, value])
        end 
    end
end
 
cert.extensions.each {|ext|
    puts('*%s' % ext.to_h['oid'])
    asn_decode(ext, 1)
}

  「(証明書4) X.509 証明書 デジタル署名認証局証明書」をデコードすると、以下の結果が得られた(抜粋)。

$ ./pem_dec.rb < UserAuthenticationCertificateCA.pem
*subjectAltName
  decode[OpenSSL::X509::Extension]
    decode[Array]
      decode[OpenSSL::ASN1::ObjectId]
        decode[String]
        may be string[subjectAltName]
      decode[OpenSSL::ASN1::OctetString]
        decode[String]
          decode[Array]
            decode[OpenSSL::ASN1::ASN1Data]
              decode[Array]
                decode[OpenSSL::ASN1::Sequence]
                  decode[Array]
                    decode[OpenSSL::ASN1::Set]
                      decode[Array]
                        decode[OpenSSL::ASN1::Sequence]
                          decode[Array]
                            decode[OpenSSL::ASN1::ObjectId]
                              decode[String]
                              may be string[C]
                            decode[OpenSSL::ASN1::PrintableString]
                              decode[String]
                              may be string[JP]
                    decode[OpenSSL::ASN1::Set]
                      decode[Array]
                        decode[OpenSSL::ASN1::Sequence]
                          decode[Array]
                            decode[OpenSSL::ASN1::ObjectId]
                              decode[String]
                              may be string[O]
                            decode[OpenSSL::ASN1::UTF8String]
                              decode[String]
                              may be string[公的個人認証サービス]
                    decode[OpenSSL::ASN1::Set]
                      decode[Array]
                        decode[OpenSSL::ASN1::Sequence]
                          decode[Array]
                            decode[OpenSSL::ASN1::ObjectId]
                              decode[String]
                              may be string[OU]
                            decode[OpenSSL::ASN1::UTF8String]
                              decode[String]
                              may be string[公的個人認証サービス署名用]
                    decode[OpenSSL::ASN1::Set]
                      decode[Array]
                        decode[OpenSSL::ASN1::Sequence]
                          decode[Array]
                            decode[OpenSSL::ASN1::ObjectId]
                              decode[String]
                              may be string[OU]
                            decode[OpenSSL::ASN1::UTF8String]
                              decode[String]
                              may be string[地方公共団体情報システム機構]

  さらに抜粋するとこう。

$ ./pem_dec.rb < DigitalSignatureCertificateCA.pem | grep may
        may be string[subjectAltName]
                              may be string[C]
                              may be string[JP]
                              may be string[O]
                              may be string[公的個人認証サービス]
                              may be string[OU]
                              may be string[公的個人認証サービス署名用]
                              may be string[OU]
                              may be string[地方公共団体情報システム機構]

  そしてクライマックスだ。「(証明書2) X.509 証明書 デジタル署名証明書」をデコードすると、以下の結果が得られた(抜粋)。

$ ./pem_dec.rb < DigitalSignatureCertificate.pem | grep may
        may be string[subjectAltName]
                  may be string[1.2.392.200149.8.5.5.1]
                      may be string[山田 太郎]
                  may be string[1.2.392.200149.8.5.5.4]
                      may be string[319700101]
                  may be string[1.2.392.200149.8.5.5.3]
                      may be string[1]
                  may be string[1.2.392.200149.8.5.5.5]
                      may be string[愛知県名古屋市中区栄3丁目]
                  may be string[1.2.392.200149.8.5.5.2]
                      may be string[00000]
                  may be string[1.2.392.200149.8.5.5.6]
                      may be string[00000000000000000000]

  当然だが上記は改ざんしている。んが、モロに自分の個人情報が入っていた。「デジタル署名」をするという行為は、上記の情報を提供するということであり、それが意図に反して行われないようにするためのものが、長い方のPINコードなのであった。逆に言えば、長い方のPINコードの要求に応じた場合は「自分の個人情報が提供される」ということだ。

  しかし、だ。「名前、生年月日、性別、住所」なんて、役所で気にもせずに一番に書面に書き出す内容である。たかが、それだけの情報なのである。マイナンバー制度に関してはマスゴミの意味不明のFUDキャンペーンで、すっかりネガティブイメージが付いてしまっているが、フタを開けてみればそれだけのこと。ボールペンで書くか、PINコードを打つかの違いしかないといえよう。仮に落として紛失したところで、運転免許証と同程度の危険性しかない。

  ちょっと前にマイナンバーカードを普及するため「マイナポイント事業」というのがあった。調べると「2020年9月に始まった第1弾では2979億円、今年6月から本格実施した第2弾では1兆8134億円を計上した」とあり、例によってマスゴミはこの予算について批判をしていたが、それは「無知なオマエラが無駄に騒ぎ立ててFUDしたから必要になった予算」ではないのか。マイナンバーで事務処理が円滑になれば役所の運営費も減るんだよ。しかも恒久的に。少しくらいは考えてモノを言えっつーの。オマエラが騒ぐとアホな国民の方々はその通りに踊っちゃうんだからさ。

  別に自分は常に日本国万歳ではないが、ことこの件については、マイナンバーカードの返納とか、日本国運営の方々に於かれては、本当にアホな国民の方々をお持ちのようで心から同情いたします。草々。

  あー、そうだ。とりあえずホテルの宿帳を書くの毎度メンドいんで、マイナンバーカードのタッチだけで済むようにしてほしいです。はい。


2024-01-20(Sat) 45歳くらいから60歳くらい向けのゲームセンターへ

 グラIIをプレイするのを忘れた」ということで、久々に近所の「天野ゲーム博物館」へ行くことにした。数年ぶりじゃないかな。

  画像の説明

  世はすっかりコロナから明けているが、なんとなくソコは明けていないような予感がして、念のためマスクを持っていったら案の定だった。まぁ、私有の施設におじゃまするワケだし、館長はかなりのご高齢なので、そこに文句をつけても仕方ないだろう。

  入店するとかなりの人数だ。流行っているのは喜ばしいこと。と、一番に目に入ったのは「サイバリオン」。これ、結構やったんだよな。と、電源を入れてプレイしてみる……が、最初のチョイスとしては最悪だった。トラックボールの操作性には何の問題もないのだが、このゲームのプレイにはだいぶ体力が要る。マスクをしていると、息が苦しくてかなわないw。それの影響かはわからんがタコ被弾を頻発。とはいえ、アーマックス、ザイゾログ、ガットノイザーの順で撃破し、チャプター4の中盤くらいまで。まぁ、久々ならそんなもんや。

  「源平討魔伝」。タコ斬り頻発で剣力が上がらない。伊予の弁慶をギリギリ倒すも、その後に飛んできた矢で頓死。ブランクって怖い。

  プレイする台を吟味しているとそれだけで満足してしまうので、今日は目に入ったらすぐコインを入れることにする。「モンスターランド」。調子はいいが、クラーケン倒す前に落ちてしまうわ、ジャイアントコングをスルーしてしまうわ、タコ忘れまくり。スフィンクスの趣味を聞き忘れて運否天賦でカラオケ選んでクリアしたのはよかったものの、丘に上がって「いいながめだ」ってセリフで笛をもらうのを忘れたことに気づくw。ラウンド8で溶岩に落ちてしまい出られず頓死。

  「奇々怪々」。あまり得意じゃないんだが、いきなり豆頭でタコミス。シーン4の途中まで。まぁ、当時もそんなもんだったが。

  「ダブルドラゴン」。髪をつかんで頭を膝蹴りする方法を忘れてしまい、ポイポイ投げてしまいイラッとしつつ、途中から肘打ちに頼り始めてしまい単調なプレイに。MISSION3で壊れた橋の飛び越しが心配だな、と思ったら案の定タコってドボンして終了。アレ、理不尽に難しいんだよな。

  とかやってると店内に放送が。「手を消毒しない人はゲームに触っちゃダメですよ」。館長の声だ。続いて「ここに子供向けのゲームはありません。あるのは45歳くらいから60歳くらい向けのゲームです」って、ちょっとウケるw。まぁその通りなんだがw。相変わらずクドいキャラだなぁ。と、そのへんで一度外出して飯を食いに行く。うどんをカキ込んでザバス飲んですぐ戻る。

  「クレイジークライマー」。珍しくバルーンにつかまることができた。バーベルや鉄骨を調子よく避けまくるも、3面でハズレ看板の落下を待ってたら窓が閉まって落下。まぁ、運もクレクマのうち、というしな。

  せっかくなのでVIPルームの中のダライアスをプレイさせてもらおうと、館長に声をかける。会員名簿をめくって登録が確認できたら、入室カードを貸してもらえるのだ。ふと気になって自分の登録日付を確認したら、ギリギリこの日記にエントリがあった。20年前じゃん。その頃に既にすっかりレトロゲームだったよなぁ。

  「ダライアス」。スクリーンの状態がよすぎる。継ぎ目の調整もほぼ完璧。オリジナルのコンパネってスゴくヘタりやすいのだが、ボタンも直されてキレイだ。しかし、初っ端からタコ被弾を連発。今回は常にどれもそんな調子だな。自身の加齢の影響なんだろうか。それが積もってAゾーンの道中で頓死。ヤベェ。ここは2番目くらいの安パイコースを選ぼう。Hゾーンのピラニアでアームを剥がされるも、その後は安定。A-B-D-H-M-R-X。Xゾーンではタコ被弾なしにタコ退治。ホッとする。

  画像の説明

  「怒IKARI」。ちょっと前までスプライトが欠ける症状が出ていたが、今回はそれはなく、代わりに一部の音が欠ける症状が。ちょうどクレジット音の「ドブーン」が欠けたのでコイン呑まれたかと思ったわ。最初の関所の先でタコったら、連続して死んでしまう。あまり上手くはないが、普段は海くらいには行くんだがなぁ。いまさらながら、このゲームの復活方法には問題がある。

  「コンバットスクール」。コレと「ワールドカップ」はやりすぎると次の日に腕が上がらなくなるゲーム。あ「サイバリオン」もか。ステップ3でボートが見つからずに頓死。覚えゲーの側面が強いし、仕方ない。

  「アサルトプラス」。電源入れたら画面が揺れていたが少し待ったら落ち着いた。プラスだと気づかなかったので「イージーアサルト」と「スーパーアサルト」の選択画面に面食らってたら前者になってしまった。ジェネレータは倒したが、ステージ4道中で終了。このゲームはPS版で結構やりこんだが、アーケード準拠の操作でやってなかったので、基本ヘタ。なのでそんなもん。

  さて、ボツボツ帰ろうか、と思ったところで「グラディウスII」を忘れていることに気づいた。今日はソレを遊びにきたんじゃないか。しかし、またもやタコ被弾を連発。なんと人工太陽ステージでミス。すっ裸でフェニックスと戦う。初めてじゃないか?w エイリアンでもミスって、ビッグアイの石に当たって終了。さすがにコレでは帰れない。しかし、もう1プレイしてヘンなトコで終了したら心が砕ける。んが、迷った挙句にもう1プレイ。今度は心臓に悪いデスの極太レーザーでタコミス。ホントに心臓に悪い。今日はやたら裸でボスと戦う日だな。高速スクロールの最後のシャッターをフォースフィールドで強行突破するも、クラブに左下に追い込まれて終了。まぁ、そこまで行ったら合格としよう。

  終始「ドルアーガの塔」が気になっていたが、宝箱カンニングペーパーがなかったので今回は避けた。ちょっと前はソコソコのプレイヤだったがしばらくやってない。ひさびさに家で練習しようかな、と思いながら、館長にカードを返却して帰宅。

  「今日は目に入ったらすぐコインを入れる」作戦で遊びまくったが、それでも千円チョイで済んでしまった。現在の100円は、当時の100円より価値が低いし、そもそも客は45歳くらいから60歳くらいなんだから屁でもない額だ。もう少し出してもいいんだがな。募金箱でも設置してはどうだろうか。と思いつつ、館長と客との雑談の中で「1コインで何時間もプレイしてる。そんな客ばっかだから、ちっとも儲からん」という内容が聞こえてきた。もちろん笑いながらのコメントだ。まぁ、既にお金じゃないんだろうなぁ。せめて、これから半年に一度くらいは来るようにしようかしらん。


2024-01-27(Sat) エアコンが好きすぎる、または、UIの考察

  「ロードスターのエアコンが好きすぎる」というと、なんだそりゃ、と言われそうではあるが、クルマ全体としてのデキもさることながら、とりわけエアコンもお気に入りなのである。どのようにエアコンが好きなのかといえば、その操作パネルである。美しすぎるのだ。その操作性もデザインも。

  自分はNR-Aグレードなのでオートエアコンでなくマニュアルであり、加飾も少ないが、そんな細かい違いはさておき、重要なのはその操作性である。同サイズの3つの円。円の周囲がダイヤルであり、円の中がボタンである。ただ、それだけだ。そして、それだけですべてが完結している。

  画像の説明

  ダイヤルは3つとも絶対位置で指示するタイプなので、それがそのまま表示器を兼ねている。ロータリーエンコーダ方式だと(温度は何度みたいな)表示器が必要になるし、操作の結果を目視確認する必要があるが、その点、絶対位置方式なら、チラと見て手を伸ばせば、必ずしも操作結果の目視確認が必要ない。

  ボタンはLEDというミニマムな表示器があるものの、3つともトグル動作であるから、こちらも、チラと見て手を伸ばせば、必ずしも操作結果の目視確認が必要ない。

  それぞれが大きくて十分に離れており、隣接していないので、手袋をしていても操作は容易で、操作ミスの起きる余地すらない。各表記にもまったく無駄がなくシンプルで明解。見たままの機能であり、全ての操作がワンアクションであり、操作の結果が見たまま残る。UI(ユーザインタフェース)とはかくありたい、と、訴えかけてくる美しい工業デザインなのである。

  最近は、タッチパネルでエアコン操作を行う車種もあるようだが、控えめに言っても最悪だと言えよう。コストダウンという面もあるのだろうが、すべて上記の逆を向いている。自動車において注視が必要になる操作を強いるUIは、間違いなく愚かな設計である。

  んが、調べると、3連ダイヤルによるエアコンの操作パネルは、別にNDロードスターに限らず、同じマツダのデミオもそうだし、ホンダのDC5インテグラや、トヨタのカローラアクシオも類似の操作形態のようだ。面白いのはNBロードスターで、機構の違いからくる差があるものの、配置のコンセプトが同じである。いや、逆だな。NDのパネルが、NBのコンセプトをさらに昇華させたものなんだな。まぁ、すべてのカーエアコンはこの操作に統一すべきだとは言わないが、これを採用しない理由も特段ない気がするんだがな。

  そういえば、自分はプログラマなので、UIを考えることもあるのだが、以前に作ったSwatterという在席表示システムも、気づけば上記の特徴を満たしていた。居場所、状態、コメントとも、操作の結果が見たまま残るデザインとなっている。

  画像の説明

  ちなみに、名前部分を押すと「在席」と「一時離席」がトグルしたり、名前部分をポイントすると、最終更新時刻がポップアップするという、隠し機能もある。これも敢えて意図したもので、「在席」と「一時離席」はプルダウンでも操作できるし、最終更新時刻の確認はそれほど重要でないからだ。知っていればより便利という程度なら学習すればいいことで、それよりは普段使いにおける見た目のシンプルさを優先するべきだと考えた結果である。

  と、そこでふと、デザイナは「デザイン 失敗」でググったりして参考にしたりしないのだろうか、と思いつき、ググってみると、やはりそれらしいページはいくつもあり、その中に以下のようなエレベータの操作パネルのデザインについて指摘しているページがあった。

  画像の説明

  そのページでは、主に「7階」のボタンが直感的でなく押し間違える、という点についての指摘で、その指摘はもっともであると思えるが、それ以外にも問題点は残っている思う。

  自分ならこうする。

  画像の説明

  まず「階」という同じ概念については、同じサイズのボタンを使うべきだ。で、離れた階ならば、ちょっと間隔を離すことでそれを表す。そして、自分なら2列になっているボタンも少し上下にズラすな。そうすることで、階の上下関係を自然に示すことができる。

  で、特に以前から「なんか他にやりようがあるだろ」と思っていたのが、開閉ボタンだ。「開」と「閉」とはあまりに似た文字だし、よくある「>|<」と「<|>」も全然スッと入ってこない。そこで「><」「( )」を提案する。「階」とは違う概念だから丸いボタンを使い、できればサイズも変えるといい。開く方は安全側なのだから、カドのない柔らかい印象にしている。また、左右の位置関係も、扉の右側にパネルがあるなら、扉の動きに合わせて右側に「( )」を配置すべきだ。加えて、子供が閉じ込められる場合を考慮すれば、開閉ボタンは低い位置に配置するのが適切だろう。

  もうひとつ考えてみた。「開」「閉」の文字をイジる。フザけているようだが、もともと「開」「閉」という文字は「門」という象形文字の延長なのであるから、それをさらに延長したまでである。これならば漢字の読めない外国の方でも、スッと理解できるんじゃないかと思う。

  画像の説明

  というわけで、巷には考えていなさすぎるデザインが溢れている。まぁ、人によって感じ方はあるが、要するに俺が考え抜いたUIこそ最強なのだ……という考えが「一番ダメ」だろう。セブンイレブンのコーヒーマシンがよい例である。あれこそが売れっ子デザイナ様の無残過ぎる晒し首だ。

  しかし、んじゃどうすればいいかといえば、おそらく人に意見を求めることが重要なのだと思うが、逆に人の意見を取り入れすぎても、無残なデザインになるような気もせんでもないな……うーむ。