Ruby2.3.0p0で動作していた古いサービスがあります。
そのサービスのユーザデータは全てデータベース(MySQL)に保存されており、パスワードがRubyのString#cryptによって暗号化されて保存されていることがわかりました。
プロジェクトファイルのconfigには暗号化に必要なsalt文字列も記載されていたのでString#cryptで利用されている暗号化アルゴリズムとconfigに記載されているsaltを利用すれば異なる環境でも同じ暗号化文字列を出力することができると考えています。
現在、サービスの環境をrubyからnodeに切り替えている最中なのですが、古いサービスと新しいサービスとでパスワードの暗号化アルゴリズムが異なっています。
そのため、ユーザデータを新しい環境(node)に移しただけでは当然ログインすることができませんでした。
この問題を解決したいと考えています。
ちなみに、新しい環境(node)は、まだ開発段階なので現在は特に何も考えずSHA256を利用しています。
そこで皆様に以下の質問があります。
- node環境でRubyのString#cryptと同じアルゴリズムの暗号化関数を使うにはどうすれば良いですか?
- パスワードの暗号化に使うアルゴリズムはSHA256で問題ないですか?
ここからは作業の履歴になりますが、1に関しまして調査したところDESまたはcrypt(3)というアルゴリズムが使われているのかな?と推測しているのですが、暗号化についてあまり詳しくないために確証が持てていません。
わからないならとにかくやってみよう!と思い、とりあえずDESアルゴリズムが利用できる暗号化モジュールを探してみたところ以下が見つかりました。
node-crypt3
https://github.com/sendanor/node-crypt3
node-ffi
http://stackoverflow.com/questions/22401920/how-to-do-unix-crypt3-in-javascript
https://github.com/node-ffi/node-ffi
crypto
https://nodejs.org/api/crypto.html
あれこれ考えたのですが、最後に掲載させていただいたcryptoはnode標準の暗号化モジュールのため、ベターな選択だと思いましたので、まずはこれで試してうまくいかなければ他の方法を考えようと思いました。
cryptoについていろいろと調べているとcrypto.getCiphers()
メソッドを実行することにより利用できるアルゴリズムの一覧を取得できることがわかりましたので実行してみました。すると以下のような結果が返ってきました。
[ 'aes-128-cbc', 'aes-128-cbc-hmac-sha1', 'aes-128-cbc-hmac-sha256', 'aes-128-ccm', 'aes-128-cfb', 'aes-128-cfb1', 'aes-128-cfb8', 'aes-128-ctr', 'aes-128-ecb', 'aes-128-gcm', 'aes-128-ofb', 'aes-128-xts', 'aes-192-cbc', 'aes-192-ccm', 'aes-192-cfb', 'aes-192-cfb1', 'aes-192-cfb8', 'aes-192-ctr', 'aes-192-ecb', 'aes-192-gcm', 'aes-192-ofb', 'aes-256-cbc', 'aes-256-cbc-hmac-sha1', 'aes-256-cbc-hmac-sha256', 'aes-256-ccm', 'aes-256-cfb', 'aes-256-cfb1', 'aes-256-cfb8', 'aes-256-ctr', 'aes-256-ecb', 'aes-256-gcm', 'aes-256-ofb', 'aes-256-xts', 'aes128', 'aes192', 'aes256', 'bf', 'bf-cbc', 'bf-cfb', 'bf-ecb', 'bf-ofb', 'blowfish', 'camellia-128-cbc', 'camellia-128-cfb', 'camellia-128-cfb1', 'camellia-128-cfb8', 'camellia-128-ecb', 'camellia-128-ofb', 'camellia-192-cbc', 'camellia-192-cfb', 'camellia-192-cfb1', 'camellia-192-cfb8', 'camellia-192-ecb', 'camellia-192-ofb', 'camellia-256-cbc', 'camellia-256-cfb', 'camellia-256-cfb1', 'camellia-256-cfb8', 'camellia-256-ecb', 'camellia-256-ofb', 'camellia128', 'camellia192', 'camellia256', 'cast', 'cast-cbc', 'cast5-cbc', 'cast5-cfb', 'cast5-ecb', 'cast5-ofb', 'des', 'des-cbc', 'des-cfb', 'des-cfb1', 'des-cfb8', 'des-ecb', 'des-ede', 'des-ede-cbc', 'des-ede-cfb', 'des-ede-ofb', 'des-ede3', 'des-ede3-cbc', 'des-ede3-cfb', 'des-ede3-cfb1', 'des-ede3-cfb8', 'des-ede3-ofb', 'des-ofb', 'des3', 'desx', 'desx-cbc', 'id-aes128-CCM', 'id-aes128-GCM', 'id-aes128-wrap', 'id-aes192-CCM', 'id-aes192-GCM', 'id-aes192-wrap', 'id-aes256-CCM', 'id-aes256-GCM', 'id-aes256-wrap', 'id-smime-alg-CMS3DESwrap', 'idea', ... 19 more items ]
どうやらDESアルゴリズムは種類があるようで、String#cryptがどのアルゴリズムを利用しているのかわかりません。
調べてもDESまたはcrypt(3)以上の情報が見つかりませんでしたので、とりあえず'des'
を試してみようと思いました。
実行したコードは以下になります。
node
1var cipher = crypto.createCipher('des', 'salt here'); 2cipher.update('password here') 3// <Buffer 80 05 eb a7 29 9e 83 59>
結果がバッファ(バイナリ?)で出力されてしまったようなのですが、String#cryptの暗号化文字列はutf-8で出力されているようなのでutf-8で出力したいです。
調べてみるとこちらでは以下のようにupdate()
メソッドをコールしていましたので同じように実行してみました。
cipher.update('password here', 'utf8', 'hex') // '390910129cef7a1c'
うまくいったか!?と期待したのですが、どうやらString#cryptとそれに利用されているsaltを使って出力した文字列とは異なるようでした。
そもそも、RubyのString#cryptが出力する文字列は'ha4NAXDFh4S3c'
のような文字列であり、上記の出力結果はどうみても16進数の数値文字列になっているように見えます。
引数に'hex'
を指定しているので当然だろうということで、引数を削ってみたのですがうまく出力できませんでした。
こういう時はドキュメントをしっかり読むことが大切だと思いましてここら辺を見てみると、どうやらencodingはutf8
以外にascii
やlatin1
を指定できるようで、また出力方法もhex
以外にlatin1
やbase64
が指定できるようでした。
ここまで試したところで少し疲れてしまいまして、パターンが多すぎて混乱しています。そもそもものすごく簡単なことを遠回りに実装しているような気もしてきました。
一体、RubyのString#cryptと同じ暗号化文字列をnode.jsで出力するにはどうすれば良いのでしょうか。
以下の質問事項
- node環境でRubyのString#cryptと同じアルゴリズムの暗号化関数を使うにはどうすれば良いですか?
- パスワードの暗号化に使うアルゴリズムはSHA256で問題ないですか?
に加えて、何か気になることがございましたら指摘していただけると助かります。
宜しくお願いいたします。m(_ _)m
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。