「Qtの基礎 - ハッシュ値」の版間の差分

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
ナビゲーションに移動 検索に移動
編集の要約なし
43行目: 43行目:
<br><br>
<br><br>


== ハッシュ化 ==
== QCryptographicHashクラス ==
==== ハッシュ化 ====
MD5、SHA-2、SHA-3等のハッシュを求める場合、<code>QCryptographicHash</code>クラスの<code>hash</code>メソッドを使用する。<br>
MD5、SHA-2、SHA-3等のハッシュを求める場合、<code>QCryptographicHash</code>クラスの<code>hash</code>メソッドを使用する。<br>
<br>
<br>
114行目: 115行目:
  }
  }
  </syntaxhighlight>
  </syntaxhighlight>
<br><br>
<br>
 
==== セキュリティ対策を施したハッシュ化の例 ====
=== セキュリティ対策を施したハッシュ化の例 ==
<code>QCryptographicHash</code>クラスは、暗号学的ハッシュ関数を提供するためのクラスであるが、<br>
<code>QCryptographicHash</code>クラスは、暗号学的ハッシュ関数を提供するためのクラスであるが、<br>
ソルト値の追加やPBKDF2等の鍵引き伸ばし関数の適用は自動的には行わない。<br>
ソルト値の追加やPBKDF2等の鍵引き伸ばし関数の適用は自動的には行わない。<br>

2024年5月23日 (木) 17:34時点における版

概要

ハッシュとは、任意のサイズのデータを固定長のデータに変換するアルゴリズムである。
ハッシュ関数と呼ばれる特殊な関数を使用して、入力データからハッシュ値 (ダイジェストとも呼ばれる) を生成する。

ハッシュの特徴を以下に示す。<br?

  • 一方向性
    ハッシュ値から元のデータを復元することは計算上非常に困難である。
  • 固定長出力
    入力データのサイズに関係なく、ハッシュ値は常に固定長になる。
  • 一意性
    異なる入力データから同じハッシュ値が生成される可能性は非常に低い。 (衝突耐性)
  • 高速性
    ハッシュ関数は効率的で、大量のデータを高速に処理できる。


ハッシュの用途を以下に示す。

  • データの整合性検証
    ハッシュ値を比較することで、データが改ざんされていないことを確認できる。
  • パスワードの保存
    パスワードをそのまま保存するのではなく、ハッシュ値を保存することでセキュリティを向上させる。
  • データの識別
    ハッシュ値を使用してデータを一意に識別できる。
  • 署名生成
    デジタル署名においてハッシュ関数が使用される。


代表的なハッシュアルゴリズムを以下に示す。

  • MD5
    古くから使用されてきたが、現在は脆弱性が発見されている。
  • SHA-1
    MD5の後継として広く使用されてきたが、現在は衝突耐性に問題があることが判明している。
  • SHA-2 (SHA-256, SHA-384, SHA-512)
    現在広く使用されている安全なハッシュアルゴリズムである。

    SHA-2は現在のコンピューティング能力では十分に安全であり、多くのシステムやプロトコルで広く使用されている。
    SHA-3への移行には、ソフトウェアやインフラストラクチャの更新が必要であり、コストと時間が掛かるため、緊急性がない限り、急激な変更は推奨されない。
  • SHA-3
    SHA-2の後継として設計された新しいハッシュアルゴリズムである。

    ただし、新しいシステムを設計する際や、長期的なセキュリティを考慮する必要がある場合には、SHA-3の採用を検討することを推奨する。
    SHA-3は、量子コンピュータによる攻撃に対してより耐性があると考えられており、将来を見据えた選択肢となっている。


ハッシュは、データの完全性検証、パスワードの保護、効率的なデータ検索等、ソフトウェア開発のさまざまな場面で活用されてる。
適切なハッシュアルゴリズムを選択し、ハッシュの特性を理解することが重要である。


QCryptographicHashクラス

ハッシュ化

MD5、SHA-2、SHA-3等のハッシュを求める場合、QCryptographicHashクラスのhashメソッドを使用する。

以下の例では、任意の文字列から、MD4、MD5、SHA-2、SHA-3のハッシュを計算している。

