Ruby-OpenSSL暗号化

OpenSSL暗号

さまざまな暗号化アルゴリズムをサポートしているOpenSSLをRubyから扱うことができます。

各暗号方式については、下記URLを参照してください。

http://doc.ruby-lang.org/ja/1.9.2/library/openssl.html


saltについて

パスワードを記録するときに、例え同じパスワードを設定しても、その暗号化結果を異ならせることを目的としてパスワードに任意に付加するデータをSaltといいます。


IV(Initialization Vector)

IVとは初期化ベクトルです。

初期化ベクトルは暗号を任意の暗号利用モードで実行するとき、同じ暗号鍵でストリームを生成しても毎回異なるストリームを生成するのに必要とされます。

毎回暗号鍵を替えるといった時間のかかる作業を省くことができます。


サンプルプログラム

サンプル

saltはランダムな 8byte の文字列(バイト列)となります。

鍵や初期化ベクトルを直接設定する必要はないので、初期化ベクトルは使用していません。


updateメソッドは渡されたデータを暗号化して返しますが、暗号化は固定長(AES-256-CBCは16byte)のブロック単位で行われます。

固定長に満たない文字列分はcipherオブジェクト内部にバッファリングされますので、finalメソッドを呼ぶことで、バッファにある残りのデータを暗号化する必要があります。


 require 'openssl'

 class Cipher
   def cipher_init()
     @cipher = "aes-256-cbc"
     @salt   = OpenSSL::Random.random_bytes( 8 )
   end

   def encrypt( data, passwd )
     enc = OpenSSL::Cipher::Cipher.new( @cipher )
     enc.encrypt
     enc.pkcs5_keyivgen( passwd, @salt )
     enc_data = enc.update( data ) + enc.final
     return( enc_data )
   end

   def decrypt( data, passwd, salt )
     enc = OpenSSL::Cipher::Cipher.new( @cipher )
     enc.decrypt
     enc.pkcs5_keyivgen( passwd, @salt )
     dec_data = enc.update( data ) + enc.final
     return( dec_data )
   end
 end

saltを暗号データとして保存しておく場合


#!/usr/bin/env ruby -Ku
# crypt.rb

require "openssl"

module Crypt
  class Cipher
    def initialize()
      # AES暗号方式
      @cipher_mode = "aes-256-cbc"
    end

    #!
    # @brief     暗号化する
    # @param[in] data          暗号化するデータ
    # @param[in] passwd        パスワード
    # @return    padding_data  saltを含んだ暗号データ
    # @note      pad_data = salt(8bytes) + data
    #
    def encrypt( data, passwd )
      begin
        salt = OpenSSL::Random.random_bytes( 8 )
        enc_data = encrypt_data( data, passwd, salt )
        padding_data = salt + enc_data
      rescue
        padding_data = nil
      end
      return( padding_data )
    end

    #!
    # @brief     復号化する
    # @param[in] data          暗号データ
    # @param[in] passwd        パスワード
    # @return    dec_data      復号データ
    # @note      data = salt(8bytes) + data
    #
    def decrypt( data, passwd )
      begin
        salt = data[0,8]
        dec_data = decrypt_data( data[8,data.size], passwd, salt )
      rescue
        dec_data = nil
      end

      return( dec_data )
    end

    private

    #!
    # @brief     暗号化する
    # @param[in] data       暗号化するデータ
    # @param[in] passwd     パスワード
    # @param[in] salt       SALTデータ(8Bytes)
    # @return    enc_data   暗号データ
    #
    def encrypt_data( data, passwd, salt )
      enc = OpenSSL::Cipher::Cipher.new( @cipher_mode )
      enc.encrypt
      enc.pkcs5_keyivgen( passwd, salt )
      enc_data = enc.update( data ) + enc.final
      return( enc_data )
    end

    #!
    # @brief     復号化する
    # @param[in] data       暗号データ
    # @param[in] passwd     パスワード
    # @param[in] salt       SALTデータ(8Bytes)
    # @return    dec_data   復号データ
    #
    def decrypt_data( data, passwd, salt )
      dec = OpenSSL::Cipher::Cipher.new( @cipher_mode )
      dec.decrypt
      dec.pkcs5_keyivgen( passwd, salt )
      dec_data = dec.update( data ) + dec.final
      return( dec_data )
    end
  end
end

関連ページ