【Node.js】bcryptのラウンド数による処理時間の計測

こんにちは、フリーランスエンジニアの太田雅昭です。

bcryptでのラウンド数

ユーザーのパスワードをDBに保存する場合に、一度ハッシュ化する必要があります。その際のセキュリティを向上させるために、ソルトを用いるのですが、bcryptライブラリでは、ラウンド数を指定するだけで勝手に良いようにやってくれるようです。

ラウンド数が増えるほどセキュリティは向上しますが、その分処理時間が増えます。というより、処理時間がかかるからこそのセキュリティの向上ですが。生成に時間がかかると、悪意ある攻撃者に万が一ハッシュ値が漏れてしまった場合に、攻撃者がパスワードを検証する時間が増えるためです。

計測してみた

bcryptでのラウンド数ごとに計測してみました。なお現実的に使用する可能性のある範囲のみで行なっています。GPT4が生成したコードそのままです。

*使用プラグインのバグか、正常に表示されないため、言語指定を外しています。

コード

const bcrypt = require('bcrypt');
const password = 'examplePassword';

async function hashPassword(rounds) {
const start = Date.now();
const hash = await bcrypt.hash(password, rounds);
const end = Date.now();
return end - start; // 処理時間をミリ秒で返す
}

async function compareRounds() {
const times = [];
for (let rounds = 1; rounds <= 15; rounds++) {
const time = await hashPassword(rounds);
times.push({ rounds, time });
}
return times;
}

compareRounds().then((times) => {
console.log('各ラウンド数の処理時間:', times);
});

結果(Mac M2)

各ラウンド数の処理時間: [
{ rounds: 1, time: 1 },
{ rounds: 2, time: 1 },
{ rounds: 3, time: 1 },
{ rounds: 4, time: 1 },
{ rounds: 5, time: 2 },
{ rounds: 6, time: 3 },
{ rounds: 7, time: 6 },
{ rounds: 8, time: 13 },
{ rounds: 9, time: 26 },
{ rounds: 10, time: 50 },
{ rounds: 11, time: 101 },
{ rounds: 12, time: 202 },
{ rounds: 13, time: 403 },
{ rounds: 14, time: 807 },
{ rounds: 15, time: 1631 }
]

一般的には10が使用されるようですが、CPUも進歩していっているので、12あたりを使用しようと考えています。サーバースペックにもよりますが、これくらいなら12でも良さそうかなと思っています。15はさすがに厳しいですね。

余談

一時期チューハイにハマったのですが、今はウィスキーにハマっています。チューハイはやっぱり糖分が気になりますね。その点、ウィスキーなら糖分なしでちびちび行けるので、いいなと。