サポートされているハッシュの詳細については、Qtの公式ドキュメントを参照すること。

 #include <QCoreApplication>
 #include <QCryptographicHash>
 #include <QDebug>
 
 int main(int argc, char *argv[])
 {
    QCoreApplication a(argc, argv);
 
    // ハッシュ化する文字列
    QString input = "Hello, world!";
 
    // MD4
    QByteArray md4Hash = QCryptographicHash::hash(input.toUtf8(), QCryptographicHash::Md4);
    QString md4HexHash = md4Hash.toHex();
    qDebug() << "MD4 Hash:" << md4HexHash;
 
    // MD5
    QByteArray md5Hash = QCryptographicHash::hash(input.toUtf8(), QCryptographicHash::Md5);
    QString md5HexHash = md5Hash.toHex();
    qDebug() << "MD5 Hash:" << md5HexHash;
 
    // SHA-2 (SHA-224)
    QByteArray sha224Hash = QCryptographicHash::hash(input.toUtf8(), QCryptographicHash::Sha224);
    QString sha224HexHash = sha224Hash.toHex();
    qDebug() << "SHA-2 (SHA-224) Hash:" << sha224HexHash;
 
    // SHA-2 (SHA-256)
    QByteArray sha256Hash = QCryptographicHash::hash(input.toUtf8(), QCryptographicHash::Sha256);
    QString sha256HexHash = sha256Hash.toHex();
    qDebug() << "SHA-2 (SHA-256) Hash:" << sha256HexHash;
 
    // SHA-2 (SHA-384)
    QByteArray sha384Hash = QCryptographicHash::hash(input.toUtf8(), QCryptographicHash::Sha384);
    QString sha384HexHash = sha384Hash.toHex();
    qDebug() << "SHA-2 (SHA-384) Hash:" << sha384HexHash;
 
    // SHA-2 (SHA-512)
    QByteArray sha512Hash = QCryptographicHash::hash(input.toUtf8(), QCryptographicHash::Sha512);
    QString sha512HexHash = sha512Hash.toHex();
    qDebug() << "SHA-2 (SHA-512) Hash:" << sha512HexHash;
 
    // SHA-3 (SHA3-224)
    QByteArray sha3_224Hash = QCryptographicHash::hash(input.toUtf8(), QCryptographicHash::Sha3_224);
    QString sha3_224HexHash = sha3_224Hash.toHex();
    qDebug() << "SHA-3 (SHA3-224) Hash:" << sha3_224HexHash;
 
    // SHA-3 (SHA3-256)
    QByteArray sha3_256Hash = QCryptographicHash::hash(input.toUtf8(), QCryptographicHash::Sha3_256);
    QString sha3_256HexHash = sha3_256Hash.toHex();
    qDebug() << "SHA-3 (SHA3-256) Hash:" << sha3_256HexHash;
 
    // SHA-3 (SHA3-384)
    QByteArray sha3_384Hash = QCryptographicHash::hash(input.toUtf8(), QCryptographicHash::Sha3_384);
    QString sha3_384HexHash = sha3_384Hash.toHex();
    qDebug() << "SHA-3 (SHA3-384) Hash:" << sha3_384HexHash;
 
    // SHA-3 (SHA3-512)
    QByteArray sha3_512Hash = QCryptographicHash::hash(input.toUtf8(), QCryptographicHash::Sha3_512);
    QString sha3_512HexHash = sha3_512Hash.toHex();
    qDebug() << "SHA-3 (SHA3-512) Hash:" << sha3_512HexHash;
 
    return a.exec();
 }


セキュリティ対策を施したハッシュ化の例

QCryptographicHashクラスは、暗号学的ハッシュ関数を提供するためのクラスであるが、
ソルト値の追加やPBKDF2等の鍵引き伸ばし関数の適用は自動的には行わない。

そのため、これらの機能を使用する場合は、設計者側で実装する必要がある。

パスワードのハッシュ化を安全に行う場合は、以下に示すような手順を実装することが推奨される。

  • ソルト値の生成
    パスワード毎にランダムな一意のソルト値を生成する。
    ソルト値は、十分に長く、暗号学的に安全な乱数生成器を使用して生成する必要がある。
  • パスワードとソルト値の結合
    ソルト値をパスワードに結合する。
    一般的には、パスワードの前後にソルト値を付加する。
  • 鍵引き伸ばし関数の適用
    結合したパスワードとソルト値に対して、PBKDF2等の鍵引き伸ばし関数を適用する。
    鍵引き伸ばし関数は、計算コストを調整できるパラメータを持ち、ハッシュ計算に時間が掛かるようにすることで、ブルートフォース攻撃を困難にする。
  • ハッシュ値の生成
    鍵引き伸ばし関数により得られた結果を、暗号学的ハッシュ関数(SHA-256等)で処理して、最終的なハッシュ値を生成する。
  • ハッシュ値とソルト値の保存
    生成されたハッシュ値とソルト値をデータベース等に安全に保存する。


QtではPBKDF2を直接サポートするクラスは無いが、QMessageAuthenticationCodeクラスとQCryptographicHashクラスを組み合わせることにより、PBKDF2を実装することができる。

以下の例は、PBKDF2-HMAC-SHA256を使用したパスワードをハッシュ化している。

まず、QRandomGeneratorクラスを使用してランダムなソルト値を生成し、次に、パスワードとソルト値を結合してPBKDF2-HMAC-SHA256を適用している。
また、反復回数とキーの長さを指定することにより、計算コストを調整することができる。
ただし、実際の設計では、イテレーション回数を適切に調整して、ハードウェアの進歩に合わせて定期的に更新する必要がある。

 #include <QCryptographicHash>
 #include <QMessageAuthenticationCode>
 #include <QRandomGenerator>
 
 QByteArray hashPassword(const QString &password, const QByteArray &salt, int iterations, int keyLength)
 {
    QMessageAuthenticationCode hmac(QCryptographicHash::Sha256);
    QByteArray derivedKey(keyLength, Qt::Uninitialized);
 
    hmac.setKey(password.toUtf8() + salt);
 
    QByteArray U = hmac.result();
    QByteArray T = U;
 
    for (int i = 1; i < iterations; ++i) {
       hmac.addData(U);
       U = hmac.result();
       T = T.toHex().append(U.toHex());
    }
 
    return QCryptographicHash::hash(T, QCryptographicHash::Sha256).left(keyLength);
 }
 
 int main(int argc, char *argv[])
 {
    // ...略
 
    QString password = "myPassword";
    QByteArray salt = QRandomGenerator::global()->generate(16).toHex();
    int iterations = 10000;
    int keyLength = 32;
 
    QByteArray hashedPassword = hashPassword(password, salt, iterations, keyLength);
 
    // ...略
 }


ただし、セキュリティ上重要な用途では、専門家によって監査・検証されたライブラリや実装を使用することが推奨される。