@kyanny's blog

My thoughts, my life. Views/opinions are my own.

暗黙知と形式知

  • 形式知の方が良い、が、全てを形式知にしようとするのは、コストがかかる以外にも微妙な問題をはらむ
  • 暗黙知の問題は、自分が「知らない」ということを知ることができない、ということ。知って初めて「そんな情報(知識)があるとは知らなかった」とわかる
    • 形式知になっていれば、入手できる情報(知識)のうち知らないものは何か?が把握できる
  • 暗黙知のもたらす消極的なメリット・形式知のもたらす消極的なデメリット
    • 暗黙知は経験が培うもの。暗黙知を多く獲得する過程で自信や責任感が育まれる(論理の飛躍があることは認める)。ある種の通過儀礼
    • 形式知化を推奨・促進する過程で「知らないことは悪ではない。暗黙知が必要なこと・形式知化されていないことの方が問題」という価値観が正義になることがある。これが危険
    • 「まだ知らない情報(知識)があるのではないか?情報(知識)を獲得する努力を怠ってはいないか?」と内省する動機が損なわれる
    • すでに暗黙知を持っていて、その暗黙知の形式知化を推進する側が「(暗黙知を)知らないことは悪くない」と啓蒙するぶんには良いが、情報(知識)を享受する側が「(私が)知らないことは悪くない」という主張を盾にしだすと終わる
  • 情報(取得可能性)格差について
    • 情報(知識)収集に積極的な人は暗黙知を多く獲得する。その中の一部に、「(自分自身は暗黙知を獲得しているし今後も獲得できるので形式知化されていなくても困らないが)暗黙知を知れないことは問題なので形式知化すべき」という主張を持つ人がいる。その中の一部が実際に行動に移す。こういう人たちは「知らないことは悪ではない」と本気で考えつつも、自分自身は「知らない」という状態を看過せず知り続ける
      • 罪悪感ではなく好奇心に駆られて情報(知識)収集をするので、「知らないことは悪ではない(だって知ることは楽しいことだもの)」という考え方をする
    • 情報(知識)収集に消極的な人は↑の人たちが獲得した知識を享受するのみ。この勢力が「(私が)知らないことは悪くない。(↑の人たちが)暗黙知を形式知化していないことが問題」という考えを持つようになると、終わる
    • 暗黙知を形式知化するのにはコストがかかる。時間・お金だけでなく、形式知化(== 文書化)することが難しい概念などもあり、そういう知識こそが貴重。情報(知識)獲得に積極的な人が新しい知識を獲得するペースは獲得済みの暗黙知を形式知化するペースより早いので、両者の情報格差は広がり続ける
  • 「知らないことは悪くない」という主張に対して「それは違う」と反論するのは難しいご時世なので、「知らないことは悪くない」という価値観を増長させない工夫が必要なのかもしれない
    • あえて暗黙知をそのままにしておくことによって、「全てを形式知化するのが最善ではない、暗黙知を獲得することも必要」というムードを演出する、とか
    • 味付けを間違えると「部活の先輩にうさぎ跳びをさせられた」みたいな感じになってしまうので、難易度は高いが

二要素認証アプリがアカウントの衝突を検知する方法、および衝突時の振る舞いについて

背景

二つの異なるウェブサイトに二要素認証を実装した。いわゆる管理画面で、プロダクション用とステージング用の二つ。 Label も Issuer も同一で Secret だけ異なる otpauth URI と QR コードが生成された*1

Microsoft Authenticator アプリで QR コードを読み込んだところ、一つ目は問題なく登録できたが二つ目の登録時に警告メッセージが表示された。二要素認証アプリの画面に表示される「アカウント名」のような情報が同一だから重複と判定されているのだろう。幸い Secret の文字列がわかっていたので、手入力することで回避できた。

しかし、他の二要素認証アプリを使っている人は同様の問題が発生しなかった。アプリによってアカウントの重複(衝突, conflict)を検知する方法が異なるようだが、衝突検知方法や衝突検知時の振る舞いに決まりはあるのか?が気になったので調べた。

