AES_ENCRYPT() と AES_DECRYPT() を使用して MySQL を暗号化および復号化する正しい方法の例

AES_ENCRYPT() と AES_DECRYPT() を使用して MySQL を暗号化および復号化する正しい方法の例

序文

最近、仕事でAES_ENCRYPT()関数を使用してプレーンテキストを暗号化し、MySQL に保存する必要があるという要件に遭遇しましたが、いくつか問題が発生しました... 以下に詳細を紹介します。

暗号化された暗号文を復号すると、結果が NULL になると言われています。

彼女が送ってきたテーブル構造を見てみました。

次に、彼女が AES_DECRYPT() 関数を使用して文字列を暗号化し、それを挿入しているのを確認しました。実行が成功すると、 warning:
Query OK, 1 row affected, 1 warning (0.00 sec)

(エラーはありませんが、警告は出ます。おそらく sql_mode が原因です)

このとき、彼女は警告を無視し、 AES_DECRYPT()で復号化したところ、得られた平文が NULL であることがわかりました。

テーブル構造をもう一度見てみると、フィールド属性は「varchar」であり、文字セットは ut8 であり、警告は次のようになります。

mysql> 警告を表示します。
+---------+------+------------------------------------------------------------------------------------+
| レベル | コード | メッセージ |
+---------+------+------------------------------------------------------------------------------------+
| 警告 | 1366 | 行 1 の列 'passwd' の文字列値が正しくありません: '\xE3f767\x12...' |
+---------+------+------------------------------------------------------------------------------------+
セット内の 1 行 (0.00 秒)

ドキュメントをチェックして、これら 2 つの関数がどのように使用されるかを確認してください。

-- キー 'key' を使用して 'hello world' を暗号化し、暗号化された文字列を @passmysql> SET @pass=AES_ENCRYPT('hello world', 'key'); に保存します。 
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

-- 暗号化された文字列の長さを確認します(すべて 2 の累乗です)
mysql> CHAR_LENGTH(@pass)を選択します。
+--------------------+
| CHAR_LENGTH(@pass) |
+--------------------+
| 16 |
+--------------------+
セット内の 1 行 (0.00 秒)

-- AES_DECRYPT() を使用して復号化します。mysql> SELECT AES_DECRYPT(@pass, 'key');
+---------------------------+
| AES_DECRYPT(@pass, 'キー') |
+---------------------------+
| こんにちは世界 |
+---------------------------+
セット内の 1 行 (0.00 秒)

それでどうやって保存するのでしょうか?

方法1:

フィールド プロパティを varbinary/binary/four blob 型に設定し、その他のバイナリ フィールド プロパティを設定します。

varbinary、binary、blob の属性を持つ 3 つのフィールドを作成します。

そして、キー key を使用して 'plaintext1'、 'text2'、 'plaintext_text3' を暗号化し、テーブルに保存します。

最後に取り出します。

mysql> テーブル t_passwd を作成します (pass1 varbinary(16), pass2 binary(16), pass3 blob);
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

mysql> t_passwd に値 (AES_ENCRYPT('plaintext1', 'key'), AES_ENCRYPT('text2', 'key'), AES_ENCRYPT('plaintext_text3', 'key')) を挿入します。 
クエリは正常、1 行が影響を受けました (0.01 秒)

mysql> t_passwd から AES_DECRYPT(pass1, 'キー')、AES_DECRYPT(pass2, 'キー')、AES_DECRYPT(pass3, 'キー') を選択します。
+---------------------------+----------------------------+---------------------------+
| AES_DECRYPT(pass1, 'キー') | AES_DECRYPT(pass2, 'キー') | AES_DECRYPT(pass3, 'キー') |
+---------------------------+----------------------------+---------------------------+
| プレーンテキスト1 | テキスト2 | プレーンテキスト3 |
+---------------------------+---------------------------+---------------------------+
セット内の 1 行 (0.00 秒)

もちろん、属性括弧の長さはプレーンテキストの長さによって異なります。ここではプレーンテキストの方が短いため、16 のみが与えられています。

方法2:

暗号文を 16 進数に変換し、varchar/char 列に保存します。

ここでは、入金には HEX() を使用し、出金にはUNHEX()使用する必要があります。

文字列属性を持つフィールドを作成します。

まず、AES を使用してキー「key2」で「hello world」を暗号化し、次に HEX 関数を使用して暗号化された文字列を 16 進数に変換します。

最後に、暗号化された文字列は UNHEX を通じて取り出され、キー「key2」に従って AES を通じて復号化されます。

mysql> テーブル t_passwd_2(pass1 char(32)) を作成します。
クエリは正常、影響を受けた行は 0 行 (0.01 秒)

mysql> t_passwd_2 に値 (HEX(AES_ENCRYPT('hello world', 'key2')) を挿入します);
クエリは正常、1 行が影響を受けました (0.00 秒)

mysql> t_passwd_2 から AES_DECRYPT(UNHEX(pass1), 'key2') を選択します。 
+-----------------------------------+
| AES_DECRYPT(UNHEX(pass1), 'key2') |
+-----------------------------------+
| こんにちは世界 |
+-----------------------------------+
セット内の 1 行 (0.00 秒)

同様に、平文の長さに応じて、AES_ENCRYPT で暗号化された文字列の長さも変化するため、HEX 以降の文字列の長さも変化します。
実際の使用においては、ビジネスに基づいて妥当な価値を評価するだけで十分です。

方法3:

16 進数化せずに varchar に直接保存します。

問題の始まりに戻ると、暗号化された文字列を utf8 文字セットで保存することはできず、属性は varchar です。

実際には、文字セットを latin1 に変更するだけです。

挿入中に警告は報告されません。

