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

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

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

(2024年2月17日)使用ライブラリ等を更新
(2023年10月9日)使用ライブラリ等を更新
(2023年6月3日)使用ライブラリ等を更新

目次

サンプル・プログラム

圧縮ファイルの内容
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.5 2024/02/17 使用ライブラリ等を更新
1.2.4 2023/10/09 使用ライブラリをバージョンアップ
1.2.3 2023/06/03 使用ライブラリをバージョンアップ
1.2.2 2023/01/28 使用ライブラリをバージョンアップ
1.2.1 2022/10/31 使用ライブラリをバージョンアップ

リソースの準備

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

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

使用ライブラリ

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

プログラムの解説

   9: // 初期化処理 ======================================================
  10: #include <iostream>
  11: #include <stdio.h>
  12: #include <stdlib.h>
  13: #include <tchar.h>
  14: #include <time.h>
  15: #include <sstream>
  16: #include <string>
  17: #include <winsock2.h>
  18: #include <windows.h>
  19: #include <shlobj.h>
  20: #include <commctrl.h>
  21: #include <richedit.h>
  22: #include <random>
  23: #include <boost/program_options.hpp>
  24: #include <boost/property_tree/xml_parser.hpp>
  25: #include <boost/format.hpp>
  26: #include "resource.h"
  27: 
  28: using namespace std;
  29: using namespace boost;
  30: using namespace boost::program_options;
  31: using namespace boost::property_tree;
  32: 
  33: #define MAKER       "pahoo.org"             //作成者
  34: #define APPNAME     "makepassword"          //アプリケーション名(GUI版)
  35: #define APPNAMEJP   "パスワード生成機"      //アプリケーション名
  36: #define APPCMD      "mkpsw"                 //アプリケーション名(CUI版)
  37: #define APPVERSION  "1.2.5"                 //バージョン
  38: #define APPYEAR     "2020-2024"             //作成年
  39: #define REFERENCE   "https://www.pahoo.org/e-soul/webtech/cpp01/cpp01-05-01.shtm"   // 参考サイト
  40: 
  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ライブラリにあるメルセンヌ・ツイスタ乱数を使うことにする。

 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を利用するもので、「PHPでクリップボードにテキスト貼り付け(Windowsアプリ版)」で作ったプログラムをC++に移植した。

  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