調べてわかったこと

30 秒ごとに 6 桁の数字が変わるあれは RFC 6238 - TOTP: Time-Based One-Time Password Algorithm という仕様に基づいている。

今回知りたかったのはそっちではなくて、アプリ側の仕様。それらしい RFC は見つけられず、かわりに Google Authenticator の GitHub Wiki ページを見つけた。

以下の二つの otpauth URI は Label に含まれる issuer prefix も issuer parameter も同一で、 Secret だけが異なる*2

  • URI 1: otpauth://totp/ACME%20Co:john@example.com?secret=7U5FG3XE6T7XPXGZSDX57LCNFNZZCF6D&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30
  • URI 2: otpauth://totp/ACME%20Co:john@example.com?secret=SVY3WJKNE54W6RDANT5GOJTKU32FU3BE&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30
Label accountname issuer prefix issuer parameter
URI 1 ACME%20Co:john@example.com john@example.com ACME%20Co ACME%20Co
URI 2 ACME%20Co:john@example.com john@example.com ACME%20Co ACME%20Co

Recommendation for code generation app developers に以下の記述がある。 issuer が同一の場合、既存アカウントの上書きは避けなければいけない、との指針があるが、具体的な振る舞いについては記載が無い。

The internal logic your app needs to avoid overriding existing entries with the same username that belong -or might belong- to completely different websites.

つまり、衝突を検知した時の振る舞いは実装依存ということだ。少なくとも以下の異なる振る舞いを発見した。

  • 同名の別アカウントとして登録する
  • 警告を表示し、上書きするか別名のアカウントとして登録するか選択させる
  • 警告を表示し、上書きするか登録をやめるか選択させる
  • アカウント名称の変更を促し、変更しない限り登録させない
  • 黙って既存アカウントを上書きする

黙って上書きするアプリがあったら怖いな、と思ったら案の定あった(LastPass Authenticator)。挙動を理解した上で使うならともかく、上書きされていることに気づかなかったら大変だ。二要素認証アプリは「信頼と実績」で選ぶのが良いと思う。

実験

二要素認証アプリはたくさんあるが、いくつかピックアップして検証した。原則としてすべて iOS アプリでの挙動。

  • Google Authenticator
  • Microsoft Authenticator
  • Authy
  • LastPass Authenticator
  • Duo Mobile
  • IIJ SmartKey

検証に利用した otpauth URI は以下の二つ。

  • URI 1: otpauth://totp/ACME%20Co:john@example.com?secret=7U5FG3XE6T7XPXGZSDX57LCNFNZZCF6D&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30
    • f:id:a666666:20200705162055p:plain
  • URI 2: otpauth://totp/ACME%20Co:john@example.com?secret=SVY3WJKNE54W6RDANT5GOJTKU32FU3BE&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30
    • f:id:a666666:20200705162059p:plain

QR コードの生成には https://rootprojects.org/authenticator/ を利用した。

Google Authenticator

警告無く、同名の別アカウントとして登録された。

f:id:a666666:20200705162536j:plain

Android アプリの場合

URI 1 を登録済みの状態で URI 2 の QR コードをスキャンすると以下の警告が表示された。「両方のアカウントを保持」を選ぶと自動的に別名で保存された。「変更」を選ぶと既存の URI 1 アカウントが上書きされた。

f:id:a666666:20200705170407j:plainf:id:a666666:20200705170515j:plain

Microsoft Authenticator

URI 1 を登録済みの状態で URI 2 の QR コードをスキャンすると以下の警告が表示された。「続行」を選ぶと既存の URI 1 アカウントが上書きされた。

f:id:a666666:20200705162838p:plain

Authy

警告無く、同名の別アカウントとして登録された。登録前に Account Nickname の入力画面が出るので、別名をつけることができる。

f:id:a666666:20200705163652p:plain