mysql> CREATE TABLE t_passwd_3(pass varchar(32)) CHARSET latin1;
クエリは正常、影響を受けた行は 0 行 (0.00 秒)

mysql> t_passwd_3 に INSERT INTO し、AES_ENCRYPT('text', 'key3') を選択します。
クエリは正常、1 行が影響を受けました (0.00 秒)
記録: 1 重複: 0 警告: 0

mysql> t_passwd_3 から AES_DECRYPT(pass, 'key3') を選択します。
+---------------------------+
| AES_DECRYPT(pass, 'key3') |
+---------------------------+
| テキスト |
+---------------------------+
セット内の 1 行 (0.00 秒)

この方法は美しいですが、フィールドの文字セットを latin1 に設定すると、隠れた危険が生じる可能性があります。

文書にはこう記されている。

多くの暗号化および圧縮関数は、結果に任意のバイト値が含まれる可能性がある文字列を返します。これらの結果を保存する場合は、VARBINARY または BLOB バイナリ文字列データ型の列を使用します。これにより、非バイナリ文字列データ型 (CHAR、VARCHAR、TEXT) を使用する場合に発生する可能性がある、末尾のスペースの削除やデータ値を変更する文字セット変換に関する潜在的な問題を回避できます。

一般的な考え方としては、方法 3 を使用して暗号化された文字列を char/varchar/text 型に直接保存すると、文字変換を実行するときやスペースを削除するときに潜在的な影響が出る可能性があります。

したがって、char/varchar/text で保存する必要がある場合は、方法 ② を参照して 16 進数に変換します。

または、方法①のようにバイナリフィールドに直接格納します。

要約する

上記はこの記事の全内容です。この記事の内容が皆さんの勉強や仕事に少しでもお役に立てれば幸いです。ご質問があれば、メッセージを残してコミュニケーションしてください。123WORDPRESS.COM をご愛顧いただき、ありがとうございます。

参考資料:

第 12 章 関数と演算子 - 12.13 暗号化と圧縮関数

以下もご興味があるかもしれません:
  • MySQLサーバーは--read-onlyオプションで実行されているため、このステートメントを実行できません
  • mysql データベースmysql: [エラー] 不明なオプション ''--skip-grant-tables''
  • MySQL ビューの一貫性を確保する方法の詳細な説明 (チェック オプション付き)
  • MySQL に絵文字を保存するときに表示されるエラー メッセージ「java.sql.SQLException: 文字列値が正しくありません:'\xF0\x9F\x92\xA9\x0D\x0A...'」の解決方法
  • MySQL の NULL と空の文字列
  • ODBC経由でMySQLとPHPを任意のデータベースに接続する例
  • Ubuntu で apt-get を使用して mysql をインストールおよび完全にアンインストールする方法の詳細な説明
  • mysqlサーバーは--skip-grant-tablesオプションで実行されています
  • pt-heartbeat を使用して MySQL レプリケーションの遅延を監視する方法の詳細な説明
  • MySQL pt-slave-restart ツールの使い方の紹介

<<:  複数のネットワークカードを備えた Linux システムでのルーティング構成の詳細な説明

>>:  JavaScriptのプロトタイプオブジェクトを徹底的に理解しましょう

推薦する

曇り空のアイコン効果を実現する純粋な CSS

効果効果は以下のとおりです​実装のアイデアbox-shadow プロパティを使用して、複数の灰色の円...

Linux コンパイル最適化で習得しなければならないいくつかの姿勢のまとめ

01. コンパイルオプションとカーネルコンパイルLinux カーネル (英語: linux kern...

レム適応の一般的なパッケージ3つについて

序文以前、rem適応についての記事を書きましたが、具体的なパッケージは紹介しませんでした。今日は、よ...

仮想マシンのLinux初心者がIPを設定し、ネットワークを再起動する

仮想マシンを初めて使用する方や、仮想マシンに Linux をインストールしたばかりの方は、システムが...

テーブルはセルとimg画像を結合してtd HTML全体を埋めます

ソースコード(一部のクラスは削除されています):コードをコピーコードは次のとおりです。 <テー...

MySQL DDLステートメントの使用

序文SQL の言語分類には主に以下の種類があります。 DDLデータ定義言語作成、削除、変更データ定義...

MySQL コマンドライン操作中のエンコードの問題の詳細な説明

1. MySQLデータベースのエンコーディングを確認する mysql -u ユーザー名 -p パスワ...

Vue で手ぶれ補正を実装するためのサンプルコード

手ぶれ防止: 繰り返しのクリックによるイベントのトリガーを防止まず、揺れとは何でしょうか? 震えるの...

MySQL で重複行を見つけて削除する方法

目次1. 重複行を見つける方法2. 重複行を削除する方法3. 複数の列で重複を見つける方法4. クエ...

MySQL 5.7 のインストールと設定の詳細な手順

1. MySQLをダウンロードする1. MySQLの公式ウェブサイトにログインし、64ビットシステム...

ウェブページの再設計の7つの主要要素 ウェブページの再設計の7つの主要要素を共有する

Shopify Plus は、私たちが設立した e コマース プラットフォームのエンタープライズ バ...

JavaScriptはスクロールバーの位置を取得し、ページをアンカーポイントまでスライドします。

序文この記事は、私が最近仕事で遭遇した問題を記録したものです。アプリネイティブとフロントエンドのh5...

CSS 評価効果の星の例

何?何のスターコートですか?さて、もっとわかりやすくするために写真を見てみましょう。 よく見ると、パ...

divは、自動入力スタイルをブロックする入力ボックスとして入力を使用せずにコンテンツを入力できます。

今日、私は公開用の動的なウィンドウ スタイルを設計しましたが、マウスで入力をクリックしたときにブラウ...