12,964
回編集
112行目: | 112行目: | ||
<br><br> | <br><br> | ||
== | == 使用例: CBCモード == | ||
==== サンプルコード ==== | |||
以下の例では、<code>QCrypto</code>クラスを使用して、CBCモードでの暗号化と復号を行っている。<br> | 以下の例では、<code>QCrypto</code>クラスを使用して、CBCモードでの暗号化と復号を行っている。<br> | ||
<br> | <br> | ||
429行目: | 430行目: | ||
* パスワードからキーを生成しているが、実務ではより安全なキー管理方法を使用すべきである。 | * パスワードからキーを生成しているが、実務ではより安全なキー管理方法を使用すべきである。 | ||
* エラーハンドリングにおいて、入出力の検証を追加することを推奨する。 | * エラーハンドリングにおいて、入出力の検証を追加することを推奨する。 | ||
<br> | |||
==== パスワード / キーの管理 ==== | |||
パスワード / キーの管理は非常に重要なセキュリティ上の問題である。<br> | |||
ハードコーディングされたパスワードは避けるべきであり、より安全な方法でパスワードを取得・管理する必要がある。<br> | |||
<br> | |||
以下に、いくつかの一般的なアプローチと推奨事項を示す。<br> | |||
<br> | |||
===== ユーザ入力 ===== | |||
最も簡単な方法は、ユーザに直接パスワードを入力してもらうことである。<br> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
QString getPasswordFromUser() | |||
{ | |||
QInputDialog dialog; | |||
dialog.setInputMode(QInputDialog::TextInput); | |||
dialog.setTextEchoMode(QLineEdit::Password); | |||
dialog.setWindowTitle("パスワードの入力"); | |||
dialog.setLabelText("暗号化パスワードを入力してください: "); | |||
if (dialog.exec() == QDialog::Accepted) { | |||
return dialog.textValue(); | |||
} | |||
return QString(); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// 使用例 | |||
QString password = getPasswordFromUser(); | |||
if (!password.isEmpty()) { | |||
aes.setKey(password); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
===== 環境変数の使用 ===== | |||
セキュリティ上のリスクはあるが、開発環境やテスト環境では環境変数を使用することがある。<br> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
QString getPasswordFromEnv() | |||
{ | |||
return qgetenv("MY_APP_ENCRYPTION_KEY"); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
===== 暗号化された設定ファイル ===== | |||
暗号化された設定ファイルにパスワードを保存する方法もある。<br> | |||
ただし、この方法を使用する場合は、設定ファイル自体を安全に保護する必要がある。<br> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
QString getPasswordFromConfig() | |||
{ | |||
QSettings settings("MyCompany", "MyApp"); | |||
return settings.value("EncryptionKey").toString(); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
===== キーストア / セキュアエンクレーブ ===== | |||
OSのセキュアなキーストアを使用する方法である。<br> | |||
これは最も安全な方法の1つであるが、実装が複雑になる可能性がある。<br> | |||
<br> | |||
以下に示すAPIを使用する場合は、プラットフォーム固有のコードが必要になる。<br> | |||
* Windows | |||
*: Data Protection API (DPAPI) | |||
* MacOS | |||
*: Keychain | |||
* Linux | |||
*: Secret Service API | |||
<br> | |||
===== ハードウェアセキュリティモジュール (HSM) ===== | |||
高度なセキュリティが必要な場合、HSMを使用してキーを管理することができる。<br> | |||
<br> | |||
===== キーの派生 ===== | |||
ユーザのパスワードから安全にキーを派生させる方法もある。<br> | |||
これには、PBKDF2やscrypt等のキー派生関数を使用する。<br> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
QByteArray deriveKey(const QString &password, const QByteArray &salt) | |||
{ | |||
// OpenSSLを使用してPBKDF2でキーを派生させる例 | |||
QByteArray key(32, 0); // 256ビットキー | |||
PKCS5_PBKDF2_HMAC(password.toUtf8().constData(), password.length(), | |||
reinterpret_cast<const unsigned char*>(salt.constData()), | |||
salt.length(), 10000, EVP_sha256(), | |||
key.size(), reinterpret_cast<unsigned char*>(key.data())); | |||
return key; | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
===== 推奨事項 ===== | |||
* パスワードを平文で保存しないこと。 | |||
* 可能な限り、ユーザに直接パスワードを入力してもらう方法を選択すること。 | |||
* パスワードの強度要件を設定して、ユーザに強力なパスワードの使用を促す。 | |||
* パスワード / キーの転送時は、安全な通信チャネル (例: HTTPS) を使用すること。 | |||
* 必要に応じて、多要素認証を実装することを検討する。 | |||
* 定期的なパスワード変更を促すポリシーを実装することを検討する。 | |||
<br> | |||
実務では、これらの方法を組み合わせて使用することが一般的である。<br> | |||
例えば、ユーザが入力したパスワードからキーを派生させて、派生したキーをセキュアなキーストアに保存するという方法がある。<br> | |||
<br><br> | <br><br> | ||