Linuxで扱う乱数に関する話

これはLinux Advent Calendar4日目の記事です。 Unix系OSには、カーネルに乱数生成器を持つ実装が多くあります。乱数は暗号分野でも利用され、非常に重要な位置を占めています。Linuxにおける乱数に関する話題を取りあげてみます。 エントロピープール 一般的に、特別なハードウェアを持たない限り、真の乱数を計算機が生成することは困難です。Linuxでは、質の良い乱数を生成するためにエントロピープールと呼ばれる領域を持っています。エントロピープールには、キーボードの入力タイミングやストレージ、ネットワークなどで発生するハードウェア割り込みなどをもとにした推測の困難な情報(環境ノイズ)が蓄積されます。乱数の生成時には、このエントロピープールの内容を消費、加工します。 エントロピープールにどの程度情報がたまっているかを調べるには、/proc/sys/kernel/random/entropy_availを見ます。エントロピープールの上限値は/proc/sys/kernel/random/poolsizeをcatした出力値です(デフォルト値は4096) 。OpenPGPやSSLの鍵などを生成する際には、この値を確認した方がよいかもしれません。 スペシャルデバイス 乱数を生成する特別なデバイスファイルには、/dev/randomと/dev/urandomの2種類があります。 /dev/randomは全ての乱数をエントロピープールから生成します。エントロピーが不足した場合は新たにたまるまでブロッキングされるため、あまり速度が出ません。乱数の質よりも速度に重点を置く場合には、/dev/urandomを使います。urandomを使う場合、エントロピープールを再利用して乱数を生成します。 havege havegedを動かすことで、より多くの環境ノイズ(主にCPUの情報)をもとにしてエントロピープールを常に多い状態へと保つことができます。エントロピープールへの情報の追加は/dev/randomのioctrlインターフェースを用いています。また、havagedは単独の乱数生成アプリケーションとしても利用できます。 NeuG g新部さんによるハードウェア乱数生成実装として、NeuGがあります。NeuGはSTM32F103上で動作し、チップに搭載されているA/Dコンバーターからの入力の量子化誤差を乱数生成に利用します。NueGの動作するハードウェアとしてFST-01があります。この記事を書いている2014年12月初頭では品切れ中ですが、今後追加生産・販売を予定しているそうです。 仮想化の問題 エントロピープールの情報は、予測が困難であるハードウェアからの情報に大きく依存しています。仮想マシンの場合、多くのハードウェアは仮想化されており、ハイパーバイザ等の配下にあります。したがって、物理マシンと比較すると質の良い乱数を生成させることがより困難となっています。セキュリティに十分な注意を払う必要がある場合には、信頼できない仮想マシン上での暗号鍵の生成などは控えた方が良いでしょう。 訂正 コメントでg新部さんからいくつかご指摘を頂きましたので修正・追記しました。FST-01はhttp://www.seeedstudio.com/より購入可能とのことです。詳細はコメントをご覧ください。 宣伝 この記事はFSIJ勉強会での解説をもとに得た知見を自分なりに記録したものです。FSIJでは定期的に勉強会を開催しています。GnuPGの開発者の一人であるg新部さんもいらっしゃるので、興味のある方はぜひお越しください。  

Published
Categorized as Linux

第120回東京エリアDebian勉強会、2014年11月勉強会参加

