VS Code + pipenv で MacにPython開発環境を作る

なぜVS Code?

  • Remote Developmentがよさそう
  • intellisenseによる補完がよさそう
  • そのうちpythonもintellicodeの補完もでるだろう
  • 現在はPython中心でPycharm使っているが他の言語も使う予定
  • めっちゃ流行っている

なぜpipenv?

VS Code の installと設定

pyenvでpythonがビルドできない問題。。

  • x-codeが古いとおこられている
  • x-code入れ直すためにOSが古いと怒られる
  • clangが適切に入っていないのが問題だった(次の記事参照)

Pythonの非同期asyncioについてのメモ

ノンブロッキングな非同期の要素

  • コルーチンオブジェクト(async/await)
  • コルーチンをスケジュール管理するオブジェクト(Task もしくはFuture)
  • 複数コルーチンを実行するloop

非同期処理の用語

  • asyncioモジュールはノンブロッキングな非同期処理に使う
    • シングルスレッドでの非同期処理である
      • マルチプロセスはcpu、マルチスレッドはプロセスの中でのプログラムの単位でメモリ共有
  • 関数をコルーチンにするにはasyncをつける
    • コルーチンとは関数の途中で処理を保留し、状態を保持して後から再開することができる関数のこと
  • コルーチンを実行するにはawaitが必要? ここ怪しいな
  • コルーチンを実行するだけでは非同期にならない. スケジュール調整と実行するloopが必要.
  • コルーチンを実行するスケジュールを立てるにはtaskもしくはfutureにする必要がある
    • taskはコルーチンを非同期処理するために賢くスケジュール実行してくれる(時間がかかる処理を待つ間、他の処理を実行)
    • asyncio.gatherやasyncio.waitを使ってfuture化できる
    • task化、future化することで、コルーチンの結果を取り出す、引数を渡す、callbackを設定するなどができる
  • スケジュール実行するにはloopが必要である
    • asyncio.run で生成と終了までしてくれる
    • loop = asyncio.new_event_loop()で明示的に作ることもできる
  • Task
    Tasks are used to schedule coroutines concurrently. When a coroutine is wrapped into a Task with functions like asyncio.create_task() the coroutine is automatically scheduled to run soon.
  • Future
    A Future is a special low-level awaitable object that represents an eventual result of an asynchronous operation. When a Future object is awaited it means that the coroutine will wait until the Future is resolved in some other place. Future objects in asyncio are needed to allow callback-based code to be used with async/await. Normally there is no need to create Future objects at the application level code. Future objects, sometimes exposed by libraries and some asyncio APIs, can be awaited.

参考資料

暗号技術入門のメモ

暗号技術の理解のために大事なこと

  • 各種暗号技術の目的を正しく理解する
  • 暗号技術に使われる用語が日常語と混同しやすいので、用語の意味をしっかりと理解する

暗号技術には目的がある。 目的がわかれば、技術の中身も理解しやすくなる。

最終目的: 遠く離れた二人の間で、第三者に知られることなく、メッセージを正しくやりとりしたい

この目的を達成するための必要な機能を挙げていく

  • 機密性の担保(メッセージを盗聴されないこと)
  • 正真性の担保(メッセージを改ざんされないこと)
  • 送信元の認証(送信元になりすまされないこと)
  • 送信元が否認しないこと(送信者が送信後に私が送ったのではないと否認できないこと)

暗号技術はこれらの機能を満たす必要がある.

機密性の担保(メッセージを盗聴されないこと)

暗号化と復号化

三者にメッセージが見られたら困ることはたくさんある。メッセージの中身を見られないためには、暗号化と復号化、という処理をする。

暗号化とは、メッセージの意味がわからないように元のメッセージの内容を書き換えること。

復号化とは、暗号化された内容を、元のメッセージに戻すこと。

アルゴリズムと鍵

暗号化と復号化でポイントになるのは、アルゴリズムと鍵、である。

アルゴリズムとは暗号化のルールみたいなもの。鍵はアルゴリズムのパラメータのようなもの。

ちなみに、日本語の鍵という言葉は、錠前(lock)のことも鍵と呼ぶので注意。暗号の世界でいう鍵はあくまでkeyの方だけである。錠前(lock)のほうが暗号アルゴリズムに相当する。

暗号化アルゴリズムの例

暗号アルゴリズム(=錠前の仕組み): アルファベットの並びでn文字の分だけずらす たとえばaを3文字ずらすなら、dである。hならj。zを3文字ずらすときは、最初に戻ってcとする。

このアルゴリズムで鍵をn=2とすると、文字列 helloは hello → jgnnq というように暗号化できる。

つぎに暗号を元のメッセージに戻す、つまり復号化をしてみる 今回のアルゴリズムの場合、n=2だけ戻せばいいので、 jqnnq → hello と簡単に戻すことができる。

鍵の2つの役割

