There's an echo in my head

日々のメモ。

結城浩「新版暗号技術入門 秘密の国のアリス」を読んでる

新版暗号技術入門 秘密の国のアリス

新版暗号技術入門 秘密の国のアリス

すごくわかりやすいし面白い。

  • 共通鍵暗号
    • 事前に共有しておいた秘密鍵を使って暗号化・復号化する方式
    • 今のところAES-256-CBCが安全
      • AES(やDES)は固定長のブロックを暗号化するための技術
        • ブロック暗号という
        • ストリーム暗号
      • CBCやCTRは自由長のバイト列をブロックに分割してブロック暗号に渡す方法。モード
        • CBCは前ブロックの結果(最初は初期化ベクトル)を対象のブロックにXORしてから暗号化する
          • 並列処理はできない
          • 最後のブロックはそれ以前の全てのブロックの影響を受けるので、最後のブロックだけ切り取ってMACに使うことができる
        • CTRはnonceをもとに作ったカウンタをブロックごとにインクリメントして暗号化し、ブロックとXORをとる
          • ブロックごとの並列処理ができる
          • ブロックごとの暗号化は独立しているのでCBCのようにMACには使えない
  • 公開鍵暗号の仕組み
    • 公開鍵暗号は公開鍵で暗号化したものはそれと対になるプライベート鍵でのみ復号化できるという方式
    • RSA公開鍵暗号アルゴリズムのひとつ
      • デジタル署名にRSAが使えるのは、それが上記と逆にプライベート鍵で暗号化したものを公開鍵で復号化できるから
      • 公開鍵暗号アルゴリズムであってもデジタル署名に使えるとは限らない
  • 共通鍵暗号公開鍵暗号の使い分け
    • 共通鍵暗号は速いけど事前に相手に秘密鍵を安全に共有しておく必要がある
    • 公開鍵暗号は遅いけど公開鍵だけを相手に渡しておけばよく、これは他者に漏れても構わない
      • プライベート鍵さえ漏れなければ良い
    • 長い秘密のメッセージを送りたい場合には、そのセッション用の秘密鍵を生成し、それでメッセージを暗号化する。そしてセッション秘密鍵を相手の公開鍵で暗号化してセットで送れば、相手はそれと対になるプライベート鍵でセッション秘密鍵を復号化し、さらにメッセージを復号化できる
  • 暗号化で守れないもの
    • 暗号化はあくまでデータを他人に見られないようにするための技術
    • 通信経路での改ざんは行われなかったのかという正真性の検証にはハッシュを使う(MD5SHA-1、SHA-2(SHA-256など)、最近はSHA-3をコンペするとか)
    • そもそも本当に本人が送ってきたものなのか、また第三者がみてどうやってそれを判断するかという認証にはメッセージ認証コード(MAC)やデジタル署名を使う

などなど。デジタル署名あたりまで読み終えたけど、SSL/TLSはまだまだこれから。

素数をもとにしたRSAが解けるかどうかは素因数分解を高速に解けるかどうかにかかっていて、P≠NP問題が暗号につながるのはこれかーとか。楕円曲線暗号ってなんだろうなーとか。AESはオープンなコンペ方式で専門家が穴をつつきまくった結果負けなかったアルゴリズムであるとか。

やあ、楽しいですね。

OSXでmysqlが"Too many open files in system”を起こした時の対処

10.7あたりからパーティションを切っていると頻発するようになっていて、最近ようやく対処方法が分かった。

3つのファイルに次のような設定をしたのちMacを再起動する。

/etc/sysctl.conf:

kern.maxfiles=20480 
kern.maxfilesperproc=18000

/etc/launchd.conf:

limit maxfiles 8192 20480
limit maxproc 1000 2000

/etc/profile:

ulimit -n 4096

参考

IAMでEC2を起動、停止できるカスタムポリシーを作る

ポリシージェネレータをいじったり手でいじったりして、特定のタグを持つインスタンスの起動、停止ができるカスタムポリシーを作った。

// ※ 実際はJSONなのでコメントは記入できません
{
  "Version": "2012-10-17",
  "Statement": [
    // EC2のインスタンスに対する状態の取得を許可する
    // これも↓のAllowStopStartのように対象をタグで絞り込もうとしたら動いてくれなかったので、全サーバに対して許可した
    {
      "Sid": "AllowDescribe",
      "Effect": "Allow",
      "Action": [
        "ec2:Describe*"
      ],
      "Resource": [
        "*"
      ]
    },
    // key=Foo,value=Barタグを持つインスタンスに対して起動と停止を許可する
    {
      "Sid": "AllowStopStart",
      "Effect": "Allow",
      "Action": [
        "ec2:StartInstances",
        "ec2:StopInstances"
      ],
      "Condition": {
        "StringEquals": {
          "ec2:ResourceTag/Foo": "Bar"
        }
      },
      "Resource": [
        "arn:aws:ec2:*"
      ]
    }
  ]
}

