3

組み込み関数 AES_ENCRYPT() および AES_DECRYPT() を使用して文字列を暗号化および復号化するときに MySQL が行うことを模倣する必要があります。

いくつかのブログ投稿を読みましたが、どうやら MySQL はこれらの機能に AES 128 ビット暗号化を使用しているようです。さらに、この暗号化には 16 ビット キーが必要なため、MySQL は、サイズが 16 ビットになるまで文字列に x0 文字 (\0s) を埋め込みます。

MySQL のソース コードから C で記述されたアルゴリズムは、ここで確認できます。

今度は MySQL が Rails アプリケーションで行うことを再現する必要がありますが、私が試したすべてのことはうまくいきません。

私が得ている動作を再現する方法は次のとおりです。

1) 新しい Rails アプリを作成する

rails encryption-test
cd encryption-test

2) 新しい足場を作成する

script/generate scaffold user name:string password:binary

3) config/database.yml を編集し、テスト MySQL データベースを追加します。

development:
    adapter: mysql
    host: localhost
    database: test
    user: <<user>>
    password: <<password>>

4) 移行を実行する

rake db:migrate

5) コンソールに入り、ユーザーを作成し、MySQL クエリからパスワードを更新します

script/console
Loading development environment (Rails 2.2.2)
>> User.create(:name => "John Doe")
>> key = "82pjd12398JKBSDIGUSisahdoahOUASDHsdapdjqwjeASIduAsdh078asdASD087asdADSsdjhA7809asdajhADSs"
>> ActiveRecord::Base.connection.execute("UPDATE users SET password = AES_ENCRYPT('password', '#{key}') WHERE name='John Doe'")

それが私が立ち往生したところです。MySQL を使用して復号化しようとすると、次のように機能します。

>> loaded_user = User.find_by_sql("SELECT AES_DECRYPT(password, '#{key}') AS password FROM users WHERE id=1").first
>> loaded_user['password']
=> "password"

ただし、OpenSSL ライブラリを使用しようとしても、それを機能させる方法はありません。

cipher = OpenSSL::Cipher::Cipher.new("AES-128-ECB") 
cipher.padding = 0
cipher.key = key
cipher.decrypt 

user = User.find(1)
cipher.update(user.password) << cipher.final #=> "########gf####\027\227"

キーをパディングしてみました:

desired_length = 16 * ((key.length / 16) + 1)
padded_key = key + "\0" * (desired_length - key.length)

cipher = OpenSSL::Cipher::Cipher.new("AES-128-ECB") 
cipher.key = key
cipher.decrypt 

user = User.find(1)
cipher.update(user.password) << cipher.final #=> ""|\e\261\205:\032s\273\242\030\261\272P##"

しかし、それは本当にうまくいきません。

RubyでMySQL AES_ENCRYPT()およびAES_DECRYPT()関数の動作をどのように模倣できるかについての手がかりはありますか?

ありがとう!

4

3 に答える 3

1

通常、キーをパディングしたくないので、暗号化/復号化するデータをパディング/アンパディングします。それが問題の別の原因になる可能性があります。この可能性を排除するために、完全な数のブロックのテスト データを使用することをお勧めします。

また、OpenSSL API のキーには、コードにあるキーの ASCII 表現ではなく、「リテラル」キーが必要であると思われます。

OpenSSL の ruby​​ ドキュメントが不足していて、Java を少し話せる場合は、BouncyCastle プロバイダーを使用して JRuby でプロトタイプを作成することをお勧めします。これは、TwoFish (OpenSSL API には存在しない) を使用するときに効果を発揮するために行ったことです。 .

編集:キーのパディングに関するコメントを読み直しました。質問にはビット/バイトの混乱があります。投稿されたキーの長さは89文字(712ビット)であるため、これがどのような場合にどのように適用されるかわかりません。おそらく、このパディング現象を解消するために 128 ビットのキー/パスワードを試してみるべきでしょうか?

ちなみに、MySQL 開発者は弱い暗号のために叩かれる必要があります。単純に 0 バイトでパディングするよりも、パスワードを拡張するためのより良い方法があります :(

于 2009-03-23T22:07:15.487 に答える
0

openssl 実装の使用を気にしない場合、attr_encryptedは、ActiveRecord かどうかに関係なく、ほとんどのクラスでドロップイン暗号化を許可する gem です。残念ながら、MySQL の AES_EN/DECRYPT 関数とは互換性がありません。

于 2010-10-27T21:59:58.703 に答える