C++ でパスワード生成機を作る

(1/1)
C++でパスワード生成機を作る
PHPでパスワードを生成」で作ったパスワード生成機をC++に移植する。
パスワード文字は、英大文字、英小文字、数字、記号の1つまたは複数を組み合わせ、任意の長さのパスワードを生成する。生成したパスワードはクリップボードにコピーできるようにする。

作ったパスワードは、「C++ でパスワードの強度を調べる」で強さを調べてみてほしい。
CUI版 "mkpsw.exe" を用意した。GUI版と同じディレクトリにインストールされる。コマンドラインから実行することを想定している。
たとえば "mkpsw -l11 -u -a -n -s -p" のようなバッチを用意しておくと、このバッチを実行するだけで、「英大文字・小文字、数字、記号を混在させた11桁のパスワードをクリップボードにコピーする」という処理ができる。あとは、パスワード入力テキストボックスに、[ctrl+P]でペーストしてやるだけでいい。

(2024年11月3日)使用ライブラリ更新
(2024年7月7日)使用ライブラリ更新
(2024年2月17日)使用ライブラリ等を更新

目次

サンプル・プログラム

圧縮ファイルの内容
makepassword.msiインストーラ
bin/makepassword.exe実行プログラム本体
bin/etc/help.chmヘルプ・ファイル
sour/makepassword.cppソース・プログラム
sour/resource.hリソース・ヘッダ
sour/resource.rcリソース・ファイル
sour/application.icoアプリケーション・アイコン
sour/makefileGUI版ビルド
sour/makefile_cmdCUI版ビルド
makepassword.cpp 更新履歴
バージョン 更新日 内容
1.2.7 2024/11/03 使用ライブラリ更新
1.2.6 2024/07/07 使用ライブラリ更新
1.2.5 2024/02/17 使用ライブラリ更新
1.2.4 2023/10/09 使用ライブラリ更新
1.2.3 2023/06/03 使用ライブラリ更新

リソースの準備

Eclipse を起動し、新規プロジェクト makepassword を用意する。
ResEdit を起動し、resource.rc を用意する。
Eclipse に戻り、ソース・プログラム "makepassword.cpp" を追加する。
リンカー・フラグを "-mwindows -static -lole32 -lboost_program_options-mt -lpthread -lwinpthread" に設定する。

MSYS2 コマンドラインからビルドするのであれば、"makefile" と "makefile_cmd" を利用してほしい。

使用ライブラリ

今回は、オープンソースのライブラリ Boost C++ライブラリを使用する。導入方法等については、「C++ 開発環境の準備」をご覧いただきたい。

解説:乱数

makepassword.cpp

  41: //char*バッファサイズ
  42: #define SIZE_BUFF       512
  43: 
  44: //標準フォント
  45: #define FONT_FACE       "MS UI Gothic"
  46: 
  47: //現在のインターフェイス
  48: HINSTANCE hInst;
  49: 
  50: //アプリケーション・ウィンドウ
  51: HWND hParent;
  52: 
  53: //アプリケーション・ウィンドウ位置
  54: unsigned hParent_X, hParent_Y;
  55: 
  56: //エラー・メッセージ格納用
  57: string ErrorMessage;
  58: 
  59: //ヘルプ・ファイル
  60: #define HELPFILE    ".\\etc\\help.chm"
  61: 
  62: //オプション
  63: #define OPTION_UPPER    'u'     //英大文字
  64: #define OPTION_LOWER    'a'     //英小文字
  65: #define OPTION_NUMBER   'n'     //数字
  66: #define OPTION_SYMBOL   's'     //記号
  67: 
  68: //パスワードに使う文字セット
  69: const string Seed[] = {
  70:     "ABCDEFGHIJKLMNOPQRSTUVWXYZ",       //英大文字
  71:     "abcdefghijklmnopqrstuvwxyz",       //英小文字
  72:     "0123456789",                       //数字
  73:     "()%$#+-*"                          //記号
  74: };
  75: 
  76: //オプションの初期値
  77: #define OPTION_INIT     "an"
  78: 
  79: //生成するパスワードの最小桁数と最大桁数
  80: #define MIN_PASSWORD    4
  81: #define MAX_PASSWORD    20
  82: 
  83: //パスワード長
  84: unsigned PswLen = MIN_PASSWORD;
  85: 
  86: //乱数関係
  87: std::random_device rnd;         //非決定的な乱数生成器を生成
  88: std::mt19937 mt((int)time(0));  //メルセンヌ・ツイスタの32ビット版+シード

パスワードに使う文字セットは配列 Seed に用意する。
生成するパスワードの最小桁数と最大桁数を定義する。
文字列を操作するために、char*バッファのサイズを SIZE_BUFF に定義する。

疑似乱数としてC++のrand関数を使おうとしたが、偏りがあるので、randomライブラリにあるメルセンヌ・ツイスタ乱数を使うことにする。

解説:クリップボード

makepassword.cpp

 135: /**
 136:  * クリップボードに文字列をセット
 137:  * @param   string str 文字列
 138:  * @return  なし
 139: */
 140: void setClipboardData(string str) {
 141:     char buff[str.size() + 1];
 142:     char_traits<char>::copy(buff, str.c_str(), str.size() + 1);
 143: 
 144:     OpenClipboard(NULL);
 145:     EmptyClipboard();
 146: 
 147:     HGLOBAL hText = GlobalAlloc(GHND | GMEM_SHARE, SIZE_BUFF);
 148:     PTSTR pText = (PTSTR)GlobalLock(hText);
 149:     lstrcpy(pText, buff);
 150:     GlobalUnlock(hText);
 151:     SetClipboardData(CF_TEXT, hText);
 152:     CloseClipboard();
 153: }

クリップボードに文字列をセットするユーザー関数 setClipboardData を用意した。Win32APIを利用する。

解説:メインダイアログ

isleap2.cpp

  31: /**
  32:  * ダイアログボックス
  33:  * @param   HWND hDlg
  34:  * @paramm  UINT uMsg
  35:  * @param   WPARAM wParam
  36:  * @paramL  PARAM lParam
  37:  * @return  INT_PTR CALLBACK
  38: */
  39: INT_PTR CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  40:     char buff[255];
  41: 
  42:     time_t t = time(0);                 //現在時刻
  43:     tm* now = localtime(&t);            //ローカルタイム
  44:     int year = now->tm_year + 1900;     //西暦年を取り出す
  45:     bool res = isleap(year);            //閏年かどうか判定する
  46: 
  47:     switch(uMsg) {
  48:         case WM_INITDIALOG:
  49:             snprintf(buff, sizeof(buff), "%d年は 閏年%s", year, (res ? "です." : "ではありません."));
  50:             SetDlgItemText(hDlg, IDC_LABEL, buff);
  51:             break;
  52:         case WM_CLOSE:
  53:             EndDialog(hDlg, 0);
  54:             break;
  55:     }
  56:     return 0;
  57: }

ダイアログボックス関数にイベントが増えた。
ボタンをクリックすると、WM_COMMAND イベントが発生する。クリックされたボタンのIDで処理を場合分けする。

参考サイト

(この項おわり)
header