先日「第120回東京エリアDebian勉強会、2014年11月勉強会」に参加してきました。 rroonga関連のパッケージをどうにかしようと考えていたのですが、Jornada 720にDebianを入れようとしていた人が来ていたので、そのお手伝いをしました。私自身はJornada 680を持っていて、過去にDebianを入れて使った経験があったので、それが多少役に立ちました。 Jornadaは、今は亡き「ハンドヘルドPC」と呼ばれるカテゴリのデバイスで、キーボードとディスプレイのついた小型PC的なものです。680はsh3が、780はStrongARMが搭載されています。標準OSとしてWindows CEが入っています。 基本的には「Lenny on j720」にあるカーネル、ブートローダー(CE用実行バイナリ)をCFに入れて、適切なカーネルパラメータを設定して起動するだけです。 任意のアプリケーションをインストールできるようにしたかったのですが、その場にあったPCMCIAネットワークカード(Corega PCC-TD)の認識がうまくゆかず、そこまではたどり着けませんでした。 一応、最近のkernelにもjornada 780向けのコード自体は入っていますが、パッケージとして用意されているarm用カーネルでその設定を有効にしたものは現状ありませんでした。コンパイルして動くかどうかもあやしい気がします。 この時代のunstableはLennyだったようで、userlandはLennyのものでした。このころはhotplug周りの仕組みが変化していた時期でしたが、Lennyは既にudevで動いていたようです。/etc/pcmcia/config*にCorega PCC-TDの設定を追加してやればNICも動いたかもしれません。 しかしLennyの頃はアーキテクチャarmとarmelが用意されていたのに対して、それ以降ではarmel/armhfに変わっています。ABIも変わってしまっているので、直接的なアップグレードはおそらくうまくいかなかったことでしょう。 Jornada 780は探せば1万円を切る程度の価格で入手できるようですが、さすがに今から使おうという気にはちょっとなれませんでした。

Windows版puttyのビルド

puttyのビルドに関する情報、特にWindows向けが少ないのでメモとして記録しておきます。 必要なもの Perl (ActivePerl, Strawberry, cygwinなんでも良い) puttyのソース スクリプトの実行 perl mkfiles.plを実行 出力結果 windows/MSVC ディレクトリの下にVisual C++ 6向けのputty.dswファイルとサブディレクトリ以下に各種コマンド(putty, puttygen等)のサブディレクトリとプロジェクトファイル(dsp)が生成されます。 新しいVisual Studioで開く エクスプローラーからputty.dswを右クリックし、「プログラムから開く」で利用したいバージョンのVisual Studioを選択します。Expressでも使えます。 開いたあとはVisual Studioがslnファイルに変換してくれます。コマンドラインからmsbuildなども使えるようになります。 注意点 SSPIと呼ばれる機構を利用しているので、マクロSECURITY_WIN32を定義する必要があります。プロジェクトのプロパティからプリプロセッサの設定でこのマクロ定義を追加するなどの処置をすると良いでしょう。

動作中のプロセスのptyをつなぎかえられる、reptyrを使ってみる

UNIX板のGNU screenスレッドで紹介されていたreptyrを使ってみました。 screen外のプロセスにattachさせる 既にscreenを実行している状況で、screenのセッション外のプロセスを起動してみます。適当なterminalを起動するなり、外からsshでつなげるなりしてみます。あとでプロセスを探しやすいようにttyコマンドで現在使っているptyデバイスが何かを確認しておきます。 次にscreen内の任意のウインドウのshellから、当該プロセスにつなげてみます。 この時点で、元のターミナルは無反応になり、bashの制御がscreen下に移りました。shellを終了すればreptyrに制御が戻ります。 gdbと組み合わせる reptyrのもう一つの機能、ptyを外部から使わせるために確保する-lオプションを使ってみます。 別のshellからgdbでこのptyを使ってみます。set inferior-ttyで/dev/pts/7を指定することで、gdbが動かすプロセスの出力をreptyr側の端末に変更できます。 reptyrを実行していたshell上に、lsの出力が表示されます。標準入出力をデバッガの画面と切り離すことができて便利です。 実装方法 以前「起動済みプロセスのリダイレクト先を設定したい」という記事を見かけた記憶があったので、基本的には同じようなやりかただろうと思いつつソースを見てみたら、その通りでした。 起動しているプロセスに対してptrace(2)でattachし、ptyをdup2でfile descripter 0, 1, 2に複製しています。ただし、単なるリダイレクトと違い仮想端末が相手なのでresize等に対応するためのコードも含まれているようです。 前述の記事や本プログラムのドキュメントにもありますが、Ubuntuのカーネルはデフォルトで一般ユーザーのptraceを禁止しています。procfsを見てそのあたりをチェックするコードも入っています。Ubuntuユーザーが利用する場合、rootで実行するか、sysctlの設定を変更する必要があります。