ここで鍵には2つの役割があることがとてもとても大切である。

つまり、鍵をかけるとき(暗号化)と鍵を使って元に戻すとき(復号化)のときだ。

これは家の鍵でも同じで、鍵は家を出るときと入るときの2回使うことになる。

暗号化に使う鍵と復号化に使う鍵が同じ場合、その鍵を対称鍵や共通鍵というように呼ぶ。一般の家の鍵は対称鍵になる。

一方、南京錠は錠をかけるときは鍵を使う必要がなく、錠を開けるときは必要なので、対称鍵ではない。

対称鍵の鍵配送問題

もし対称鍵をメッセージをやり取りする二人だけしか持っていなければ、メッセージを盗み見ることはできない。

ただし、対称鍵を二人だけが持っている状況にどうやってするのだろうか?

家が近いなら直接USBメモリで渡すとかできるが、離れていては難しいし、手間がかかりすぎる。

この鍵の配送の問題を解決するのが、公開鍵暗号だ。

公開鍵暗号は鍵配送問題を解決する

公開鍵暗号とは鍵の2つの役割(暗号化と復号化)の鍵を分ける。 そして復号化の鍵を公開する。

そして暗号化の鍵と復号化の鍵は必ず1対のペアになる。そんな都合のいいアルゴリズムを発見してくれたおかげで実現できた。

なお、暗号化の鍵のことを公開鍵に対して秘密鍵と呼ぶ。

この仕組があれば、鍵配送問題を解決できる。

メッセージを受信したい人はまず、公開鍵と秘密鍵のペアを作る。そしてメッセージを送信してほしい相手に、その公開鍵を送る。

メッセージを送信する人は、公開鍵でメッセージを暗号化して送る。メッセージを復号化できるのは秘密鍵を持った人だけなので、メッセージの機密は守られる。

公開鍵暗号ではメッセージを受信する側が最初にアクションを起こさなくてはいけない。

公開鍵暗号のポイント

  • 暗号化の鍵と復号化の鍵を分ける
  • 暗号化の鍵を公開し、復号化の鍵は公開しない
  • メッセージを受け取りたい人が、秘密鍵と公開鍵のペアを作り、メッセージを送ってもらいたい人に公開鍵を送る
    • つまりメッセージの受信側がお膳立てをする必要がある
  • そしてメッセージを公開鍵で暗号化して送ってもらう
  • そのメッセージを復号化できるのは世界で秘密鍵を持っているひとだけ

ハイブリッド方式は公開鍵暗号と対称鍵暗号の欠点を補完しあう

公開鍵暗号があるならもう対称鍵暗号は用無しでは、、と思うかもしれないがそうではない。

公開鍵暗号秘密鍵暗号に比べてめちゃくちゃ暗号化と復号化のコストが高いのだ。

だから現実の暗号通信は、公開鍵暗号と対称鍵暗号のいいとこ取りをした、ハイブリッド方式が用いられている。

仕組みは極めて単純。 対称鍵のやり取りをするところだけ公開鍵をつかって、安全に対称鍵がやりとりでいたら、以後は対称鍵を使う。

正真性の担保(メッセージを改ざんされないこと)

さて、暗号化により、メッセージの機密性(盗み見されないこと)は担保できた。

しかし、メッセージが改ざんされるかもしれない。暗号化と復号化だけではこの改ざんされたかどうか、というのはわからない。

メッセージを受け取ったはいいが、それが書き換えられているかどうかわからないのは非常に怖い。

これを解決する大事な技術が一方向ハッシュ関数である。

一方向ハッシュ関数で正真性を確認できる

関数とは、入力値に対して処理をして、出力値を出す、というものだ。

一方向ハッシュ関数でよく使われるSHA-256という関数は、 どんなサイズの数値を入力しても、256ビットの数値を返す関数である。

そして入力した数値が少しでも変化すると、その256ビットの数値が大きくかわる。

この関数を利用すると、メッセージが改ざんされたかどうかを確認できる。

ただし、ハッシュ値が必ず意図した相手が作った正しい値と保証された前提である。正解が間違っていたらどうしようもない。

またなりすましも同様である。これを認証問題というが、認証問題は複数技術を組み合わせて解決する。

送信元の認証(送信元になりすまされないこと)

認証とはメッセージが意図した相手から正しく送られてきたかどうかの保証である。認証にはメッセージ認証コードという技術をつかう。

メッセージ認証コードでなりすましを防止する

なりすましを防ぐメッセージ認証コードはこれまで出てきた技術の組み合わせで実現できる。

message authentication codeの頭文字をとってMACという。 MACを使えば、正真性を確認して、メッセージの認証、すなわち意図した相手からのメッセージである、ということを保証できる。

MACを作るには共有鍵が必須である。送信者は、共有鍵とメッセージを入力としてMACを計算する。

そしてメッセージとMAC値を送る。 受信者は、受け取ったメッセージと共有鍵を使ってMAC値を計算する。

