Madogiwa Blog

主に技術系の学習メモに使っていきます。

`zxcvbn`のモダンな代替ライブラリ`zxcvbn-ts`を使ってパスワード強度を測定するメモ📝

ユーザーに安全なパスワードの設定を促すために強度を測定しフィードバックしたいといった時にDropbox製のzxcvbnがよく使われていると思います。

github.com

ただ、このライブラリのサイズが大きかったりメンテナンスに不安があったりと、

So, I came across this library and was very excited to put it to use. I pulled it down via npm and was shocked to find the minified dist script is 823kb. That's insane. Dist size (JavaScript) makes this lib unusable in a client · Issue #169 · dropbox/zxcvbn · GitHub

代替ライブラリを探していたところzxcvbn-tsというライブラリを使うとLazy Loading等が使えていい感じに使えそうだったので使い方をメモ📝

github.com

zxcvbn-tsとは?

以下の通りzxcvbnを再実装したライブラリとのこと。

This is a complete rewrite of zxcvbn in TypeScript which is licensed under the MIT license.
Introduction | zxcvbn-ts

完全に再現しているわけではなく微妙にスコアが違うみたいなのでzxcvbnからの乗り換えを行う場合には参照しておくと良さそうです。

zxcvbn-ts.github.io

zxcvbn-tsのinstall

以下のページの通りですが、

zxcvbn-ts.github.io

以下のコマンドでインストールできます。

npm install @zxcvbn-ts/core @zxcvbn-ts/language-common --save

各国のよくある名前とかの辞書を取り込みたい場合には以下から任意の国の辞書情報を取り込むこともできます。

github.com

zxcvbn-tsを利用する

以下がzxcvbn-tsを利用してパスワードの文字列を受け取ってスコアの数値を返却するサンプル実装です。 zxcvbnOptionsを使ってoptionを設定する感じ以外はzxcvbnとほとんど同じように使うことができます。

import { zxcvbn, zxcvbnOptions, type OptionsType } from "@zxcvbn-ts/core";
import { adjacencyGraphs, dictionary } from "@zxcvbn-ts/language-common";

const defaultOption: () => OptionsType = () => {
  return { graphs: adjacencyGraphs, dictionary };
};

export const calcPasswordStrengthScore = (password: string): number => {
  const options = defaultOption();
  zxcvbnOptions.setOptions(options);
  return zxcvbn(password).score;
};

zxcvbn-tsの辞書情報等を遅延読み込みさせる

辞書情報等はサイズが大きいのでパフォーマンス等の問題で実際に利用するまで読み込ませたくないときもあるかもですが、zxcvbn-tsは遅延読み込みにも対応しているようです。

zxcvbn-ts.github.io

以下が@zxcvbn-ts/language-commonを遅延importして利用時に読み込むようにしたサンプルです。 ※私はviteを使っているので、別のmodule bundlerを利用している場合には微妙にコードを修正する必要があるかもです。

import { zxcvbn, zxcvbnOptions, type OptionsType } from "@zxcvbn-ts/core";

const defaultOption: () => Promise<OptionsType> = async () => {
  const common = await import("@zxcvbn-ts/language-common");
  return { graphs: common.adjacencyGraphs, dictionary: common.dictionary };
};

export const calcPasswordStrengthScore = async (password: string): Promise<number> => {
  const options = await defaultOption();
  zxcvbnOptions.setOptions(options);
  return zxcvbn(password).score;
};

おわりに

zxcvbn-ts、遅延ローディングも対応してるのとアクティブにメンテナンスされているようて良さそうですね✨