Published
Categorized as Linux

SSLv3の脆弱性(POODLE)対応

SSL 3.0に、プロトコル自体の脆弱性がGoogleによって発見されました。”Paddning Oracle On Downgrade Legacy Encryption”略してPOODLEと呼ばれています。 検証サイト https://www.poodletest.com/ が立ち上がっており、脆弱性の詳細に関する元ソースへのリンクもあります。 今回の脆弱性はサーバー、クライアントともに対策が必要になります。とり急ぎ自分の周りにあるSSL/TLSを使うサービスに対策を施しました。 Apache+mod_ssl SSL_Engine onとしているセクション内で、以下の設定をしました。 SSL 2.0, 3.0を無効にし、利用可能な暗号からMD5,  3DES等を外しています(参考: httpsだからというだけで安全?調べたら怖くなってきたSSLの話!?)。 Postfix 参考: Postfix TLS Support Courier-imapd Debianのcourier-imapdはOpenSSLをリンクしているのでTLS1のみ設定しています。 確認方法 OpenSSLのs_clientを利用することで、任意のバージョンのSSL/TLSを使った接続を試すことができます。 上記サンプルでは、1回目はSSLv3, AESでの接続、2回目はSSLv3, RC4での接続ができています(参考: 私が愛した openssl (SSL/TLS 編))。設定が正しくできれば、以下のような結果となりネゴシエーションに失敗します。 STARTTLSを使う場合は-starttlsオプションが利用できます。 Debianでの対応状況(2014/10/16朝頃) w3mはSSLv3を無効化するパッチの当たったバージョンがsidにアップロードされています SSLv3が無効にされたOpenSSL 1.0.1jがリリースされており、sidにもアップロードされています。

mikutter-perlの公開

