rubyでopenSSLを使う in Mac OS X
一眠りしてから書きました。実行した環境は以下の通りです。
とりあえず暗号文を表示するためのメソッドを用意します。暗号文をprintするとちゃんと見えないので。
def bin_dump(str, num) num.times do |i| str[i].bytes { |b| print b.to_s(16) } end puts "" end
"/dev/random"を使って暗号化鍵を生成する
暗号鍵を生成するクラスを作ってみました。こんな感じです。
require 'openssl' def bin_dump(str, num) num.times do |i| str[i].bytes { |b| print b.to_s(16) } end puts "" end class Create_key def initialize(alg) @cip = OpenSSL::Cipher.new(alg) OpenSSL::Random.load_random_file("/dev/random") end #乱数シード変更 def ch_seed OpenSSL::Random.load_random_file("/dev/random") end #イニシャライズベクタ生成 def iv_gen return @cip.random_iv end #鍵生成 def key_gen return @cip.random_key end #鍵長を返す def key_len return @cip.key_len end end #このプログラムが単体で実行される場合のみ以下を実行 if __FILE__ == $0 ck = Create_key.new("aes-256-cbc") key = ck.key_gen len = ck.key_len print "len = ", len, "\n" bin_dump(key, len) end
実行結果
bash-3.2$ ruby create_key.rb len = 32 cf3dced495f690584a388d2556f87bf10612ab9ffa891cc4dde407175ebb2ad
スペシャルファイル"/dev/random"を乱数シードとして使っています。処理が返ってこない場合はかわりに"/dev/urandom"を使いましょう。少なくともubuntuでは処理が返ってこなくなりました。"if __FILE__ == $0"はコメントにあるようにこのプログラムが単体で実行された場合にのみ、実行されます。だからほかのプログラムからこのクラスを使ったりした場合は無視されるんですよ。便利だね〜。
"/dev/random"とはなにかやなんで処理が返ってこなくなるかはLet's google!
文字列の暗号化と復号を行う
require 'openssl' require './create_key' def bin_dump(str, num) num.times do |i| str[i].bytes { |b| print b.to_s(16) } end puts "" end class Crypto def initialize(key = nil, iv = nil, alg = "aes-128-cbc") @cip = OpenSSL::Cipher.new(alg) @key = key @iv = iv end def encrypt(s) if @key != nil && @iv != nil @cip.encrypt #暗号化モード @cip.key = @key #鍵セット @cip.iv = @iv #イニシャライズベクタセット @cip.padding = 1 #パディング有効 enc_data = "" enc_data << @cip.update(s) enc_data << @cip.final return enc_data else return nil end end def decrypt(s) if @key != nil && @iv != nil @cip.decrypt #復号モード @cip.key = @key #鍵セット @cip.iv = @iv #イニシャライズベクタセット @cip.padding = 1 #パディング有効 dec_data = "" dec_data << @cip.update(s) dec_data << @cip.final return dec_data else return nil end end end #このプログラムが単体で実行される場合のみ以下を実行 if __FILE__ == $0 plaintext = ARGV[0] ck = Create_key.new("aes-128-cbc") key = ck.key_gen iv = ck.iv_gen c = Crypto.new(key, iv, "aes-128-cbc") ciphertext = c.encrypt(plaintext) if ciphertext != nil print "[ciphertext] : " bin_dump(ciphertext, 16) b = c.decrypt(ciphertext) p b else print "error\n" end end
実行結果
bash-3.2$ ruby crypto.rb megane [ciphertext] : 9c2bf5bfe43e984852eaec4b111c7229 "megane"
さっきの鍵生成プログラムをrequireして、暗号鍵と初期化ベクタを生成します。それでもって暗号化したり、復号したりします。実際使う場合は作った鍵をファイルに保存して厳重に管理しましょう。
深く考えずに作ったので色々至らない点もあるかもしれないっす。そしてここまで作って、ClassじゃなくてModuleにした方が良かったのではと思いました。 まぁあとは後々修正していきましょう!