LastPass Authenticator

黙って上書きされた。びっくりしたので動画を撮った。 LastPass のサポートに報告した。

Duo Mobile

警告無く、同名の別アカウントとして登録された。

f:id:a666666:20200705164520p:plain

IIJ SmartKey

URI 1 を登録済みの状態で URI 2 の QR コードをスキャンし、登録を試みると以下の警告が表示された。サービス名を変更しないと登録できない。

f:id:a666666:20200705210246p:plainf:id:a666666:20200705210255p:plain

考察

  • LastPass Authenticator は既存アカウントを黙って上書きする。この挙動はかなり怖いので、これを使う特別な理由が無い限り、安全のために他の二要素認証アプリを利用した方が良いと思う。
  • Microsoft Authenticator の挙動が最も説明的だが、初見殺しでもある。見慣れないダイアログが突然出現すると、びっくりして反射的にボタンを押してダイアログを閉じてしまうかもしれない。もし内容を読まずに「続行」してしまうと、何が起こったか分からない。
  • Google Authenticator の Android 版の挙動も、ユーザーが取れる選択肢が多く、優れている。「両方のアカウントを保持」を選ぶと自動的に別名がつくので、後で見分けやすい。ダイアログが出るのでうっかり操作ミスをして事故るリスクがあるのは Microsoft Authenticator と同様。
  • IIJ SmartKey の「上書き登録できない」という挙動が最も安全だ。欲を言えば、登録ボタンを押す前に警告が表示されると、さらに分かりやすいと思う。少し知識のあるユーザーは、既存アカウントとサービス名やアカウント名が同じだと気づいた場合、登録ボタンを押すのを躊躇するかもしれない。

まとめ

  • 二要素認証アプリは issuer の値でアカウントを区別する。自分で otpauth URI を生成する場合は、 issuer にユニークな値を使うこと。
  • アカウント衝突時の振る舞いはアプリの実装に依存する。自分で用意した otpauth URI を登録する場合は、二要素認証アプリの挙動を確かめておくと安全。
  • アカウント衝突時は手入力を試すと回避できることがある。それでも無理なら別の二要素認証アプリを使う。

*1:URI のフォーマットについては後述

*2:この otpauth URI はブログ記事用に作ったものであり、実運用されているウェブサイトとは無関係

ポップコーンを作るけど、量とかちょっと不安だから一緒に見ててと妻に言われ、バターが多いかな?と思ったけどポップコーンのタネは多すぎないように見えたのでいいと思うと言った。ポップコーンがなかなかポンポン跳ね始めないので不安に思った妻が「油が多すぎたんだよ」おれもバターが多い気がした、と言い、どうなってるか鍋の蓋を取って見てみたらと言ったら何馬鹿なこと言ってるのという感じであしらわれた。間も無くポップコーンが跳ね始め、妻はそれみたことかと得意げに、「あなたの言う通り蓋を開けてたら今頃ポップコーンが鍋の外に飛び出て大変だったよ。まったくこういうことにはまるで無能なんだから」と。そうだね、おれもそう思う。

M-x comment-line (C-x C-;)

カーソル行をコメント・アンコメントしてくれる。リージョンが選択されているときはリージョン範囲の行全てが対象。

知らなかった...。これまでずっと

  • 行頭に移動 C-a
  • マークをセット C-SPC
  • 行末に移動 C-e
  • リージョンをコメント M-;

していた。

キーストロークが半分になるので、ぜひ指に覚えさせたい。

comment-line is an interactive compiled Lisp function in `newcomment.el'.

It is bound to C-x C-;.

(comment-line N)

For more information check the manuals.

Comment or uncomment current line and leave point after it. With positive prefix, apply to N lines including current one. With negative prefix, apply to -N lines above. Also, further consecutive invocations of this command will inherit the negative argument.

If region is active, comment lines in active region instead. Unlike ‘comment-dwim’, this always comments whole lines.

[back]