20
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PHPのMcrypt関数でencryptしたデータをRubyでdecryptする

Last updated at Posted at 2014-06-13

過去にPHPでencryptしてDBに突っ込まれたデータを、
今回Rubyでdecryptする際に結構はまったので。

encrypt

PHP側のコードはだいたいこんな感じ
暗号方式は 3DES ECB だった。

mcrypt.php
<?php
$mcrypt_key = 'hoge'; #3DESの規定キー長より短い
$plaintext = 'あいうえお'; #マルチバイト文字

$td = mcrypt_module_open(MCRYPT_TRIPLEDES, '', MCRYPT_MODE_ECB, '');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $mcrypt_key, $iv);

$ciphertext = mcrypt_generic($td, $plaintext);

# 表示の関係上base64エンコード
echo base64_encode($ciphertext);

実行結果:QERSswy6yzBsSrZfRxS+ow==

ポイントは

  • キー長が短い(エラーにならない)
  • マルチバイト文字

decrypt

で、ruby側。バージョンは1.9.3
今回はruby-mcryptを利用。

mcrypt.rb
# -*- encoding:utf-8 -*-
require 'mcrypt'
require 'base64'

mcrypt_key = 'hoge'
ciphertext = 'QERSswy6yzBsSrZfRxS+ow=='

crypto = ::Mcrypt.new(:tripledes, :ecb)
# キー長が足りない分は \0 で埋める
if mcrypt_key.length < crypto.key_size
  mcrypt_key = mcrypt_key.ljust(crypto.key_size, "\0")
end
crypto.key = mcrypt_key
crypto.iv = nil
crypto.padding = :zeros

plaintext = crypto.decrypt(::Base64.decode64(ciphertext))
# decrypt結果の文字コード情報をUTF-8にする
p plaintext.force_encoding('utf-8')
実行結果:あいうえお
  • キー長が短い場合は \0 で埋める(そのままだとエラーになる)
  • decryptの結果は ascii-8bit になってるので適宜encodingの変更をする

余談

OpenSSL::Cipherでも試してみた。

キーの\0埋めや最後のforce_encodingはこちらも同様。
ただ、paddingの方式がOpenSSLの場合PKCS#5で固定(?)で
PHPのMcryptは \0 埋めが固定(?)みたいなので、OpenSSL側でのpaddingをせずに自前で除去する必要がありそう。

openssl.rb
# -*- encoding:utf-8 -*-
require 'openssl'
require 'base64'

mcrypt_key = 'hoge'
ciphertext = 'QERSswy6yzBsSrZfRxS+ow=='

crypto = ::OpenSSL::Cipher.new('des-ede3')
crypto.decrypt
# キー長が足りない分は \0 で埋める
if mcrypt_key.length < crypto.key_len
  mcrypt_key = mcrypt_key.ljust(crypto.key_len, "\0")
end
crypto.key = mcrypt_key
# 明示的にpaddingを無効
crypto.padding = 0

plaintext = crypto.update(::Base64.decode64(ciphertext))
# 末尾の\0を除去し、文字コード情報をUTF-8にする
p plaintext.sub(/\0*\Z/, '').force_encoding('utf-8')
実行結果:あいうえお
20
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?