CSVとBase64とOpenSSL::Cipherを組み合わせる
追記:色々直しました。引数にファイル名が必須でしたが、標準入力も読みます。空のカラムで例外が出ていましたが直しました。復号だけだと意味わからんと思うので暗号化も足しました。
各ライブラリについてはマニュアルを参照のこと。
- OpenSSL http://docs.ruby-lang.org/ja/2.1.0/library/openssl.html
- CSV http://docs.ruby-lang.org/ja/2.1.0/class/CSV.html
- Base64 http://docs.ruby-lang.org/ja/2.1.0/library/base64.html
なお、暗号化モードECBは脆弱性があるので絶対に使ってはいけないそうです。
下記のように使用して(おおよそ)元のCSVが戻ってきたら正常に動作しています。
$ ruby ~/encrypt_csv.rb xx.csv | ruby ~/decrypt_csv.rb
decrypt_csv.rb
# encoding: utf-8
require 'openssl'
require 'base64'
require 'csv'
$cipher = OpenSSL::Cipher.new("AES-128-ECB")
$KEY = 'ABCDEFGHIJKLMNOP'
class String
def decrypt
str = if /=$/ =~ self
$cipher.reset
$cipher.decrypt
$cipher.key = $KEY
ret = $cipher.update(Base64.decode64(self)) + $cipher.final
ret.force_encoding 'utf-8'
ret
else
self
end
end
end
CSV.filter do |cols|
cols.map!{|x|x ? x : ""}.map!(&:decrypt)
end
encrypt_csv.rb
# encoding: utf-8
require 'openssl'
require 'base64'
require 'csv'
$cipher = OpenSSL::Cipher.new("AES-128-ECB")
$KEY = 'ABCDEFGHIJKLMNOP'
class String
def encrypt
return self if self.empty?
$cipher.reset
$cipher.encrypt
$cipher.key = $KEY
Base64.strict_encode64($cipher.update(self) + $cipher.final)
end
end
CSV.filter do |cols|
cols.map!{|x|x ? x : ""}.map!(&:encrypt)
end
今日の知見
CSV.filterは便利。ブロックに与えられる引数(row)はmap!等で書き換えないとoutputに反映されないのがわかった。