2008年10月01日

shredのあれこれ

はてなブックマークに登録

先日の shredを6倍速くしてみた のエントリは、 社内向けのメールをほとんどそのまま公開してしまったために、危険性にふれず安易に手抜きを推奨するような記事にしてしまいました。 社内でshredを使う目的は、過去に そのディスク、捨てる前に 〜shredで内容消去〜 でも紹介したように精神衛生上の問題なので乱数の質が落ちることは問題にならなかったのですが、これを機にもうすこしshredやHDDの消去について調べてみました。

shredの元になった論文

shredのinfoからリンクされている論文があります。 (Secure Deletion of Data from Magnetic and Solid-State Memory) この論文を読んでみると、shredがいくつものビットパターンで何passも書き込みを行う理由が説明されていました。

磁気的に消去するために、1と0を交互に何度も書き込みたいのですが、HDD(CDなども)の物理層で書き込まれるデータは、1や0が連続して出現しないように エンコーディングされていて(Run Length Limited (RLL))、奇数passで0xFFを、偶数passで 0x00を書き込むだけではフリップされないビットが存在するようです。 そこで、この論文では、どういったビットパターンを書き込めばRLLでエンコードされた物理層の全bitをフリップすることができるかをリストにしています。 ただし、現代のHDDがは単純なRLLよりも効率の良い(物理容量と論理容量の差が小さい)方式で書き込まれているので、RLLをターゲットにした ビットパターンで全bitをフリップできるとは限りません。その代わり、ランダムなデータを書き込むだけで、データを復元しにくくなります。

また、最初と最後にランダムを書き込むと少し、固定ビットパターンの書き込み順序をシャッフルするとさらに元のデータを推測しにくくなるとも かかれていました。

その他の参考文献

DoD 5220.22-M という規格があるらしく、それに準拠したという消去ツールがいくつかあります。 一次情報を探して見つけたのが DoD 5220.22-M です。この資料に書かれていた手順は、1. 全アドレス可能領域をあるcharで埋める、2. 補数で埋める、3. 乱数を書き込む、というものでした。

ただし、「DoD 5220.22-M準拠」という消去ツールでも消去時に書き込むデータはばらばらで、本当にこの資料のことを言っているのか自信がありません。

shredの過去の実装とML上での議論

shredが乱数を全面的に/dev/urandomに頼るようになったのはcoreutils-6.0からで、5系では、/dev/urandomから乱数の種だけ取ってきて、 乱数の生成は内部で行っていました。乱数生成には、ISAACという、暗号論的乱数生成アルゴリズムを用いていました。(stdlibのrandom()よりずっと 安全です)

どういう経緯なのかは判りませんが、coreutils-6.0からは 乱数をすべて /dev/urandom から持ってくるようになりました。 これで劇的に遅くなったのですが、MLで「5passで実行したら4日経っても終わらない」という報告がありました。 How to tune shred to run faster on Solaris 8

それに対する返信で、shredのデフォルトのパス数を変更しようという議論が行われたスレッド Default number of overwrites in shred が紹介されていました。 この議論では、現代のHDDなら1passでも十分効果があるとか、Secure Erase Newsletterでは2passと言われていたという発言もありました。

shred以外のツール

shredを /dev/sd? に対して利用する場合、書き込み対象は論理アドレスだけなので、代替セクタなどに情報が残る可能性があります。 そういった部分も消去するためには、HDD自身に消去機能が必要になるのですが、ATAコマンドに該当するコマンドがありました。Security Erase (SE) と Enhanced Security Erase (ESE) です。 ESEの場合、ユーザーに見えない領域も含めて、最低2passの乱数書き込みを行うようです。(参考: CMRR Secure Erase)

この機能をLinuxから使う場合、hdparm --security-erase-enhanced などとすれば良いらしいですが、Ubuntu Hardy で man hdparm してみたところ 「DANGEROUS」「EXPERIMENTAL」といった単語が並んでいました。代わりに、CMRRがHDDEraseというフリーソフトを出しています。 Ultimate Boot CD という多機能ブートCDの中にHDDEraseが入っているので、 自分のHDDがESEに対応している場合はこれを利用するとお手軽に消去ができそうです。

まとめ

いろいろ調べたわりに、あまりまとまった資料が見つけられなかったのですが、とりあえずまとめてみます。

まず、shredのデフォルトのpass数が25なのは、フロッピーや古いHDDのことも考えられているからで、現代のHDDに対してshredをかけるなら -n 2 か -n 3 で十分らしいです。

乱数の品質についてかかれた資料は見つかりませんでした。ただ、たくさんのpassを実行する中の一つのpassとして使う疑似乱数ならともかく、 pass数を減らして実行する場合は、乱数を予測されることで少しでもデータを復元できる可能性があがりそうです。 幸い、coreutils-5系を使うことで、stdlibのrandom()よりよっぽど安全な乱数を、/dev/urandomより ずっと高速に利用できることが判ったので、今後shredを利用するときには5系を使おうと思います。

その他の手段として、shredの--random-source で /dev/urandom の代わりに別のファイルを指定できるので、

$ mkfifo rnd
$ openssl rand 999999999999999 > rnd &
$ shred --random-source=rnd /dev/sdb

の用に、外部から乱数を流し込むこともできます。opensslの乱数生成は、/dev/urandomに比べてだいたい5倍ほど高速でした。


@methane
klab_gijutsu2 at 16:25│Comments(2)TrackBack(0)tool 

トラックバックURL

この記事へのコメント

1. Posted by からし   2008年11月15日 17:54
通りすがりです。つい先日同じようにshred高速化に取り組んでいたのでコメントを。

Wikipediaに暗号論的擬似乱数生成器(CSPRNG)てのがありまして、
そこにISSACもありますが、自分はANSI X9.17(X9.31)の方を使って実装しました。
周期は2^128になりますが、テラバイト程度のHDDなら十分かなと。
OpenSSLのFIPS版にも実装されてるようですが、マルチスレッド版がなかなか
見つからないので、OpenSSLのAES関数を使わせてもらってマルチスレッド実装しました。

自分のはもう少し工夫して(蛇足?)、単純にAESを繰り返すのではなく、
AESで暗号化する前に擬似乱数をXORするようにしました。
AESの処理に比べれば擬似乱数生成の負荷は取るに足らないものだし、
単純にAESを繰り返すよりは精神的に安心できるので。(^^
AESの暗号鍵や擬似乱数のSeedは/dev/urandomからです。

最近のCPUではAESの処理は高速で、1スレッド当たり100MB/s以上は軽く出るので、
HDD単体に対しては十分な速度で乱数生成できます。CPU負荷はありますが。(^^
失礼しました。
2. Posted by methane   2008年11月17日 20:25
からし様

コメントありがとうございます。

shred、やっぱり遅いですよね。CPU速度とHDD容量によっては、一台のHDDをshredするのに何日もかかってしまいますから。

今度大量の乱数が必要になったとき、からし様の紹介して下さった方法を参考にさせていただきます。

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント