あれ、どうやったっけ

(たぶん)テキストサイト風blog。文が安定するまで書き直しあるからメンゴ。

RubyでAESって暗号化したのをファイルに書いて復号化するとかそういう

あんまりよくわかってないのが(自分的に)残念だけど、なんか難しいよ。とりあえずRubyの大先生が例を書いてくだすっているのでコピペで済ます orz そういうもん扱いにしとく……。

OpenSSL::PKCS5.pbkdf2_hmac_sha1には確かに「返り値の文字列から鍵と IV に必要なバイト数を切り出して利用します。 」と記載済み。とにかく生フレーズでは割れやすい事例でもあったのかと? とにかく NNせずにゴム付けて 生の値を使用せずにSHAの値を使用しているんでしょう、たぶん ← よくわかってない

2017/11/16 説明あったし……「ソルトなくてもパス割れする抜け道と、ハッシュ算法的な意味で違う文字でも抜けちゃう抜け道」をふさぐ手法を使って鍵とIVを設定せよ、位のようです。

qiita.com

pythonのドキュメントだとウナウナナントカ書いてて、その一行見つけるのに10分かかりそう orz 僕は以前それで気づかないことがあり、刺されました……文字列操作メインでpythonつらいわーという恨みつらみ。

あーあと思い出したけどパイソニスタとパイソニアンどっちが正しいん? Pythonのりどみには「version x.x.x からパイソニアンは自称パイソニスタにしてください」って書いてなかったし……(いまパイソニアンにヘイトされたこと思い出してるんです。ruby使ったらそんなにあかんのか)。

とにかく、やってみよう。

require 'openssl'
require 'base64'

# この辺が一番それっぽい
#
# https://docs.ruby-lang.org/ja/latest/class/OpenSSL=3a=3aCipher.html
# https://docs.ruby-lang.org/ja/latest/class/OpenSSL=3a=3aPKCS5.html#M_PBKDF2_HMAC_SHA1
#
# 推奨されない方法論含む(pkcs#5 v1.5の記載。v2.0ではやりかたを変えてくれということらすい)
#
# http://webos-goodies.jp/archives/encryption_in_ruby.html
#
# blowfishの例はあったのでいちおう
#
# http://weblog-1.github.io/ruby/2015/11/14/blowfish-ruby-php

CRYPT_METHOD = "AES-256-CBC"
ITER_COUNT = 2048

def encrypt(data, pass, salt)
  enc_data = enc_dec(data, pass, salt, lambda{|c| c.encrypt})
  Base64.encode64 enc_data
end

def decrypt(base64_data, pass, salt)
  enc_data = Base64.decode64 base64_data
  enc_dec enc_data, pass, salt, lambda{|c| c.decrypt}
end

# めんどくさいからlambda渡すわ……どうやったっけ……思い出せない……
def enc_dec(data, pass, salt, switch_func)
  cipher = OpenSSL::Cipher.new(CRYPT_METHOD)
  cipher.padding = 1
  
  switch_func.call(cipher)
  
  key_iv = OpenSSL::PKCS5.pbkdf2_hmac_sha1(pass, salt, ITER_COUNT, cipher.key_len + cipher.iv_len)

  key = key_iv[0, cipher.key_len]
  iv = key_iv[cipher.key_len, cipher.iv_len]
  
  cipher.key = key
  cipher.iv = iv
  
  cipher.update(data) + cipher.final
end

base_data = <<'EOS'
---
- test: dummy_data
- i_want_you: "i_hate_you"
EOS

crypt_data = encrypt(base_data, "anything_good", "abcdefg")

p crypt_data

p decrypt(crypt_data, "anything_good", "abcdefg")

出力はこんなの。

# => "ScEo9xRZJOpFj0quR6r8+FLIeeSgg51AcFbcwZFla5D+/2wXwv/E2hTuMaBx\n8U+OfynKDs1DykNE0n5l8HZGzw==\n"
# => "---\n- test: dummy_data\n- i_want_you: \"i_hate_you\"\n"

えーとなんだっけ、yieldでどうこうしてblock持ってきたら要らんようななんかが入ってるけどめんどくさい時のアレでごまかしました。ここ1年くらいコード書いてなかったのでめんどくさくなってテヌキスタして「あーこれ一か所だけ違ったらイケるやつや」でごまかした。暗号化手順と復号化手順が違う奴でやったらあかんやつやで。rubocopに処刑されそう。

Base64してるのはファイルに書くときそうしないと困るでそってことです。ここではしてませんが目的は「暗号化したのファイルに吐いたり、読み込んだのを復号化」で、やるための目途を付けるためのコードですな。 まぁ……ファイルから読んだときはforce_encodingとか"Salted__"系の文字列付ける対応(OpenSSL絡み)しといたほうが良いのかな、程度の話はあると思うのですが。というか"Salted__"の文言については「どっかで入る」程度のことしか知らないので明日か明後日か死ぬまでには調べますたぶん。使わんかも知らんけど。

暗号化されたファイルをイジって爆死、Salt触って無事死亡、なんとかしろください →

(´・ω・`) 知らんがな

きっとあるんだろうなあ……。

あと文字列系に関するRubyのおもてなし度の高さがイカれすぎててワロス。あの人ら菩薩か。