マルチプラットフォームで動作する、Rubyで書かれたTwitterクライアントmikutterのプラグイン、mikutter-perlを書きました。 動機: RubyからPerlを呼びたい 前々からNamazuのRuby実装を作りたい、ということを考えていました。現状のNamazuは独自のデータ形式を持っていますが、新しい実装ではバックエンドをGroongaにしたいと思っています。現状、Groongaのperl bindingはこれといった定番がないのに対し、RubyにはRroongaがあるので、作るならRubyだろうと考えています。 ただ、これまでPerlで書かれたフィルター群をどうにか継承できないか、とも考えていました。Namazuのフィルターはさまざまな形式のファイルからテキストを抽出するもので、今となっては結構な種類の数があります。 フィルター部分のみを呼び出すために、RubyからPerlのコードを呼び出したいという考えを実現する最初の一歩として、mikutter-perlを書いてみたというわけです。なお、Perl側には逆のことをするInline::Rubyというものがあります。 libperl呼び出し部分 最初に書いておきますが、やっていることは大したことありません。perlembedのサンプルとそう大きくは変わりません。 当初は直接libperl.soをDL::Importで読み込んで実行することを考えていたのですが、その手法には問題がありました。構造体へのアクセスができず、初期化に必要な作業が実行できません。以下にperlembedでも出てくるコード例を示します。 肝となるのはPL_exit_flagsです。perl_alloc, perl_constructで作成したperlインタプリタのインスタンス的なものに対し、終了時の挙動をフラグとして設定する箇所です。 gcc -Eオプションを使ってこの部分がどのような内容に展開されるかを確認すると、以下のようになります(on Debian wheezy)。 Perlinterpreterはstruct interpreterをtypedefしたもので、my_perlのIexit_flagsに値を代入するようなコードに展開されます。 デバッグ情報、シンボル情報などをstripした状態で、dlopen(2)だけでこれらにアクセスすることはできません。そもそもPerl周りはたくさんのマクロを使っているので、そこをクリアしたとしても汎用性が担保できません。 結局、そのあたりを全部担当するためのコードをCで書き、シンプルなインターフェースだけにまとめてDL::Import(dlopen)で呼び出せるようなコードを書きました(perlstub.c)。 RubyとPerlの間のやりとりも単純な文字列だけなので、割とシンプルに書きあがりました(mikutter-perl.c)。DL::Importはchar *を自動的にRubyの文字列に変換してくれるので楽です。 PL_exit_flagsさえ気にしなければ、DL::Importだけでコードを完結させることはできます。実際に書いたコードをgistにおいてあります。 mikutterプラグインの開発にあたって 今回初めてmikutterのプラグインを作成しました。参考にした資料は以下の通りです。 Writing mikutter plugin (http://toshia.github.io/writing-mikutter-plugin/) 基本的な書き方とイベントフィルタ、アクティビティの扱いについての情報 Event and Filters (http://toshia.github.io/writing-mikutter-plugin/event.html) 利用可能なイベントの一覧。今回は自分の実際のポストのみを対象とするためpostedイベントを監視 mikutter-shell-post (https://github.com/penguin2716/mikutter_shell_post) 似たようなことを実現している先行例として大いに参考になりました mikutter pluigin特有だと思われる、自分がはまった点についても列挙しておきます。 プラグイン内部で発生した例外は自力で受けないとスルーされる。ちょっとしたエラーがあっても止まらないのでわからない mypostイベントは、mikutter起動時に取得される過去の自身のツイートを受け取った時にも発生する。今まさにポストしたツイートに対応するイベントはpostedになる

ownCloudのDBマイグレーション失敗とリカバー

ふとしたことから、手元のsid環境を更新したのですが、その時にownCloudが5.0.25から7.0.2へと大きく変わってしまいました。ownCloudはアップブレード機能を持っている(web, occコマンド)のですが、それが途中でこけてしまったので、対処方法をblogに残しておきます。 5.0.25から7.0.2へ移行 自分はsid環境を、lxcコンテナの一つに持っています。その中でownCloudも運用しています。最初に導入したときのバージョンは5.0.25だったのですが、この記事を書いている辞典では7.0.2が最新です。5->6のメジャーアップグレードをはさめばうまくいったのかもしれませんが、自分のケースではデータベースの移行がうまくゆきませんでした。バックエンドにはSQLite3を使っています。 oc_lucene_statusでのエラー アップグレード時に発生したエラーログの一部を以下に示します。 oc_lucene_statusというテーブルの移行に失敗しています。このテーブルはLuceneによる全文検索用のものと思われますが、自分自身が全文検索を使ったことがこれまでなかったので、単純にテーブルの削除と再作成をすればよいだろうと推測し、まずはバックアップを取ったうえでdropしてみました。 単純にdropをしただけでは、当然テーブルがなくなるだけなので、やはりアップグレードに失敗します。その時のエラーは以下の通りです。 データベースのテーブルの定義はXMLで書かれています。ソースコードのapps/search_lucene/appinfo/database.xmlが該当するファイルです。これを見て適当に見よう見まねでテーブルを作ってみたところ、うまくゆきませんでした。 これはまずいと思い、バックアップしておいた方のデータベース上でのテーブル構造を参照してみました。 この結果を参考に、新しい方のデータベースで同じテーブルを作成し(表示されているSQLをそのまま実行する)、再度アップグレードを試みたところ成功しました。 無事アップグレードに成功し、今では普通に利用できています。

caffから受け取った署名を自分の鍵へ取り込む(gpg import)

ずいぶん間が開いてしまいましたが、GnuPG key signの作業をする(signing-party/caff)の続きです。前回は自分が相手に対して署名を行い、その結果を送るための手続きについて説明しました。今回はその逆、自分が受け取った相手からの署名を自分の鍵に追加する方法について説明します。 メールをファイルに保存 相手がcaffを使っている場合、pgp鍵のおそらくは各IDごとに1通のメールが届きます。 私の鍵の場合だと、IDとしているメールアドレスは4つあるので、一人当たり4通メールが送られてきます。それらを1つづつファイルとして保存します。 メールの内容は、それぞれのIDに対応する、自身の公開鍵で暗号化されたpgp asciiメッセージです。 メールの復号化 このメールをpgpコマンドで復号化します。 上記コマンド例では、入力されたファイルをmsgというファイル名で復号化しています。復号化した内容は、caffの標準テンプレートであれば以下のようになります。 署名の取り込み この復号化されたファイルには、添付ファイルとして鍵への署名があります。本文中にも説明がありますが、gpg –importコマンドを実行することで署名を自分の鍵に取り込むことができます。 これを、届いたメールの数だけ実施します。さすがに毎回passphreaseを入力するのはしんどいので、gpg-agent等を使うと楽になります。gpg-agentはバージョン2系からついてきます。1.4系にはありません。エージェントの使い方はssh-agentとよく似ているので、そちらに慣れている人であれば楽に使えるでしょう。 私は以下のようなワンライナーで一括処理をするようにしています。 公開キーサーバー上の鍵の更新 最後に、公開キーサーバーへ新しい(電子署名の増えた)鍵を送信して更新します。これは普段から公開キーサーバーに鍵を登録している人だけがすればよい作業なので、運用によっては不要な作業です。 以上で作業は終わりです。

第116回東京エリアDebian勉強会参加、そしてJessieインストーラBeta1

先の8/23に、第116回東京エリアDebian勉強会に参加してきました。 今回のお題 東京エリアDebian勉強会は、参加に際してなんらかの「お題」が出ます。ここ最近は「もくもく会」と呼ばれる「みんなでその場で集まって、各自が抱えている課題に黙々と取り組む」スタイルが多く、お題の内容は「もくもく会での目標」となることがほぼ常態になっています。 私の目標は KAKASIのローマ字テーブル見直し 積ハードの消化 ECS LivaのeMMCに関する問題 といったあたりを考えていたのですが、当日の午前中にイレギュラーが発生したので、急きょそちらをもくもく会のターゲットにしました。 DELL Latitude E6520購入 日経トレンディネットでDELL Latitude E6520が約4万円で販売という記事をみかけ、急きょ開店直後のPCボンバーへ赴きました。あらかじめスペックはある程度把握していたのですが、店頭で現物も見せてもらえたので、以下の点を評価してその場で購入を決意しました。 1080p フルHDディスプレイ SandyBridge世代だけどCore i7-4200M 今となっては貴重なIEEE1394端子搭載 メモリは最大8GB(もしかしたら16GBいけるかもしれない) eSATA端子搭載 ビデオにNVIDIA GF119内蔵 特に1394はいまだDVビデオカメラを持っている身としては貴重です。今まで使っていた動画配信用のノートPCは液晶を壊してしまったので、これでdvswitch+icecast2でのOgg Theora/Vorbisによる自由ソフトウェアでの動画中継も可能です。 Debianのセットアップ wheezy 7.6 まずは普通に現状の安定板、7.6のインストーラーを試しました。使用したメディアはUSBメモリです。 無線LANで躓く E6520の無線LANデバイスはIntel Corporation Centrino Advanced-N 6205、iwlwifiドライバで動作します。このドライバはnon-free firmware blobが必要なのでhttp://cdimage.debian.org/cdimage/unofficial/non-free/firmware/から取得しておき、インストールメディアにudebファイルを置いておく必要があります。デバイスの認識自体はこれだけでいけました。 問題は接続勉強会の会場はWPA2-PSKな無線LANが来ていたのですが、SSIDとパスワードを入力してもうまくネットワークに接続できませんでした。きちんとログを見ていなかったので、原因はまだわかっていません。再度インストールにトライすれば確認できるだろう、ということでとりあえずこの問題はさておいて、ちょっと前にリリースされたJessie Installer Beta 1を使ってみることにしました。 Jessie Installer Beta 1 次の安定板になるJessieは来年初頭には出るだろうと思われます。まずはbeta 1インストーラーをためし、何か不具合がないかを調べようと試してみました。 無線LANが認識しない いきなりこれです。有線(82579LM e1000e)は普通に認識できました。幸い会場には有線の口とケーブルもあったので、そちらを使ってインストールを続けました。 インストール完了後であれば、firmwre-iwlwifiをインストールすることで無線LANを使えるようになりますが、インストール時にうまく検出できていないのは問題です。 再起動できない wheezy, jessieどちらにも共通していますが、再起動がうまくゆきません。ただしシャットダウンはうまく動きます。それぞれでインストールされるカーネルのバージョンは3.2.0, 3.14.0です。 世代的に枯れたハードウェアだと思うので、BIOSあたりが怪しいのではないかと思っています。バージョンを確認してみると、A00… Continue reading 第116回東京エリアDebian勉強会参加、そしてJessieインストーラBeta1

twitter gemの更新に追従

概要 Rubyのtwitter gem Version 1.7.2を前提に書いていたコードを5.11.0向けに書き直したという話。 経緯 2011年ごろ、Twitterの自分のタイムラインを定期的に取得して保存するロガー的スクリプトをrubyとtwitter gemで書いて使っていました。 そのスクリプトは2013年のAPI変更で使えなくなってしまいました。この時には「過去のツイートを取得する」機能がTwitter側から用意されていたので、じゃあそれでいいやと思い、運用を止めました。 しかし、実際に取得できる情報は自分のツイートのみで、自分のタイムラインそのものではありませんでした。現状のTwitter検索は過去の内容を探すのも難しいので、「以前書いたスクリプトを直して再度自力でログを取ろう」と思い立ったので、そのために実施した修正についての記録をここに残しておきます。 修正点 クライアントインスタンスの取得と認証情報の設定 twitter 1.7.2では、Twitterモジュールのモジュール関数を呼び出して処理を行うことができたので、その方法を使って実装していました。5.11.0ではその手段が提供されなくなったので、REST APIを使う方法をとりました。 oauth_tokenとoauth_token_secretというアクセサは5.11.0でも使えますが、deprecated扱いなので警告が出ます。 タイムラインの取得 取得方法は単純で、今までTwitter.user_timeline()を読んでいたところをクラスメソッドuser_timelineに変えるだけです。 created_atの扱い 1.7.2ではツイートの作成時刻created_atは文字列で返されていたのでDateTime.parseで処理していましたが、5.11.0ではTime型を返すようになっています。 既存のコードをいじるのが面倒だったので、to_sした結果をDateTime.parseに渡しています。無駄ですがコードの変更は少なくてすみます。 結果 これらの修正で、自分のコードは無事動くようになりました。その後以下のような機能拡張を施して今にいたります。 自分だけでなくフォロワーのツイートも取得する(user_timelineの代わりにhome_timelineを使う) 各ツイートにscreen nameを付加する(x.user.screen_nameを参照) 自分がつけたfavoriteも記録する(client.favorites()メソッドを使う) UserStreamについて 今回、あえてUserStreamを使う方法は採用しませんでした。どうも同一ユーザーによるサードパーティアプリから接続できるUserStreamの数に制限があるようで、現状制限いっぱいいっぱいだからです。 しかし今回自作ロガーを再度稼働させたことで、UserStreamを貼りっぱなしのクライアントを立ち上げておく必要性は大きく下がったので、今後はUserStreamの利用も考えてみたいところです。 参考  The Twitter Ruby Gem http://rdoc.info/gems/twitter/ ソースコード https://github.com/sferik/twitter 関連書籍 [amazonjs asin=”4862670849″ locale=”JP” title=”Twitter API プログラミング”]

Published
Categorized as 開発