実際にはAllowStartStop部分だけでいいんだろうけど、decribe系のAPIも使いたかったのでAllowDescribeとして混ぜた。注釈でも触れているとおり、describe系の対象もタグで絞り込もうとしたら動かなかったので、全インスタンスを対象にした。ちなみにSidは自由に設定できる。

ポリシーは生成してからもあとから編集できるんだけど、反映されるまでに少し時間がかかった。それと、ポリシー名をあとから変えたらポリシー自体が設定していたユーザの画面から消えた…。

カスタムポリシーを使えばFull Accessのような過大な権限を与えた結果関係ない部分に対して誤操作をしてしまうこともないし、適切なポリシー名をつければそのユーザがグループの用途やできることがわかりやすくなる。

参考

ec2ssh 3.xでも2.xと同じフォーマットでHostを出力する

mirakui/ec2sshの2.x系ではHostの末尾がregionだったのに対して、3.x系ではAZに変わっていた。

# 2.x
Host tag-name.ap-northeast-1
  HostName ec2-54-NNN-NNN-NNN.ap-northeast-1.compute.amazonaws.com

# 3.x
Host tag-name.ap-northeast-1a
  HostName ec2-54-NNN-NNN-NNN.ap-northeast-1.compute.amazonaws.com

knife-soloのJSONファイルがこのHostと一致させる必要があったのでなかなか移行できずずっと見送っていたのだけれど、よく考えたら出力するときにAZ末尾のaやcを削ってしまえばいいことに気がついた。

というわけで3.x系での~/.ec2sshhost_line部分を少し書き換えたところ、2.xと同じように出力されるようになった。

host_line <<EOS
Host <%= tags['Name'] %>.<%= availability_zone %>
  HostName <%= dns_name || private_ip_address %>
EOS

host_line <<EOS
Host <%= tags['Name'] %>.<%= availability_zone.sub(/[abc]$/, "") %>
  HostName <%= dns_name || private_ip_address %>
EOS

めでたしめでたし。

PTY.spawnで外部コマンドを実行する

以前Open3.popen3で外部コマンドの出力を随時受け取って表示するということをやったけど、それでは不便な場面が出てきた。

というのも、例えばgrepでマッチした部分を色付けしたものを得ようとしてもOpen3.popen3で受け取ることはできない。これはgrepが出力先がttyのときだけ色付けするようになっているのに対して、Open3.popen3のやりとりにttyが使われていないことが原因らしい。((出力先のIOがttyかどうかはrubyだとIO#tty?で調べられる。))

正直ttyってなんなのかわからないけど、とりあえずPTY.spawnを使うと擬似ttyをruby上に作ったうえで外部コマンドとやりとりできるとのことがわかったのでやってみた。

require "pty"

PTY.spawn("long-long-command") do |r, w, pid|
  # rはコマンドの出力IO。標準出力と標準エラーの両方が同じところから出てくる
  # wはコマンドへの書き込みIO

  w.close_write
  r.sync = true

  begin
    r.each do |line|
    next if line.nil? || line.empty?
    puts line
  rescue Errno::EIO
  ensure
    ::Process.wait pid
  end
end

ちなみにknife-soloでの変更点などの出力の色付けは出力先がttyでないと行われないんだけど、それを裏で叩いているpaknifeではOpen3.popen3を使っているため色付けされない。

なので色付けされた出力を得ようとPTY.spawnを使うようにしてみたんだけど、一部分だけが色づくだけで変更箇所などは色付けされないので、どこが原因かまだ探っているところだ。

参考

knife-soloをJSONファイルを作らずに走らせる

--json-attributes <json>もしくは-j <json>オプションを使えばnodes/*.jsonを作らなくても走らせることができた。

$ knife solo cook myserver.01 -j '{"hostname":"myserver.01"}'

みたいな感じ。

さすがにJSONを長々と書くのは不便なので、基本となるロールをroles/*.rbに定義して、ノードごとに異なる値をJSONで渡す形式にしてやるとよさそう。

ロールは--override-runlist 'role[<role>]'もしくは-o 'role[<role>]'で指定できる。カンマ区切りで複数指定も可。

$ knife solo cook myserver.01 -o 'role[app]' -j '{"hostname":"myserver.01"}'

みたいな感じ。

このブログに出てくるコードスニペッツは、引用あるいは断りがない限りMITライセンスです。