koturnの日記

普通の人です.ブログ上のコードはコピペ自由です.

Vimで編集中のファイルを(ほぼ)2度と編集できなくする

最初に言っておくが,この記事は単なるジョーク記事である.

Vimには暗号化を行う機能がある. :help 'cryptmethod':help :X:help 'key' あたりを参照してもらえばよくわかるはずだ.

まず,カレントバッファにて, :X というコマンドを実行してほしい. 暗号化に用いるキーを聞かれるはずだ, キーを入力し,確認のためにもう一度キーを入力すると,編集中のファイルは暗号化される状態になる. この状態で保存すると,そのファイルは暗号化された状態で保存される. 再度そのファイルをVimで開こうとすると,キー入力が求められるはずだ. 誤ったキーを入力すると,バイナリファイルのような状態になると思う. また,Vim以外で暗号化されたファイルを開くと,当然うまく開くことはできない.

f:id:koturn:20150728063451g:plain

この暗号化に用いる方式は,Vim7.4.788の段階で,zip, blowfish, blowfish2 の3種類から選択でき,それをオプションcryptmethod に指定する. 暗号化方式は,Vimのアップデートに伴い,新たに追加されていくので,注目しておく必要がある. 古い暗号化方式を指定すると,コマンド :X を用いるときにワーニングメッセージが出る. 新しいVimで利用できる暗号化方式を用いた場合,その暗号化方式を利用できない古いVimでは E821 エラーが発生するらしい.

f:id:koturn:20150728063511p:plain

オプション cryptmethod の既定値は一番古い暗号化方式である zip であるため,最新の暗号化方式を用いたい場合,以下を.vimrcに記述しよう.

if v:version > 704 || v:version == 704 && has('patch399')
  set cryptmethod=blowfish2
elseif v:version >= 703
  set cryptmethod=blowfish
else
  set cryptmethod=zip
endif

なお,暗号化に用いるキーは,オプション key に指定することで設定できるが,手動で設定すると盗み見られるため,危険である(このことはヘルプにも書かれているはずだ). また,オプション key の内容は取得できない. echo &key としても,キーが設定されていないならば空文字列,キーが設定されていれば '*****' が返却されるだけである.

敢えて,このオプション key の値を設定すると,コマンド :X を実行した状態と同じになる. つまり,その状態で保存すれば,編集中のファイルは暗号化された状態で保存される.

暗号化されたファイルを再度開き,編集して保存したとしても,暗号化状態は解除されない. 暗号化せずに保存したいときは,コマンド :X で何も入力しないで(<CR>のみを入力して)おく,もしくは,オプション key の値を空にすればいい( set key= ).

さて,この暗号化機能を利用すれば,編集中のファイルを2度と開けなくすることが可能になるのではないか?と考えた. 暗号化に用いるキーに,使用者にとってもわからないランダムなものを設定するだけの単純な話だ. 以下を.vimrcに記述し, :DestroyFile! とコマンドを実行すれば,編集中のファイルはおそらく2度と開けなくなるだろう. 危険なコマンドなので, ! を付加しなければ,実行できないようにしてある. このコマンドを大事なファイルで実行しないように注意しよう.

if has('cryptv')
  function! s:destroy_file(has_bang) abort
    if !filereadable(expand('%:p'))
      echoerr 'Current buffer is not write out to file'
      return
    endif
    if !a:has_bang
      echoerr "Must to add '!' to destroy this file"
      return
    endif
    let cursor = getpos('.')
    normal! ggg~Gg?G
    call setpos('.', cursor)
    let &key = sha256(reltimestr(reltime()))
    write
    bwipeout
  endfunction
  command! -bar -bang DestroyFile  call s:destroy_file(<bang>0)
endif

暗号化に用いるキーは, sha256() に現在時間の文字列を与えることで生成する. これをキーに設定し,保存して,編集中のファイルをバッファから消去するだけである. 一応,暗号化前にバッファ全体に対して,アルファベットの大文字と小文字を入れ替えた後,rot13を行うようにしてある( normal! ggg~Gg?G の部分)が,これは大した意味をもたないだろう. 英文字以外に対しては意味のない操作の上,小文字大文字の入れ替えとrot13は暗号化としては貧弱すぎる. ジョークの一環として,ついでにしておいただけだ.