送られてきたMAC値と自分の計算したMAC値が一致したら認証は成功ということになる。MAC値の計算には例えばメッセージと共有鍵を結合して、そのハッシュ値MAC値とする。

もしメッセージを改ざんしたら、MAC値が変わってしまう。 MAC値を計算しなおすのには新しいメッセージと共有鍵が必要なので、共有鍵がないと正しいMAC値を計算することはできない。

メッセージ認証コードではできないこと

MAC認証は共有鍵を持っている者同士だけしかその内容を検証することができない。

三者にはわからない。だからメッセージを送った後に、私はそんなの送ってないよ、あなたが作ったんじゃね、と言われたら、それを証明することはできないのだ。

送信元が否認できないこと、第三者による認証ができること(送信者が送信後に私が送ったのではないと否認できないこと)

デジタル署名で第三者による認証が可能になる

メッセージ認証コードでは第三者による認証ができないことが問題だった。 デジタル署名はこれを解決する。 デジタル署名は一般的な署名というイメージと概念が異なるので、 中身を理解しないと言葉に引っ張られて誤解が生じるので注意である。

デジタル署名では、メッセージをハッシュ化し、そのハッシュ値秘密鍵で暗号化する。 その暗号化した値をデジタル署名、とよぶ。 したがってデジタル署名は、メッセージが1bitでも変化すると大きく変化する。

メッセージ送信者は、メッセージと共にこのデジタル署名を受信者に送付する。

メッセージを受信した側は、メッセージをハッシュ化し、このハッシュ値が デジタル署名を公開鍵で複合化した値と等しいかを検証する。

MAC値では共有鍵を鍵としては使っていなかったが(使ってもいいんだろうけど) デジタル署名では、秘密鍵を暗号化のためにつかう。

公開鍵は第三者でも手に入れることができるので、 第三者であってもその内容を認証することができる。

また、デジタル署名は、その秘密鍵を持っている人でしか作ることはできないので、 あとからなかったことにすることもできない。

デジタル署名は結局、あるメッセージと秘密鍵を結びつけている。 メッセージにあるデジタル署名がついていたら、そのメッセージにデジタル署名をつけることができたのは、 秘密鍵を持つ者だけである、ということである。

公開鍵が誰のものかわかってさえいたら、その公開鍵で署名を復号化してハッシュ値を計算し、 そのハッシュ値がメッセージから計算される値と等しくできるのは、 公開鍵と結びついた秘密鍵を持つものだけ、ということ。

デジタル署名からKPI(公開鍵基盤 Public Key Infrastructure)

デジタル署名では、その公開鍵が誰が発行したものか、がポイントになる。 それさえ証明できれば機能する。

そこで本物の公開鍵を入手するために考えられたのが証明書である。 証明書とは公開鍵をメッセージとみなして、 信頼できる人にデジタル署名をしてもらった公開鍵のことである。

要するに公開鍵をハッシュ化して、ハッシュ値を認証機関の秘密鍵で暗号化したもの、ということ。

もし認証機関の公開鍵をもっていれば、その発行された証明書を検証することができる。

そしてこの仕組を支えるのが公開鍵基盤となる。

証明書

公開鍵基盤

レコメンドシステムの参考資料

参考になるweb上の資料

書籍

  • 推薦システム: 統計的機械学習の理論と実践

2019-05-01学んだ言葉

  • byte(バイト)
    • 情報量の単位のこと。多くの場合は8bitのこと
    • 8bit は 28 = 256なので、10進数なら0~255 or -128~127, 16進数なら0x00~0xffで表すことができる
  • PythonのBytesIO
    • バイナリデータをメモリ上で高速に扱うための機能
    • 画像や音声データをファイルに書き出しなどせずにメモリ上でファイルのように受け渡しできる
    • img_bytes = io.BytesIO() → plt.savefig(img_bytes, format='png') → pil_img = Image.open(img_bytes)
    • img_in = urllib.request.urlopen(url).read() → img_bin = io.BytesIO(img_in) → img = Image.open(img_bin)
  • encode <--> decode
    • 符号化。圧縮などのためにある情報を他の形式の情報に変換することに使われる。ハフマン符号化など。
    • 文字エンコード、の場合は文脈によりその変換表を指すことと、変換作業を指すことがある
    • decode することで情報を元に戻す。暗号化と復号化の関係と同じ。
  • リテラル
  • base64
    • エンコード方式の一つ
    • バイナリデータをa-z, A-Z, 0-9, +/とパディング用=の64文字+1文字で変換する
      • 2進数を64進数に変換していることになる
    • 電子メールの送信プロトコルSMTPがASCII文字(7bitで表現される英数字)にしか対応しておらずバイナリデータ(音声や画像)をASCIIに変換する必要があった
    • MIME(Multipurpose Internet Mail Extensions:多目的インターネットメール拡張)という規格の一つ