Help us understand the problem. What is going on with this article?

Node.jsで暗号化とハッシュ

More than 5 years have passed since last update.

暗号化とハッシュ

  • ハッシュとは、平文から固定長の疑似乱数を生成する演算手法。
  • 暗号化とは、第3者に内容を知られないように、規則に従ってデータを変換すること。

Node.jsでの暗号化とハッシュ

モジュールの読み込み

Node.jsをインストールすれば、cryptoモジュールが使えます。
次の様にモジュールを読み込みます。

var crypto = require("crypto");

cryptoがサポートする暗号化アルゴリズム

cryptoで使える暗号化アルゴリズムは、crypto.getCiphers()メソッドで取得できます。

// cryptoで使える暗号化アルゴリズムを配列で取得する
var cipers = crypto.getCiphers();

console.log(cipers);

実行すると、

$ node app.js
[ 'CAST-cbc',
  'aes-128-cbc',
 :
 :
  'seed-ecb',
  'seed-ofb' ]

cryptoがサポートするハッシュアルゴリズム

cryptoで使えるハッシュアルゴリズムは、crypto.getHashes()メソッドで取得できます。

// サポートするハッシュアルゴリズムを配列で取得する。
var hashes = crypto.getHashes();

console.log(hashes);

実行すると、

$ node app.js
[ 'DSA',
  'DSA-SHA',
 :
 :
  'ssl3-sha1',
  'whirlpool' ]

cryotoで暗号化

以下、cryptoでAES192アルゴリズムを使用した暗号化と復号化です。

var crypto = require("crypto");

var planeText = 'This is Plane Text';
var passowrd = 'passw0rd';

console.log('暗号化するテキスト : ' + planeText);
console.log('暗号化キー        : ' + passowrd);

// 暗号化
var cipher = crypto.createCipher('aes192', passowrd);
cipher.update(planeText, 'utf8', 'hex');
var cipheredText = cipher.final('hex');

console.log('暗号化(AES192) :');
console.log(cipheredText);

// 復号
var decipher = crypto.createDecipher('aes192', passowrd);
decipher.update(cipheredText, 'hex', 'utf8');
var dec = decipher.final('utf8');

console.log('復号化(AES192) : ');
console.log(dec);

crypto.createCipher(algorithm, password)

引数にアルドリズムとキーを与えて、暗号オブジェクトを作成する。

  • 引数

    • algorithm 暗号化するアルゴリズムで、このアルゴリズムはOpenSSLに依存します。
    • password 暗号化・復号化で使用するキー
  • 返り値
    暗号オブジェクト

cipher.update(data, [input_encoding], [output_encoding])

dataで暗号を更新する。

  • 引数
    • data 更新するデータ
    • input_encoding 'utf8', 'ascii' or 'binary'が指定できる
    • output_encoding 暗号化されたデータの出力形式。'binary', 'base64' or 'hex'が指定できる。

cipher.final([output_encoding])

暗号化されたデータを取得する。
※ finalメソッドが呼び出された後、暗号オブジェクトは使えません。

  • 引数

    • output_encoding 'binary', 'base64' or 'hex'を指定できる。
  • 返り値
    暗号化されたデータ

crypto.createDecipher(algorithm, password)

引数にアルゴリズムとパスワードを与えて、復号オブジェクトを作成する。

  • 引数

    • algorithm 復号化するアルゴリズムで、このアルゴリズムはOpenSSLに依存します。
    • password 暗号化・復号化で使用するキー
  • 返り値
    復号オブジェクト

decipher.update(data, [input_encoding], [output_encoding])

エンコードされた復号データを更新する。

  • 引数
    • data 更新するデータ
    • input_encoding 'utf8', 'ascii' or 'binary'が指定できる
    • output_encoding 復号化されたデータの出力形式。'binary', 'base64' or 'hex'が指定できる。

decipher.final([output_encoding])

復号化されたプレーンテキストを取得する。
※ finalメソッドが呼び出された後、復号オブジェクトは使えません。

  • 引数

    • output_encoding 'binary', 'ascii' or 'utf8'を指定できる。
  • 返り値
    復号化されたデータ

実際に実行すると

$ node app-cipher.js
暗号化するテキスト : ThisisPlaneText
暗号化キー        : passw0rd
暗号化(AES192) :
df8fba3165b241ccf50aaa2c3aabc0ca
復号化(AES192) : 
ThisisPlaneText

cryptoでハッシュ値を求める

以下、cryptpでsha512アプゴリズムを使用たハッシュ値の算出

var crypto = require("crypto");

var password ='passowrd';

var sha512 = crypto.createHash('sha512');
sha512.update(password)
var hash = sha512.digest('hex')

console.log(hash);

crypto.createHash(algorithm)

指定したアルゴリズムでハッシュオブジェクトを作成する。

  • 引数

    • algorithm ハッシュ化するアルゴリズム。OpenSSL のバージョンでサポートされている利用可能なアルゴリズムに依存。
  • 返り値

ハッシュオブジェクト

hash.update(data, [input_encoding])

与えられた data でハッシュの内容を更新します。

  • 引数

    • input_encoding 'utf8', 'ascii' or 'binary'を指定できる。
  • 返り値
    ハッシュオブジェクト

hash.digest([encoding])

ハッシュするために渡されたすべてのデータのダジェストを計算する。
※ digest()メソッドが呼ばれた後、ハッシュオブジェクトは使えない。

  • 引数

    • encoding 'hex', 'binary' or 'base64'が指定できる。
  • 返り値
    ハッシュ化された値

実行すると、

$ node app-hash.js 
91583dac4a1574f0fba6a71decb149101b9ed67402b84f1bcfbf529a742948e4381960ec00715b6b7c6aa721b811a703fc8b13ebc3d3f90641e00848ef06e080

BCryptでハッシュ化

MD5やSHAは高速に実行できる様に設計されていて、レインボーテーブルの作成が容易で攻撃者が1秒間に何回ものブルートフォースを試みることができるらしい。だからあまりセキュアでないとのこと。

Bcryptアルゴリズムは、汎用的なアルゴリズム(SHA、MD5など)より意図的に計算量を増やしてて、「オフライン総あたり攻撃」に強い特性を持っているとのこと。
よりセキュアにハッシュ化できるアルゴリズムがBCryptの様です。とりあえず使ってみる。

Bcryptのインストール

npm install bcrypt

このモジュールのもつAPIには同期で処理できるものと非同期で処理できるものがある様です。
詳細はGitHubのページに記載してあります。

とりあえず、非同期で試してみました。

var bcrypt = require('bcrypt');

bcrypt.genSalt(10, function(err, salt) {
    bcrypt.hash("B4c0/\/", salt, function(err, hash) {

        console.log(hash);

        // To check a password:   
        bcrypt.compare("B4c0/\/", hash, function(err, res) {
            // res == true
            console.log("equal")
            console.log(res);
        });

        bcrypt.compare("not_bacon", hash, function(err, res) {
            // res == false
            console.log("not equal");
            console.log(res);
        });
    });
});

// Auto-gen a salt and hash:
bcrypt.hash('bacon', 8, function(err, hash) {
    console.log(hash);
});

genSalt(rounds, cb)

非同期でSALTを取得する。

  • 引数
  • rounds - [オプション] - データの処理コスト. (default - 10)
  • cb - [必須] - SALTが生成された後、発火されるコールバック。
    • コールバックの引数
      • err - 最初のパラメータはエラーの詳細
      • salt - 2つ目のパラメータは生成されたSALTを提供する。

hash(data, salt, cb)

与えられえたデータとSALTからハッシュを計算する。

  • 引数
    • data - [必須] - 暗号化するデータ
    • salt - [オプション] - ハッシュするために使用するSALT。
    • cb - [必須] - データがハッシュ化された時に発火するコールバック
      • コールバックの引数
        • err - 最初のパラメータはエラーの詳細
        • encrypted - 2つ目のパラメータはハッシュ化された値

compare(data, encrypted, cb)

データとハッシュ化された値を比較する。

  • 引数
    • data - [必須] - 比較するデータ
    • encrypted - [必須] - 比較するデータ(ハッシュ値)
    • cb - [必須] - 比較した結果、コールバックが発火する。
      • コールバックの引数
        • err - 最初のパラメータはエラーの詳細
        • same - 2つ目のパラメータは比較した結果[true or false]

実行すると、

$ node app-bcrypt.js 
$2a$08$vj/8fY70VkEmVab/czGJ8euRvsGo0q0T5ETDKUusCXMXytYXeCKkC
$2a$10$LLsJqwOAirlXQW5DVt1pDeyPTWM5qoooqHjkAjA68iIp2mpcCfdZ2
not equal
false
equal
true

_daisuke
個人的な技術系の覚え書きなどを公開していきます。 最近の興味はAWS / IBM Bluemix。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした