MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
Qtの応用 - AESのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
Qtの応用 - AES
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == AESは、DESおよび3DESに代わって規格化された共通鍵暗号方式である。<br> ブロック長は128ビット、鍵長は128ビット・192ビット・256ビットが選択できる。<br> <br> AESのソースコードは、[http://www.gladman.me.uk/ Brian Gladman氏のWebサイト]で公開されている。<br> アセンブラで記述されたもの(高速)とC言語で記述されたものが公開されている。<br> <br> また、Githubに[https://github.com/bricke/Qt-AES.git Qt AESライブラリ]が公開されている。<br> <br><br> == ブロック暗号化モード == AESには、ブロック暗号化モードという機能がある。<br> 最も単純なのがECBモードであり、データを16[byte]ごとに区切って暗号化する。<br> しかし、Birthday Attack等に弱いという欠点があるため、ECBモードは使用するべきではない。<br> * CBC *: 暗号文ブロック連鎖モード(Cipher Block Chaining) * OFB *: 出力フィードバックモード(Oftput Feed Back) * CFB *: 暗号フィードバックモード(Cipher Feed Back) * ECB *: 暗号ブックモード(Electric Code Book) <br> この他にも、PCBCやCounter Method等の新しい暗号利用モードも考案されている。<br> <br> ==== ECBモード ==== ECBモードは、1ブロックずつ単純に処理する。<br> ただし、ECBモードはブロック単位処理の裏をかいた暗号文一致攻撃をに弱い欠点がある。<br> <br> 暗号ブロックが一致した場合は復号した平文は一致するため、重要な秘密が漏れる可能性が高いと考えられる。<br> 特定の暗号ブロックに対応する平文ブロックが1度でも知られると、同一の値を持つ暗号ブロックは全て解読される。<br> <br> 実際には、暗号文全体のうち部分的な平文は状況的に推測できるということは少なくないため、長い平文を暗号化する場合は非推奨である。<br> <br> また、ブロック単位の差し替え等の暗号文改竄攻撃にも弱いという問題がある。<br> 改竄攻撃を成功させるために、鍵を入手したり平文を正確に把握する必要が無いため、注意が必要である。<br> <br> <u>AESを使用した商用ソフトウェアにおいて、ECBモードが使用されることはほぼ無い。</u><br> <br> ==== CBCモード ==== CBCモードは、前の平文ブロックを暗号化した結果を、次の平文にXOR演算によって重ね合わせ、その結果に対して暗号化処理を行う。<br> 最初のブロックを暗号化する場合、前の暗号文の最後のブロックを利用するか、または外部から与えた初期ベクトルを使用する。<br> <br> 前の暗号化結果が次のブロックに連鎖されるので連鎖モードと呼ぶ。<br> 同一の平文から同一の暗号文が生成される可能性は極めて低いため、同一の平文が続く場合も安心して使用できる。<br> <br> CBCモードに対する暗号文一致攻撃は、以下のように考えられる。<br> 暗号文ブロック<math>C_j, C_k</math>に対応する平文が<math>P_j, P_k</math>とする時、偶然にも、<math>C_k = C_j</math>であった場合、以下の攻撃が成立する。<br> <br> それぞれの前の暗号文をCk_1、Cj_1とする時、以下が成立する。<br> <math>XOR(C_{k1}, C_k) = XOR(C_{j1}, Cj)</math><br> <br> また、CBCモードの手順から、以下が成立する。<br> <math>XOR(C_{j1}, C_{k1}) = XOR(P_j, P_k)</math><br> <br> すると、2つの平文の間に生じる差分は入手できてしまう。<br> しかし、このような攻撃が成功する確率は非常に稀であるといえる。<br> <br> CBCモードの初期値は、攻撃者から見えても構わないことになっているが、毎回違う値を利用することが推奨されている。<br> <br> CBCモードは、暗号化がランダムアクセスに適さないため、暗号化は先頭から順次行う必要がある。<br> また、復号がランダムアクセスに適しており、復号はランダムに選択した着目ブロックに対して操作できる。(1つ前の暗号文ブロックは必要である)<br> <br> ==== OFBモード ==== OFBモードは、初期ベクトルを暗号化して、それをまた暗号化して、次々と乱数を生成する。<br> その乱数列を、XOR演算によって平文に重ね合わせて、暗号化処理を行う。<br> したがって、ブロック暗号をストリーム暗号のように使用する。<br> <br> OFBモードの初期値は、攻撃者から見えても構わないことになっているが、同じ鍵を使用する場合、必ず、初期値は毎回違う値を使用する。<br> <br> 同一の初期値と鍵の組み合わせから生じる乱数列は常に同一であるため、<br> 平文と暗号文の組が1組でも攻撃者の手に渡ってしまうと、そこから乱数列が解ってしまい、<br> 同一の初期値と鍵で暗号化した全ての暗号文が解読されてしまう。<br> <br> OFBモードは、暗号化も復号化もランダムアクセスに適していないため、どちらも先頭から順次行う必要がある。<br> <br> 最近、人気のある暗号化モードにカウンタモード(またはカウンタメソッド)がある。<br> カウンタモードは、先頭からのブロック番号を求めてその値を暗号化して、その数値を乱数として使用する。<br> <br> カウンタモードであれば、安全性が若干損なう可能性があるが、暗号化も復号もランダムに行えて便利である。<br> <br><br> == 初期化ベクトル == ==== カウンタモード (CTR) ==== CTRモードでは、カウンタ値を初期化ベクトルとして使用する。<br> 各ブロックごとにカウンタをインクリメントすることにより、一意の値を生成する。<br> <br> ==== GCMモード ==== GCMモード等では、ナンス (使い捨ての数値) とカウンタを組み合わせて初期化ベクトルを生成する。<br> <br> ==== 初期化ベクトル生成時の注意点 ==== * 予測可能性 *: 自動生成されたIV (初期化ベクトル) が予測可能であってはいけない。 *: 例えば、単純なインクリメント方式は避けるべきである。 *: <br> * 一意性 *: 同じキーで同じIV (初期化ベクトル) を再利用しないことが重要である。 *: 特にストリーム暗号的なモード (CTRモード, GCMモード) では致命的な脆弱性につながる。 *: <br> * ランダム性 *: 可能な限り、暗号学的に安全な乱数生成器を使用してIV (初期化ベクトル) を生成すべきである。 *: <br> * 通信 *: IV (初期化ベクトル) は、一般的に、暗号文と一緒に送信する必要がある。 *: 多くの場合、暗号文の先頭に付加される。 *: <br> * 長さ *: IV (初期化ベクトル) の長さは、使用する暗号化モードに応じて適切に設定する必要がある。 *: 多くの場合、ブロックサイズと同じである。 <br> 自動生成されたIV (初期化ベクトル) を使用することにより、同じ平文でも毎回異なる暗号文が生成されて、セキュリティが向上する。<br> <br><br> == サンプルコード: CBCモード == 以下の例では、<code>QCrypto</code>クラスを使用して、CBCモードでの暗号化と復号を行っている。<br> <br> * キー管理 *: setKeyメソッドでパスワードからキーを生成する。 *: キーが設定されていない場合は、暗号化・復号操作は失敗する。 *: <br> *: ただし、以下の例ではパスワードからキーを生成しているが、実務では、より安全なキー管理方法を使用すべきである。 * IV (初期化ベクトル) の自動生成 *: 暗号化時において、自動的に新しいランダムなIV (初期化ベクトル) を生成して、IV (初期化ベクトル) を暗号文の先頭に付加して送信する。 *: 復号時において、暗号文からIV (初期化ベクトル) を自動的に取り出して使用する。 * パディング *: PKCS7パディングを使用しており、復号時にパディングの妥当性を確認する。 <br> <syntaxhighlight lang="cmake"> # CMakeLists.txtファイル cmake_minimum_required(VERSION 3.21) project(AESEncryptionProject LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # Pkg-configの使用 find_package(PkgConfig REQUIRED) # Qtライブラリの検索 find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED) # OpenSSLライブラリの検索 find_package(OpenSSL REQUIRED) # ソースコードファイル群 set(SOURCES main.cpp AES.cpp ) set(HEADERS AES.h ) # 実行バイナリファイルの生成 add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS}) # Qtライブラリのリンク target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Core) # OpenSSLライブラリのリンク target_link_libraries(${PROJECT_NAME} PRIVATE OpenSSL::SSL OpenSSL::Crypto) # OpenSSLのインクルードディレクトリ target_include_directories(${PROJECT_NAME} PRIVATE ${OPENSSL_INCLUDE_DIR}) # C++コンパイラフラグの設定 if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -pedantic) elseif(MSVC) target_compile_options(${PROJECT_NAME} PRIVATE /W4) endif() </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // AES.hファイル #ifndef AES_H #define AES_H #include <QObject> #include <QByteArray> class AES : public QObject { Q_OBJECT private: // Variables QByteArray m_key; QString m_lastError; private: // Methods QByteArray generateKey(const QString &password); QByteArray generateIV(); QByteArray padData(const QByteArray &data); QByteArray unpadData(const QByteArray &data); public: // Methods explicit AES(QObject *parent = nullptr); ~AES(); bool setKey(const QString &password); QByteArray encrypt(const QByteArray &plaintext); QByteArray decrypt(const QByteArray &ciphertext); QString lastError() const; }; #endif // AES_H </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // AES.cppファイル #include <QCryptographicHash> #include <openssl/aes.h> #include <openssl/rand.h> #include <openssl/err.h> #include "AES.h" AES::AES(QObject *parent) : QObject(parent) { OpenSSL_add_all_algorithms(); } AES::~AES() { EVP_cleanup(); } bool AES::setKey(const QString &password) { m_key = generateKey(password); return !m_key.isEmpty(); } QByteArray AES::encrypt(const QByteArray &plaintext) { if (m_key.isEmpty()) { m_lastError = "キーがセットされていません"; return QByteArray(); } QByteArray iv = generateIV(); QByteArray paddedText = padData(plaintext); QByteArray ciphertext(paddedText.size(), 0); EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); if (!ctx) { m_lastError = "暗号化コンテキストの生成に失敗"; return QByteArray(); } if (EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, reinterpret_cast<const unsigned char*>(m_key.constData()), reinterpret_cast<const unsigned char*>(iv.constData())) != 1) { m_lastError = "Failed to initialize encryption"; EVP_CIPHER_CTX_free(ctx); return QByteArray(); } int len; int ciphertext_len; if (EVP_EncryptUpdate(ctx, reinterpret_cast<unsigned char*>(ciphertext.data()), &len, reinterpret_cast<const unsigned char*>(paddedText.constData()), paddedText.size()) != 1) { m_lastError = "データの暗号化に失敗"; EVP_CIPHER_CTX_free(ctx); return QByteArray(); } ciphertext_len = len; if (EVP_EncryptFinal_ex(ctx, reinterpret_cast<unsigned char*>(ciphertext.data()) + len, &len) != 1) { m_lastError = "暗号化のファイナライズに失敗"; EVP_CIPHER_CTX_free(ctx); return QByteArray(); } ciphertext_len += len; EVP_CIPHER_CTX_free(ctx); return iv + ciphertext.left(ciphertext_len); } QByteArray AES::decrypt(const QByteArray &ciphertext) { if (m_key.isEmpty()) { m_lastError = "キーがセットされていません"; return QByteArray(); } if (ciphertext.size() < AES_BLOCK_SIZE) { m_lastError = "暗号文のサイズが無効"; return QByteArray(); } QByteArray iv = ciphertext.left(AES_BLOCK_SIZE); QByteArray actualCiphertext = ciphertext.mid(AES_BLOCK_SIZE); QByteArray plaintext(actualCiphertext.size(), 0); EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); if (!ctx) { m_lastError = "暗号化コンテキストの生成に失敗"; return QByteArray(); } if (EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, reinterpret_cast<const unsigned char*>(m_key.constData()), reinterpret_cast<const unsigned char*>(iv.constData())) != 1) { m_lastError = "Failed to initialize decryption"; EVP_CIPHER_CTX_free(ctx); return QByteArray(); } int len; int plaintext_len; if (EVP_DecryptUpdate(ctx, reinterpret_cast<unsigned char*>(plaintext.data()), &len, reinterpret_cast<const unsigned char*>(actualCiphertext.constData()), actualCiphertext.size()) != 1) { m_lastError = "データの復号に失敗"; EVP_CIPHER_CTX_free(ctx); return QByteArray(); } plaintext_len = len; if (EVP_DecryptFinal_ex(ctx, reinterpret_cast<unsigned char*>(plaintext.data()) + len, &len) != 1) { m_lastError = "復号のファイナライズに失敗"; EVP_CIPHER_CTX_free(ctx); return QByteArray(); } plaintext_len += len; EVP_CIPHER_CTX_free(ctx); return unpadData(plaintext.left(plaintext_len)); } QString AES::lastError() const { return m_lastError; } QByteArray AES::generateKey(const QString &password) { return QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha256); } QByteArray AES::generateIV() { QByteArray iv(AES_BLOCK_SIZE, 0); if (RAND_bytes(reinterpret_cast<unsigned char*>(iv.data()), AES_BLOCK_SIZE) != 1) { m_lastError = "初期化ベクトルの生成に失敗"; return QByteArray(); } return iv; } QByteArray AES::padData(const QByteArray &data) { int padding = AES_BLOCK_SIZE - (data.size() % AES_BLOCK_SIZE); return data + QByteArray(padding, padding); } QByteArray AES::unpadData(const QByteArray &data) { if (data.isEmpty()) { return data; } int padding = data[data.size() - 1]; if (padding > AES_BLOCK_SIZE || padding < 1) { m_lastError = "パディングが無効"; return QByteArray(); } return data.left(data.size() - padding); } </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // main.cppファイル #include <QCoreApplication> #include <QDebug> #include "AES.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); AES aes; // 暗号化 (AES CBC) if (!aes.setKey("<任意の暗号化パスワード>")) { qDebug() << "Failed to set key:" << aes.lastError(); return; } QByteArray plaintext = "Hello, World! This is a secret message."; QByteArray ciphertext = aes.encrypt(plaintext); if (ciphertext.isEmpty()) { qDebug() << "暗号化に失敗: " << aes.lastError(); return; } // 復号 (AES CBC) QByteArray decrypted = aes.decrypt(ciphertext); if (decrypted.isEmpty()) { qDebug() << "復号に失敗: " << aes.lastError(); return; } qDebug() << "復号したデータ: " << QString::fromUtf8(decrypted); return a.exec(); } </syntaxhighlight> <br> <u>※注意</u><br> * 暗号化時は、IV (初期化ベクトル) を自動生成して、暗号文の先頭に追加している。 * 復号時は、暗号文の先頭からIV (初期化ベクトル) を取り出して使用する。 * パスワードからキーを生成しているが、実務ではより安全なキー管理方法を使用すべきである。 * エラーハンドリングにおいて、入出力の検証を追加することを推奨する。 <br><br> == Crypto++ == ==== Crypto++とは ==== AES (またはその他のブロック暗号) を使用する場合は、一般的に、ブロック暗号のインスタンスを持つモードを使用する。<br> 例えば、CFBモードの場合は、以下のように記述する。<br> <syntaxhighlight lang="c++"> CFB_Mode<AES>::Encryption Encrypt; // CFB_Modeは、ブロック暗号をテンプレートパラメータとして受け取る </syntaxhighlight> <br> ==== Crypto++のインストール ==== [https://cryptopp.com Crypto++ Libraryの公式Webサイト]にアクセスして、暗号化ライブラリのソースコードをダウンロードする。<br> ダウンロードしたファイルを解凍する。<br> unzip cryptopp<バージョン>.zip cd cryptopp<バージョン> <br> または、[https://github.com/weidai11/cryptopp Github]からソースコードをダウンロードすることもできる。<br> git clone https://github.com/weidai11/cryptopp.git cd cryptopp <br> Crypto++をビルドおよびインストールする。<br> make -j $(nproc) static dynamic CXX=/<GCCのインストールディレクトリ>/g++ make test make install DESTDIR=<暗号化ライブラリのインストールディレクトリ> <br> 暗号化ライブラリの使用手順は、以下のWebサイトを参照すること。<br> https://www.cryptopp.com/wiki/Advanced_Encryption_Standard<br> <br> ==== ブロック暗号の参照 ==== 外部のブロック暗号オブジェクトのインスタンスではなく、そのオブジェクトへの参照を保持するモードオブジェクトを作成することもできる。<br> 以下の例では、外部のAESオブジェクトでCFBモードを使用している。<br> <syntaxhighlight lang="c++"> AES::Encryption aesEncryption(key, AES::DEFAULT_KEYLENGTH); CFB_Mode_ExternalCipher::Encryption cfbEncryption(aesEncryption, iv); </syntaxhighlight> <br> ExternalCipherモードは、WindowsでFIPSをサポートするために追加されたものであり、必要がない限り避けるべきである。<br> <br> ==== ECBおよびCBCモードの備考 ==== ECBおよびCBCモードでは、データをブロックサイズの倍数で処理する必要がある。<br> または、<code>StreamTransformationFilter</code>をモードオブジェクトにラッピングして、フィルタオブジェクトとして使用することもできる。<br> <code>StreamTransformationFilter</code>は、データをブロックにバッファリングして、必要に応じてパディングを行う。<br> <br> もし、フルブロックサイズで処理する(パディングを行わない)場合は、第4引数に<code>StreamTransformationFilter</code>の<code>NO_PADDING</code>を指定する。<br> <syntaxhighlight lang="c++"> StringSource(data, true, new StreamTransformationFilter(encryptor, new StringSink(result), NO_PADDING)) </syntaxhighlight> <br> ==== サンプルコード ==== 以下の例では、AESが使用する鍵長の最小値、最大値、標準値をダンプしている。(2番目と3番目はパイプラインのフィルターを使用している)<br> パイプラインは高レベルの抽象化であり、入力のバッファリング、出力のバッファリング、パディングを処理する。<br> <syntaxhighlight lang="c++"> std::cout << "鍵長 : " << AES::DEFAULT_KEYLENGTH << std::endl; std::cout << "鍵長(最小) : " << AES::MIN_KEYLENGTH << std::endl; std::cout << "鍵長(最大) : " << AES::MAX_KEYLENGTH << std::endl; std::cout << "ブロックサイズ : " << AES::BLOCKSIZE << std::endl; // 出力 // 標準値の鍵長は128ビット(16バイト) 鍵長 : 16 鍵長(最小) : 16 鍵長(最大) : 32 ブロックサイズ : 16 </syntaxhighlight> <br> 以下の例では、CFBモードを使用して、暗号化および復号を行っている。<br> ECBやCBCではないため、データ長をAESのブロックサイズの倍数にする必要は無い。<br> <syntaxhighlight lang="c++"> AutoSeededRandomPool rnd; // Generate a random key SecByteBlock key(0x00, AES::DEFAULT_KEYLENGTH); rnd.GenerateBlock(key, key.size()); // Generate a random IV SecByteBlock iv(AES::BLOCKSIZE); rnd.GenerateBlock(iv, iv.size()); byte plainText[] = "Hello! How are you."; size_tmessageLen = std::strlen((char*)plainText) + 1; // Encrypt CFB_Mode<AES>::Encryption cfbEncryption(key, key.size(), iv); cfbEncryption.ProcessData(plainText, plainText, messageLen); // Decrypt CFB_Mode<AES>::Decryption cfbDecryption(key, key.size(), iv); cfbDecryption.ProcessData(plainText, plainText, messageLen); </syntaxhighlight> <br> ここでは、外部で生成された鍵と初期化ベクトル(IV)を使用して、暗号化器と復号器を取得する例を記述する。<br> その後の処理は、上記の例と同様に記述する。<br> <syntaxhighlight lang="c++"> SecByteBlock aes_key(16); SecByteBlock iv(16); // stub for how you really get it, e.g. reading it from a file, off of a // network socket encrypted with an asymmetric cipher, or whatever read_key(aes_key, aes_key.size()); // stub for how you really get it, e.g. filling it with random bytes or // reading it from the other side of the socket since both sides have // to use the same IV as well as the same key read_initialization_vector(iv); // the final argument is specific to CFB mode, and specifies the refeeding size in bytes. // This invocation corresponds to Java's Cipher.getInstance("AES/CFB8/NoPadding") auto enc = new CFB_Mode<AES>::Encryption(aes_key, sizeof(aes_key), iv, 1); // the final argument is specific to CFB mode, and specifies the refeeding size in bytes. // This invocation corresponds to Java's Cipher.getInstance("AES/CFB8/NoPadding") auto dec = new CFB_Mode<AES>::Decryption(aes_key, sizeof(aes_key), iv, 1); </syntaxhighlight> <br><br> == Qt AESライブラリ == ==== Qt AESライブラリとは ==== Qt向けのポータブルなAES暗号化ライブラリである。<br> 128 / 192 / 256ビットの鍵長をサポートしており、ECB、CBC、CFB、OFBモードおよび部分的なAES-NIをサポートしている。<br> <br> Qt AESライブラリはフリーライセンスであり、商用 / 非商用を問わず、自由に使用、改変、販売してもよい。<br> また、ソースコードの公開義務も無い。<br> <br> そのため、Qtの実行バイナリまたはQtプロジェクトにおいて、Qt AESライブラリを同梱して配布してもよい。<br> <br> ==== Qt AESライブラリのダウンロード ==== Qt AESライブラリのビルドに必要なライブラリをインストールする。<br> # SUSE sudo zypper install make cmake gcc gcc-c++ \ qt6-core-devel # Qt 6を使用する場合 qt6-test-devel # Qt AESライブラリのテストを行う場合 (Qt 6を使用する場合) libQt5Core-devel # Qt 5を使用する場合 libQt5Test-devel # Qt AESライブラリのテストを行う場合 (Qt 5を使用する場合) <br> [https://github.com/bricke/Qt-AES Qt AESクラスのGuthub]にアクセスして、ソースコードをダウンロードする。<br> ダウンロードしたファイルを解凍する。<br> tar xf Qt-AES-<バージョン>.tar.gz cd Qt-AES-<バージョン> <br> Qt AESライブラリをビルドおよびインストールする。<br> mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=<Qt AESライブラリのインストールディレクトリ> .. make -j $(nproc) make install <br> ==== Qt AESライブラリのサンプルコード ==== Qt AESライブラリを使用するには、Qt Coreライブラリが必要となる。<br> また、テストを行う場合は、Qt Testライブラリも必要となる。<br> <br> 以下の例では、Qt AESライブラリを使用して、鍵長128[bit]のECBモードで暗号化している。<br> <syntaxhighlight lang="c++"> #include <QCryptographicHash> #include "qaesencryption.h" // AESによるデータの暗号化 QString Encrypt(QString data, QString key) { // 鍵長128ビット, ECBモード, ゼロパディング QAESEncryption encryption(QAESEncryption::AES_128, QAESEncryption::ECB, QAESEncryption::ZERO); // QCryptographicHashによる鍵の暗号化 QByteArray hashKey = QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Sha1); // データの暗号化 QByteArray encodedText = encryption.encode(data.toUtf8(), hashKey); // QByteArrayからQStringへ変換 // toBase64関数は削除できない QString encodeTextStr = QString::fromLatin1(encodedText.toBase64()); return encodeTextStr; } </syntaxhighlight> <br> 以下の例では、Qt AESライブラリを使用して、鍵長128[bit]のECBモードで復号している。<br> <syntaxhighlight lang="c++"> #include <QCryptographicHash> #include "qaesencryption.h" // Qt AESライブラリを使用したデータの復号 QString decodedText(QString data, QString key) { // 鍵長128ビット, ECBモード, ゼロパディング QAESEncryption encryption(QAESEncryption::AES_128, QAESEncryption::ECB, QAESEncryption::ZERO); // QCryptographicHashによる鍵の暗号化 QByteArray hashKey = QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Sha1); // データの復号 QByteArray decodedText = encryption.decode(QByteArray::fromBase64(data.toLatin1()), hashKey); // QByteArrayからQStringへ変換 QString decodedTextStr = QString::fromLatin1(decodedText); return decodedTextStr; } </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:Qt]]
Qtの応用 - AES
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse