パスワードハッシュ関数は、入力を大きな空間から固定された集中的な出力にマッピングする純粋な決定論的関数です。これらの出力は通常、入力の要約と呼ばれます。たとえば、入力はこの本の序文の全テキストであり、その要約は 128 ビットの値空間からの 16 進数である可能性があります。
形式的な方法を使用せずに、安全なハッシュ関数を使用する必要があります。これは、同じ要約を生成する 2 つの異なる入力を見つけることがほぼ不可能であることを意味します。ハッシュ関数はまた、不可逆であるべきです。要約だけが与えられた場合、要約を生成する入力を見つけることは不可能です。同様に、入力のわずかな変更は出力の要約に大きな変化をもたらすべきです。2 つの類似した入力は非常に異なる要約を持つべきです。ハッシュ関数はまた、入力から比較的迅速に計算されるべきであり、したがって、入力が一致し、その要約を検証することは簡単な作業です。
ハッシュ値はブロックチェーンの完全性を維持する核心であり、プルーフ・オブ・ワークのコンセンサスメカニズムの基礎です。これら 2 つの用途は、いくつかのページで見ることができます。
公開鍵暗号
公開鍵暗号は、多くの異なるアルゴリズムによって実現できますが、その中で最も人気のあるアルゴリズムの 1 つはリベスト・シャミール・アデルマン(より有名な名前は RSA)ですが、これは楕円曲線デジタル署名アルゴリズム(ECDSA)に依存しています。このアルゴリズムは、メッセージとその署名が与えられた場合に公開鍵を復元することも可能です。
これら 2 つの暗号学的概念を持って、私たちはついにブロックチェーンの構築方法を学び始めることができます。
ブロックチェーンは、分散型で不変の公共デジタル台帳です。私たちはブロックチェーンを分散データベースと見なすことができ、このデータベースでは、記録が確認されると、それは永久に削除または変更できず、権威機関がこのデータベースを制御することはできません。このデータベースは、ピアツーピアネットワーク内のすべてのノードに複製されます。データベースに実際に保存されている内容は異なる場合があります。それは通貨、資産登録、さらには実行可能なコードである可能性があります。
ブロックチェーンでは、各状態変更はトランザクションの一部です。トランザクションは、グローバルデータベース内のユーザーからの解剖的な書き込み操作と見なすことができ、この操作は 1 つまたは複数の配列を変更する可能性があります。ネットワーク内の任意のユーザーは、実行するトランザクションを提出できます。
トランザクションの処理は、ブロックチェーンの状態伝達関係の一部であり、受信した各トランザクションを処理することによって、ブロックチェーンはある状態から別の状態に移行します。たとえば、通貨を管理するブロックチェーンは、2 つのアカウント間の通貨移転を処理する可能性があります:送信者の残高を減少させ、受信者の残高を同じ金額だけ増加させます。他のブロックチェーンは、トランザクションをチェーン上で作成および実行することさえ許可します。
ブロックがブロックチェーンに追加されると、それはピアツーピアネットワークを介してすべてのノードに広がります。各ノードは、ブロック内のすべてのトランザクションを再実行して、それらが有効であるかどうかを確認し、違法な変更に気付いた場合はそのブロックを拒否します。これは、各トランザクションが実際にネットワーク全体で 1 バイトずつ実行されることを意味します。これにより、ブロックチェーンは完全に分散されます。各ノードがすべての実行中のトランザクションをチェックしますが、これはコストがかかります。混合オーバーヘッドは、実行できるトランザクションの数を制限します。
注意:公共ブロックチェーンは、ユーザーの登録を要求しません。ユーザーは新しいキー対を作成するだけで、トランザクションに署名してネットワークに参加できますが、トランザクションを処理するためにブロックチェーンに関連付けられた通貨を持つことを要求される場合があります。
トランザクションはブロックの形式でバッチ処理され、その後リンクされて実際のブロックチェーンを形成します。これらのブロックはブロックチェーンの履歴を構成し、各ブロックはその状態を変更するトランザクションのセットをパッケージ化します。各ブロック内でトランザクションを選択し並べ替える方法は、ブロックチェーンの合意ルールに依存し、これらのルールは後のページで見ることができます。
ブロックがブロックチェーンに追加されると、それはピアツーピアネットワークを介してすべてのノードに広がります。各ノードは、ブロック内のすべてのトランザクションを再実行して、それらが有効であるかどうかを確認し、違法な変更に気付いた場合はそのブロックを拒否します。これは、各トランザクションが実際にネットワーク全体で 1 バイトずつ実行されることを意味します。これにより、ブロックチェーンは完全に分散されます。各ノードがすべての実行中のトランザクションをチェックしますが、これはコストがかかります。混合オーバーヘッドは、実行できるトランザクションの数を制限します。
トランザクションはブロックの形式でバッチ処理され、その後リンクされて実際のブロックチェーンを形成します。これらのブロックはブロックチェーンの履歴を構成し、各ブロックはその状態を変更するトランザクションのセットをパッケージ化します。各ブロック内でトランザクションを選択し並べ替える方法は、ブロックチェーンの合意ルールに依存し、これらのルールは後のページで見ることができます。
ブロックがブロックチェーンに追加されると、それはピアツーピアネットワークを介してすべてのノードに広がります。各ノードは、ブロック内のすべてのトランザクションを再実行して、それらが有効であるかどうかを確認し、違法な変更に気付いた場合はそのブロックを拒否します。これは、各トランザクションが実際にネットワーク全体で 1 バイトずつ実行されることを意味します。これにより、ブロックチェーンは完全に分散されます。各ノードがすべての実行中のトランザクションをチェックしますが、これはコストがかかります。混合オーバーヘッドは、実行できるトランザクションの数を制限します。
ネットワークは毎秒処理します。言い換えれば、ブロックはトランザクションの数に基づいて配布されます。
この高コストのブロックチェーンの変更を処理するために、すべてのトランザクション手数料が支払われる必要があります。この手数料は通常、ブロックチェーンに固有の通貨(ビットコインネットワークのビットコイン、またはイーサリアムのイーサ)で支払われます。この手数料の受益者が誰であるかにかかわらず、数ページ後に見るように、この手数料の目的は、攻撃者が各ノードによって処理される必要のあるトランザクションでネットワークを圧倒するのを防ぎ、新しいブロックをチェーンに追加するノードに報酬を提供することです。
ブロックチェーンは、各ブロックにその全履歴の要約を保存することによって変更に抵抗します。チェーン内の各ブロックは、その自身のトランザクションのハッシュと前のブロックのハッシュを計算することによって識別されます。
このスキームを使用すると、チェーン内の任意のブロックの任意のトランザクションの変更は、すべての後続のハッシュの変更を引き起こし、したがって、任意の変更を無意味にします。たとえば、攻撃者が 10 ブロック前に発生したトランザクションを変更しようとすると、そのブロックの要約が変更されるだけでなく、次のブロックの要約も変更されます(前のブロックのハッシュに基づいて計算されるため)、そしてチェーンの先頭まで続きます。しかし、攻撃者がブロックチェーンを変更し、ネットワークに偽のコピーを配布するのを防ぐために、このメカニズムは攻撃者がすべてのブロックを再生成することを必要とします。これがプルーフ・オブ・ワークの由来です。
トランザクションは順序付けられ、ブロックチェーンのブロックに含まれることは、衰退の Igorifhn のネットワークに依存します。私たちが扱っているのは分散型データベースであるため、すべての参加者がどのようにチョークの変化を与えるかに同意する方法が必要です。たとえば、売り手がブロックチェーン上で資産を提供し、2 人のバイヤーがそれを奪い合っている場合、分散ネットワークは誰が最初であるかをどのように決定できますか?さらに悪いことに、売り手がこの 2 人の売り手に対して 2 回購入と現金取引を行ったと伝えないようにするにはどうすればよいでしょうか?「トランザクションがどのように順番に選択され、注文されるかを決定する方法が必要です。つまり、どのブロックにブロックを追加するかを決定する方法が必要です。」
ビットコインやイーサリアムなどの多くの公共ブロックは、「プルーフ・オブ・ワーク」と呼ばれるコンセンサスアルゴリズムに依存しています。プルーフ・オブ・ワークは、計算を実行するための大量の CPU ループの暗号的証明です。この場合、ブロックに基づいて難しい数値を計算します。ブロックをブロックチェーンに追加するには、証明を伴う必要があり、追加されたブロックのノードはその努力に対して報酬を受け取ります。この役割を果たすノードは「マイナー」と呼ばれ、新しいブロックが追加されるたびに、彼らは次のブロックを追加して相応の報酬を得ようと競争します。注意すべきは、これらの証明メカニズムは実際には非常に単純です。チェーン内の識別子の前のブロックは、前のブロックの識別子、ブロック内のすべてのトランザクション、および非 ct を含むハッシュです。現在の値を変更することによって、ブロックの要約は完全に異なります。チェーンに新しいブロックを追加するために、盗賊は特定の構造(N 個のゼロから始まる)を持っている必要があります。予測される要約がどのようになるかは受動的ではないため、マイナーは分割を繰り返し計算し、値を変更し続けて、要件を満たす要約を見つけるまで続ける必要があります。これは多くの試行を必要とし、したがって作業の証明と見なされます。
全体のインフラストラクチャは、ピアツーピアの分散ネットワークの上で動作します。これにより、ノードは自分の意志でネットワークに参加したり離れたりでき、集中型サーバーを必要としません。ここで、プルーフ・オブ・ワークアルゴリズムは、新しいノードが実際のチェーンを知る方法を提供します:彼らは最大の累積計算能力を持つチェーンを探すだけです。
これにより、悪意のある参加者が単にチェーン上の記録を変更し、すべての後続のブロックのハッシュを再計算することを防ぎます。これを行うには、攻撃者は攻撃されたブロックからのすべての作業の証拠を解決する必要があります。これは、ネットワーク内の他のマイナーよりも強力な計算能力を必要とします。
注:プルーフ・オブ・ワークの他にも、他の合意メカニズムがあります。… の中で、権威の証明と利害関係の証明が、より迅速で小さなチェーンを構築するための代替手段として存在します。
衰退アルゴリズムはネットワークの最終性に密接に関連しています。ブロックチェーンに含まれており、変更されないことがわかっている場合、私たちは反交換が最終的であると言います。最近のブロックに追加されたトランザクションは、最終的なものとは見なされません:マイナーが 1 行で 2 つのブロックを掘り出すことができた場合、最初から最後まで、彼らは新しいチェーンを生成し、最新のブロックを置き換えることができ、トランザクションを含めない可能性があります。
これは再編成と呼ばれ、プルーフ・オブ・ワークチェーンでは珍しくありません。トランザクションが最終的であることを知るには、それを含むトランザクションの上にいくつかのブロックが採掘されるのを待つ必要があります。ブロックの数は特定のチェーンと、私たちがどれだけの信頼を必要とするかによって異なります。スループットに関しては、設計によって作業の証明が計算的に高価であることを解決します。これは、各回に大量のトランザクションを追加する際に、ブロックチェーンのスループットへの依存を強制します。ただし、チェーンに追加されるトランザクションの数を制限するもう 1 つの理由があります:検証可能性。ブロックチェーンの分散性を維持するために、ネットワーク内の各ノードは、各トランザクションが合法であり、定められたルールに従って実行されることを検証できる必要があります。ネットワークが毎秒大量のトランザクションを受け入れる場合、強力なデバイスのみがそのチェーンを検証でき、必要なハードウェアにアクセスできないユーザーにはネットワークが欠落します。したがって、低スループットはブロックチェーンへの公共アクセスの保証に関連しています。
特に、イーサリアムは毎秒約 15 トランザクションを処理するように設計されています。イーサリアムでは、トランザクションが比較的複雑である可能性があるため、任意の計算を実行できるため、この上限は実際に必要な努力の量に関連しています。
これらのトランザクションは、ネットワーク内のすべてのユーザーとアプリケーション間で共有されます。従来の Web アプリケーションにとっても、これは非常に低い制限です。この制限に関するいくつかの方法は、8 章で見ることができます。
ビットコインからイーサリアムまで、これまで WWE はブロックデータを公共データベースとして扱ってきましたが、私たちはまだそのデータベースが含む可能性のある内容について深く掘り下げていません。最初の有名なブロックチェーンは、所有されているデジタル通貨を追跡するために使用されるビットコインです。
私たちが今日理解しているブロックチェーンの大部分は、2008 年にサトシ・ナカモトが彼の「ビットコイン:ピアツーピア電子現金システム」という論文で紹介したものです。この論文は短く、読みやすく、今日使用されているブロックチェーンの概念の大部分を包み込んでいます。これは、集中型の所有者や発行者なしの「純粋なピアツーピア版の電子現金」を導入しました。
要するに、ビットコインブロックチェーンは、ユーザーのビットコインの残高を追跡し、資金を 1 つの監査機関から別の監査機関に移転するトランザクションをサポートする公共の分散データベースであり、深く集中した電子支払いプラットフォームの実現です。特筆すべきは、通常の転送に加えて、ビットコインは制限されたスクリプト言語もサポートしています。この言語は、たとえば、将来の特定の期間に実行を制限する Timeelocks や、資産を移動するために複数のアカウントの同意を必要とするマルチシグネチャを構築することを可能にします。この言語で構築できるものは依然として限られています。これは、ネットワーク内の仲裁計算をサポートするために提案されました。
暗号学の歴史は古く、古代には主に軍事機密の伝送に使用されていました。「パスワード」、「暗号」などです。1970 年以前、暗号学の応用範囲はほとんど政府レベルにとどまっていましたが、標準暗号システムであるデータ暗号化標準や非対称暗号アルゴリズムの発明により、暗号学はさまざまな分野で徐々に深く応用されるようになりました。
暗号学の発展の歴史#
暗号学の発展は大きく 3 つの段階に分けられます:古典暗号学→現代暗号学→公開鍵暗号学
1. 古典暗号学:この段階の核心的な暗号学の思想は主に置換と置換です。置換とは、平文の各文字を別の文字に置き換えて暗号文を生成することを指し、受信者は対応する文字を置き換えて暗号文から平文を得ることができます。置換とは、平文の文字の順序を特定のルールに従って混乱させることを指します。
2. 現代暗号学:この段階の発展は主に対称暗号アルゴリズムです。対称暗号は、送信者が何らかの公開されたアルゴリズムを使用して平文を暗号化するためにキーを使用し、受信者が以前に送信者から与えられたキーを使用して暗号文を復号して平文を得ることを指します。
3. 公開鍵暗号学:この段階の発展は主に非対称暗号アルゴリズムです。非対称暗号の原理は、公開鍵で暗号化し、秘密鍵で復号することです。実装プロセスは、A が何らかのアルゴリズムを使用して一対のキーを生成し、それぞれ公開鍵と秘密鍵を持ち、公開鍵を公開します。B が A に情報を送信したい場合、A の公開鍵を使用して平文を暗号化し、暗号文を A に送信します。A は暗号文を受信した後、自分の秘密鍵を使用して暗号文を復号し、平文を得ます。
非対称暗号の解読の概念は以下の通りです。
非対称暗号には、公開鍵と秘密鍵が含まれます。
特徴は:
-
特徴 1:公開鍵で暗号化されたデータは、秘密鍵でのみ復号でき、公開鍵自体では復号できません。
-
特徴 2:秘密鍵で暗号化されたデータは、公開鍵でのみ復号でき、秘密鍵自体では復号できません。
-
サーバーは同時に公開鍵と秘密鍵を保持します(誰にも渡さない)。
-
サーバーが通信したい相手に自分の公開鍵を渡します。
非対称暗号を使用したインタラクションのプロセスは次のとおりです:クライアントは最初にサーバーの公開鍵を取得し、その公開鍵を使用してデータを暗号化し、暗号化されたデータをサーバーに送信します。上記の特徴 1、2 により、この時点でサーバーだけがデータを正しく復号できます。
暗号学はブロックチェーンに非常に広く応用されており、3 つのカテゴリに分けられます:対称暗号アルゴリズム、非対称暗号アルゴリズム、およびハッシュハッシュアルゴリズム。一般的な方法には、Merkle tree ハッシュツリーアルゴリズム、楕円曲線アルゴリズム、SHA-256 アルゴリズム、Base58 エンコーディングがあります。役割には、ハッシュアルゴリズムを使用して迅速に検索すること、平文を暗号化および復号化すること、情報に署名および検証すること、デジタル証明書を生成すること、アカウントアドレスを生成することなどがあります。
対称暗号アルゴリズムは、最も早く応用された暗号アルゴリズムであり、技術が成熟しています。
1 対称暗号の使用プロセス
対称暗号アルゴリズムでは、データの送信者は平文(元のデータ)と暗号化キーを特別な暗号化アルゴリズムで処理し、複雑な暗号化された暗号文を生成して送信します。受信者が暗号文を受信した場合、元のテキストを解読するには、暗号化に使用されたキーと同じアルゴリズムの逆アルゴリズムを使用して暗号文を復号する必要があります。対称暗号アルゴリズムでは、使用されるキーは 1 つだけであり、送信者と受信者の両方がこのキーを使用してデータを暗号化および復号化します。これにより、復号化側は事前に暗号化キーを知っている必要があります。
2 対称暗号の特徴
対称暗号アルゴリズムの特徴は、アルゴリズムが公開されていること、計算量が少ないこと、暗号化速度が速いこと、暗号化効率が高いことです。不足している点は、取引の両側が同じキーを使用するため、安全性が保証されないことです。さらに、各ユーザーが対称暗号アルゴリズムを使用するたびに、他の人が知らない一意のキーを使用する必要があり、これにより送信者と受信者が持つキーの数が幾何級数的に増加し、キー管理がユーザーの負担になります。たとえば、2 人のユーザーが対称暗号方式でデータを暗号化して交換する必要がある場合、ユーザーは少なくとも 2 つのキーを持って交換する必要があります。企業内のユーザーが n 人いる場合、企業全体で n×(n-1) 個のキーが必要になり、キーの生成と配布は企業の情報部門の悪夢になります。対称暗号アルゴリズムの安全性は、暗号化キーの保存状況に依存しますが、企業内の各キー保持者に秘密を守ることを要求することは不可能です。彼らは通常、意図せずにキーを漏洩します。ユーザーが使用するキーが侵入者によって取得された場合、侵入者はそのユーザーのキーで暗号化されたすべての文書を読み取ることができます。企業全体が 1 つの暗号化キーを共有している場合、企業全体の文書の機密性は無意味になります。
対称暗号アルゴリズムは分散ネットワークシステムでの使用が難しいですが、公開鍵暗号アルゴリズム、つまり非対称暗号アルゴリズムと比較すると、対称暗号アルゴリズムは暗号化と認証を提供できますが、署名機能が欠けているため、使用範囲が狭くなります。
3 対称暗号の分類
対称暗号はストリーム暗号とブロック暗号に分けられます。
ストリーム暗号は、平文の各バイトを順次暗号化します。暗号化は、ユーザーのキーを使用して、特定の複雑な演算(暗号アルゴリズム)を使用して、平文ストリームを暗号化するための擬似ランダムストリームを生成します。復号は、同じキーと暗号アルゴリズムを使用し、暗号化と同じ擬似ランダムストリームを使用して平文ストリームを復元します。
ブロック暗号は、平文の 1 ブロックを一度に暗号化します。平文を特定のビット長に分割し、平文ブロックを暗号化演算によって暗号文ブロックに変換し、暗号文ブロックを復号演算(暗号化演算の逆演算)によって復元します。
ストリーム暗号は、シードキーを使用してキー流生成器を介して平文の長さと一致する擬似ランダムシーケンスを生成する暗号アルゴリズムの一種です。
特定のメッセージ m に対してストリーム暗号を使用して暗号化操作を実行する場合、すべてのバイトが暗号化されます。一般的には、m を連続する文字に分割し、m=m1m2m3… とし、次にキー流 k=k1k2k3... の i 番目の文字 ki を使用して平文メッセージの i 番目の文字 mi を暗号化変換し、i=1,2,3...;すべての暗号化出力を連結すると、m を暗号化した後の暗号文が構成されます。復号は、暗号化と同期して行う必要があるため、ストリーム暗号を使用する場合、送信者と受信者は平文または暗号文の同じ位置で操作する必要があります。
暗号化および復号化プロセスの概略は次のとおりです。
ストリーム暗号は、実装が簡単で、ハードウェアでの実装が容易で、暗号化および復号化処理速度が速く、エラー伝播がないか、限られているなどの特徴がありますが、この種の暗号は主に軍事や政治機密機関で使用されているため、研究成果はあまり公開されていません。現在、他の分野で公開されているアルゴリズムには RC4、SEAL、A5 などがあります。
一度一密暗号#
一度一密暗号は、1917 年にマウボルグとヴェルナムによって共同で提案された理想的な暗号化スキームであり、平文メッセージを文字ごとに暗号化することを要求します。各文字の暗号化は独立しており、暗号化キーは平文の長さと一致する無作為なキーシーケンスであり、このキーシーケンスが一度一密の乱数本です。使用時、暗号文の送信者と受信者は、同じ乱数本を持っており、この乱数本は両者が合意した十分に長いランダムキーシーケンスです。送信者が平文を暗号化する際に使用するキーシーケンスは、乱数本のメッセージの長さの最初の部分から取得され、暗号化が完了した後、使用されたキーシーケンスは直ちに破棄されます。受信者は、乱数本のキーシーケンスを使用して暗号文を順次復号し、元のメッセージを得るとともに、使用されたキーシーケンスも破棄し、再利用しません。
一度一密の乱数本は無条件に安全な暗号体制と見なされており、すなわち破られない暗号体制です。盗聴者が暗号文情報を取得しても、復号する可能性は全くありません。なぜなら、暗号化キーは完全にランダムであり、規則性がないため、攻撃者はそれを暗号文分析するための情報を持っていないからです。しかし、一度一密の乱数本が漏洩しないことが前提です。
一度一密の概念の提案は、ストリーム暗号の生成に方向性を提供しました。この概念に基づいて、ますます多くのストリーム暗号アルゴリズムが次々と生まれています。
ストリーム暗号の構造#
ストリーム暗号の構造は、同期ストリーム暗号と自己同期ストリーム暗号に細分されます。同期ストリーム暗号は、キー流の生成が平文とは無関係であり、独立したランダムな方法によって生成された擬似ランダム数列です。自己同期ストリーム暗号は、非同期ストリーム暗号とも呼ばれ、同期ストリーム暗号とは反対に、キー流の生成が平文流に関連しており、具体的には、i 番目のキーの生成が前の平文の暗号化された文字に関連しています。自己同期暗号のこの特性により、研究が非常に難しくなり、ほとんどのストリーム暗号の研究は同期暗号に集中しています。
同期ストリーム暗号#
同期ストリーム暗号の暗号ストリームの生成プロセスは 2 つの部分に分かれます。1 つはキー流生成器、もう 1 つは暗号化変換器です。
暗号化プロセスの表現は次のとおりです:ci=E (ki,mi)、パラメータはすべてバイト配列の単一要素です。復号プロセスは暗号化プロセスと同期する必要があり、表現は 1 つです。キー流の生成は毎回異なります。したがって、暗号化時には、生成されたキー流要素を最初にレジスタにキャッシュし、復号に使用した後に次の暗号化を続けます。全体のプロセスは tcp プロトコルに似ています。現在最も一般的なストリーム暗号体制は、有限体 GF (2) 上の二元加法ストリーム暗号であり、その暗号化変換は ci=ki⊕mi として表されます。
特徴:
同期ストリーム暗号では、送信者と受信者は同期している必要があります。つまり、両者は同じキーを使用し、同じ位置で操作する必要があります。暗号文の文字が転送中に失われたり、破損したり、削除された場合、復号は失敗します。
2)エラー伝播なし
暗号文の文字が転送中に変更されても、その文字にのみ影響を与え、他の暗号文の文字の復号には影響しません。
3)能動的攻撃による同期性の破壊
同期が必要な結果として、能動的攻撃者が転送中の暗号文の文字を再送、挿入、削除などの破壊操作を行うと、暗号化および復号化プロセスの同期性が直接損なわれます。したがって、使用時には、他の暗号学的技術を利用して転送された暗号文の認証および完全性検証操作を行う必要があります。
2.2 自己同期ストリーム暗号
自己同期暗号のキー流の生成は、平文流および暗号文流とは独立しておらず、通常、i 番目のキーの生成は、主キーに加えて、すでに生成されたいくつかの暗号文の文字に関連しています。
特徴:
1)自己同期
送信者が暗号文流を転送する過程で、いくつかの暗号文の文字が攻撃されると、受信者の復号は、攻撃された暗号文と送信者の同期が取れないだけであり、他の暗号文流の復号は問題ありません。
2)限られたエラー伝播
受信者の復号は、攻撃された i 個の暗号文の文字にのみ影響を与え、他の暗号文流には問題がありません。したがって、生成される平文には最大 i 個のエラーがあります。
3)能動的攻撃による現在の同期性の破壊
4)平文の統計的拡散
各平文の文字は、その後のすべての暗号文に影響を与え、すなわち平文の統計的特性が暗号文に拡散します。したがって、自己同期ストリーム暗号は、平文の冗長性を利用した攻撃に対して同期ストリーム暗号よりも強力です。
2.3 キー流生成器
ストリームキーの重要な部分はキー流生成器です。理想的なキー流生成器は完全にランダムなキー流を生成しますが、実際にはユーザーの秘密鍵に基づいて特定のアルゴリズムによって生成されるため、真のランダム性を持つことはできず、生成されるキー流は擬似ランダムシーケンスです。
キー流生成器は通常、線形フィードバックシフトレジスタ(LFSR)と非線形組み合わせ部分で構成されます。線形フィードバックシフトレジスタは、駆動部分と呼ばれることがあります。その動作原理は、駆動部分の j 時点の状態変数 x を入力として、非線形組み合わせ部分 f に入力し、f(x)を現在の時刻の kj として出力します。駆動部分は、非線形組み合わせ部分が使用するシーケンスを提供し、非線形部分は各時刻のシフトレジスタの状態を組み合わせて、キーシーケンスの j 時刻の値 kj を生成します。一般的に言えば、駆動部分内部の変数は常に変化しており、各時刻の値は異なり、非線形組み合わせ部分に異なる時刻の x の値を継続的に入力し、非線形組み合わせ部分はこの時刻の x を受け取り、関数 f を通じて現在のキー流バイトを生成します。
2.4 フィードバックシフトレジスタ
フィードバックシフトレジスタは、ストリーム暗号がキー流を生成する重要な構成要素です。GF (2) 上の n 次フィードバックシフトレジスタは、n 個の二元ストレージと 1 つのフィードバック関数 f (a1,a2,a3,a4,...,an) で構成され、n 次フィードバックシフトレジスタは次の図のようになります。
各ストレージはシフトレジスタの 1 次と呼ばれ、任意の時点でこれらのレベルの内容はフィードバックシフトレジスタの状態を構成し、各状態は GF (2) 上の次元ベクトルに対応し、合計で 2^n の状態が可能です。各時点の状態は、長さ n のシーケンス a1、a2、a3、...、an または n 次元ベクトル(a1、a2、a3、...、an)で表され、ここで ai は現在の時点での i 次ストレージの内容です。初期状態はユーザーによって決定され、i 番目のシフトクロックパルスが到来すると、各レベルのストレージ ai はその内容を次のレベル ai-1 に渡し、フィードバック関数 f (a1,a2,a3,a4,...,an) はレジスタの現在の状態に基づいて次の時点の an を計算します。フィードバック関数は n 元のブール関数であり、すなわち n 個の変数 a1、a2、a3、...、an はそれぞれ独立して 0 と 1 の 2 つの可能な値を取ることができ、関数内の演算には論理 AND、論理 OR、論理補完などの演算が含まれ、最終的な関数値は 0 または 1 です。
RC4 アルゴリズム#
RC4 暗号アルゴリズムは、RSA 三人組のリーダーであるロン・リベストによって 1987 年に設計された可変長のストリーム暗号アルゴリズムのクラスです。このアルゴリズムの速度は、DES 暗号の約 10 倍に達し、非常に高いレベルの非線形性を持っています。1994 年 9 月、アルゴリズムはインターネット上で公開されました。RC4 アルゴリズムの暗号化は XOR を使用しているため、サブキーシーケンスが繰り返されると、暗号文が破られる可能性があります。RC4 は古い検証および暗号化アルゴリズムであり、ハッカー攻撃を受けやすいため、現在は使用が推奨されなくなっています。
RC4 アルゴリズムの実装は非常に簡単で、1 から 256 のバイト(8 から 2048 ビット)の可変長キーを使用して 256 バイトの状態ベクトル S を初期化します。S の要素は S [0]、S [1]、S [2]、...、S [255] と記述され、S は最初に S [i]=i として初期化されます。以降、常に 0 から 255 のすべての 8 ビット数を含みますが、置換操作が行われます。生成される各キーのバイトは、S の 256 要素から特定の方法で選択された要素によって生成されます。各キーのバイトが生成されるたびに、S ベクトル内の要素は置換操作を行います。したがって、RC4 アルゴリズムは 2 つの部分に分かれます:S の初期化とキー流の生成であり、キー流の生成プロセスでは、生成される各キーのバイトが対応する平文の要素と XOR 演算を行って暗号文を得ます。
1.1 S の初期化
S を生成する手順は次のとおりです:
1)長さ 256 のバイト配列を宣言し、S の要素に 0 から 255 までの昇順で埋めます。すなわち、S [0]=0、S [1]=1、S [2]=2、...、S [255]=255。
2)j:=0
3)0<=i<=255 の範囲で、次の 2 つの方法を繰り返します:
j = (j + S[i] + int(K[i%keylen])) % 256
S[i], S[j]=S[j], S[i]
1.2 キー流の生成
手順は次のとおりです:
1)i=0;j=0
2)i = (i + 1) % 256
3)j = (j + S[i]) % 256
4)S[i], S[j]=S[j], S[i]
5)出力キーのバイト key = S [(S [i]+S [j])%256]
1.3 RC4 の安全性
RC4 アルゴリズムの暗号化は XOR 方式を採用しているため、サブキーシーケンスが繰り返されると、暗号文が破られる可能性がありますが、現在 128 ビットの RC4 のキー長が繰り返される可能性は発見されていないため、RC4 は現在最も安全な暗号化アルゴリズムの 1 つと見なされています。
1.4 RC4 暗号化プロセス
RC4 の暗号化プロセスを簡単に紹介します:
1)自分のキーを使用してキー流発生器を生成します。
2)キー流発生器は平文の長さに基づいて擬似ランダムシーケンスを生成します。
3)擬似ランダムシーケンスの各ビット要素は、平文に対応するビット要素と XOR 演算を行い、暗号文を生成します。
示意図:
golang での RC4 暗号化の実装:#
package main
import "fmt"
func main() {
data := []byte("helloworld");
output:=make([]byte,len(data))
fmt.Printf("平文:%s\n", data);
K := []byte("qwuoaknfabbalafbj");
keylen := len(K);
SetKey(K, keylen);
output=Transform(output, data, len(data));
fmt.Printf("暗号文: %x\n", output);
SetKey(K, keylen);
output1:=make([]byte,len(data))
output1=Transform(output1, output, len(data));
fmt.Printf("復号後の平文:%s", output1);
}
var S = [256]int{}
//Sボックスの初期化
func SetKey(K []byte, keylen int) {
for i := 0; i < 256; i++ {
S[i] = i;
}
j := 0;
for i := 0; i < 256; i++ {
j = (j + S[i] + int(K[i%keylen])) % 256;
S[i], S[j]=S[j], S[i];
}
}
//キー流を生成
func Transform(output []byte, data []byte, lenth int)[]byte {
i := 0;
j := 0
output=make([]byte,lenth)
for k := 0; k < lenth; k++ {
i = (i + 1) % 256;
j = (j + S[i]) % 256;
S[i], S[j]=S[j], S[i];
key := S[(S[i]+S[j])%256];
//ビット単位のXOR操作
output[k] = uint8(key)^data[k];
}
return output
}
golang での封装された方法を使用して RC4 暗号化を実装しますが、復号はありません。
package main
import (
"fmt"
"crypto/rc4"
)
func main() {
var key []byte = []byte("fd6cde7c2f4913f22297c948dd530c84") //暗号化に使用するKEYを初期化
rc4obj, _ := rc4.NewCipher(key) //Cipherを返す
str := []byte("helloworld") //暗号化する必要のある文字列
plaintext := make([]byte, len(str)) //
rc4obj.XORKeyStream(plaintext, str)
//XORKeyStreamメソッドはsrcのデータをキーで生成された擬似ランダムビットストリームとXORし、dstに書き込みます。
//plaintextは、base-16エンコードされた文字列で、各バイトは2つの文字を使用して表され、文字列にフォーマットする必要があります。
stringinf := fmt.Sprintf("%x\n", plaintext) //文字列に変換
fmt.Println(stringinf)
}
ブロック暗号は、ブロック暗号とも呼ばれ、英語では Block Cypher と呼ばれ、一般的には平文 m をパディングして固定されたブロック長 s の整数倍の平文ストリング M を得ます。その後、M を長さ s のブロックに分割し、最後に各ブロックに同じキーを使用して暗号化変換を実行します。一般的なアルゴリズムには AES、DES、3DES があります。
ブロック暗号では、平文ブロックと暗号文ブロックの間には論理演算関係があり、これらの関係は演算のモードです。
一般的なブロック暗号演算の 5 つのモード:
-
電子コードブック(ECB)モード
-
暗号ブロックチェーン(CBC)モード
-
暗号フィードバックモード(CFB)
-
出力フィードバックモード(OFB)
-
カウンタモード(CTR)
現在推奨されているのは CBC モードと CTR モードであり、他のモードはあまり使用されていないか、推奨されていません。
1. ECB モード
ECB は電子コードブックモードとも呼ばれ、英語では Electronic codebook と呼ばれ、最も基本的なブロック暗号化モードです。暗号化前に暗号化ブロックサイズ(たとえば、AES は 128 ビット)に基づいていくつかのブロックに分割され、最後のブロックが 128 ビット未満の場合はパディング(具体的にはアルゴリズムによって異なりますが、デフォルトは 0x00)を使用し、その後、各ブロックを同じキーで個別に暗号化して暗号文ブロックを得て、暗号文ブロックを連結して暗号文を得ます。復号も同様です。
下の図は ECB モードの暗号化および復号化プロセスを示しています。
暗号化プロセス:
これにより、同じ平文内容は常に同じ暗号文に暗号化され、暗号文の形式は平文と同じになります。これは非常に安全ではなく、特に画像や平文の内容が多く繰り返される場合に問題となります。すべてのブロックの暗号化方式が一貫しているため、平文内の繰り返し内容は暗号文に反映されるため、統計分析攻撃に対抗するのが難しくなります。また、平文と暗号文の内容の順序が一致するため、攻撃者は暗号文を簡単に破壊できます。攻撃者が暗号文の転送中に暗号文の内容の順序を乱すと、受信者が得る暗号文は元の平文情報に復号できなくなります。これが ECB モードがほとんど使用されない理由でもあります。
特徴:
1. 操作が簡単で、実装が容易であり、並列計算に適しており、エラーは伝送されません;
2. 平文のパターンを隠すことができません;
3. 平文に対して能動的攻撃を行う可能性があります;
CBC モード#
CBC は暗号文ブロックリンクモードとも呼ばれ、英語では Cipher Block Chaining と呼ばれ、名前の由来は暗号文ブロックが鎖のように相互に接続されているためです。
CBC モードでは、各平文ブロックは最初に前の暗号文ブロックと XOR されてから暗号化されます。この方法では、各暗号文ブロックは前のすべての平文ブロックに依存します。同時に、各メッセージの一意性を保証するために、最初のブロックには初期化ベクトルを使用する必要があります。
最初のブロックのインデックスが 1 の場合、CBC モードの暗号化プロセスは次のようになります:
Ci = Ek (P ⊕ Ci-1), C0 = IV.
その解読プロセスは次のようになります:
Pi = Dk (Ci) ⊕Ci-1, C0 = IV.
CBC モードの演算プロセスの示意図
CBC アルゴリズムの利点:
-
平文の繰り返し配置は暗号文に反映されません
-
並列計算をサポートします(復号のみ)
-
任意の暗号文ブロックを復号することができます
CBC アルゴリズムの欠点: -
特定のエラービットを含む暗号文を復号する場合、最初のブロックのすべてのビットと次のブロックの対応するビットがエラーになります
-
暗号化は並列計算をサポートしません
CFB は暗号フィードバックとも呼ばれ、英語では Cipher feedback と呼ばれ、モードは CBC に似ており、ブロック暗号を自己同期ストリーム暗号に変換できます。動作プロセスも非常に似ています。ブロックのサイズと同じシフトレジスタを使用し、IV でレジスタを初期化します。次に、レジスタの内容をブロック暗号で暗号化し、結果の上位 x ビットを平文の x ビットと XOR して暗号文の x ビットを生成します。次に、生成された x ビットの暗号文をレジスタに移動し、次の x ビットの平文に対してこのプロセスを繰り返します。暗号化プロセスは CBC と同様であり、平文の変更はすべての暗号文に影響を与えます。したがって、暗号化プロセスは並列化できません。同様に、CBC と同様に、復号プロセスは並列化できます。
CFB モードの演算プロセスの示意図
CFB モードの利点:
-
パディングは必要ありません
-
並列計算をサポートします(復号のみ)
-
任意の暗号文ブロックを復号することができます
CFB モードの欠点:
-
暗号化は並列計算をサポートしません
-
特定のエラービットを含む暗号文を復号する場合、最初のブロックのすべてのビットと次のブロックの対応するビットがエラーになります
-
再送攻撃に対抗できません
OFB:ブロック暗号を同期シーケンス暗号として実行し、CFB に似ていますが、OFB では前の n ビットの暗号文出力ブロックがフィードバックされます。OFB にはエラー拡散の問題はありません。
出力フィードバックモード(Output feedback, OFB)は、ブロック暗号を同期ストリーム暗号に変換できます。これは、キー流のブロックを生成し、平文ブロックと XOR して暗号文を生成します。他のストリーム暗号と同様に、暗号文の 1 ビットの反転は、平文の同じ位置のビットも反転させます。この特性により、多くのエラー訂正コード、たとえばパリティビットは、暗号化前に計算され、暗号化後に検証されても正しい結果を得ることができます。
各 OFB を使用する出力ブロックは、前のすべての出力ブロックに関連しているため、並列処理はできません。ただし、平文と暗号文は最終的な XOR プロセスでのみ使用されるため、IV を事前に暗号化でき、最後に平文または暗号文を並列的に XOR 処理できます。
入力全 0 の CBC モードを使用して OFB モードのキー流を生成することができます。この方法は非常に実用的であり、CBC ハードウェアの実装を利用して OFB モードの暗号化プロセスを加速できます。
暗号化プロセス:
OFB モードの利点:
-
パディングは必要ありません
-
事前に暗号化、復号化の準備を行うことができます
-
暗号化と復号化は同じ構造を使用します
-
特定のエラービットを含む暗号文を復号する場合、平文の対応するビットのみがエラーになります
OFB モードの欠点:
-
並列計算をサポートしません
-
能動的攻撃者が暗号文ブロック内の特定のビットを反転させると、平文ブロック内の対応するビットも反転します
CTR モード#
カウンタモード(CTR モード)暗号化は、一連の入力データブロック(カウンタと呼ばれる)を暗号化し、ストリーム暗号を生成し、ストリーム暗号を平文と XOR して暗号文を得ます。同様に、復号はストリーム暗号を暗号文と XOR して平文を得ます。
データブロックは、逐次加算されるカウンタによって生成される異なるビットシーケンスを使用して暗号化される前に生成されます。これは nonce と counter(ブロック番号)で構成されます。CTR カウンタは、長さ 128 ビット(16 バイト)です。最初の 8 バイトは nonce と呼ばれる初期値であり、この値は毎回暗号化するたびに異なります。次の 8 バイトはブロック番号であり、常に + 1 される値です。nonce の役割は、データブロックの内容を複雑にすることです。nonce だけでなく、カウンタだけの場合、データブロックは非常に単純になります。Golang でのカウンタの実装は、ここで説明されているものとは若干異なります。最初に BLOCK.SIZE () の長さの初期ベクトル iv を初期化し、iv の最後のバイトはカウンタによって逐次増加され、同様に、暗号化される前の異なるデータブロックも生成されます。
暗号化プロセスは、初期カウンタを生成することです。8 つのブロックがあると仮定すると、初期カウンタから + 1 を繰り返して 8 つのカウンタ値を取得し、各カウンタ値を暗号化してキー流を生成し、各キー流と対応する平文ブロックを XOR して暗号文を得ます。したがって、暗号化プロセスは一度一密に相当します。
CTR モードでは、ブロックを任意の順序で暗号化および復号化できます。なぜなら、暗号化および復号化時に必要な「カウンタ」の値は nonce とブロック番号から直接計算できるからです。これは、並列計算を実現できることを意味します。並列計算をサポートするシステムでは、CTR モードの速度は非常に速いです。
下の図は、CTR モードの暗号化および復号化のプロセスを示しています。
暗号化プロセス:
unc AesCTR_Encrypt(plainText,key[]byte)[]byte{
//ユーザーが渡したキーが16バイトに適合するかどうかを確認し、適合しない場合は処理します
keylen:=len(key)
if keylen==0{ //ユーザーが渡したキーが空の場合はデフォルトキーを使用します
key=[]byte("wumansgygoaescbc") //デフォルトキー
}else if keylen>0&&keylen<16{ //キーの長さが0から16の間の場合は、0で残りを埋めます
key=append(key,bytes.Repeat([]byte{0},(16-keylen))...)
}else if keylen>16{
key=key[:16]
}
//1.使用する暗号aesを指定します
block, err := aes.NewCipher(key)
if err!=nil{
panic(err)
}
//2.パディングは不要で、直接ctrブロックモードのストリームを取得します
// ブロックを生成するキー流のStreamインターフェースを返し、初期ベクトルivの長さはブロックのブロックサイズと等しくなければなりません。
iv := []byte("wumansgygoaesctr")
stream := cipher.NewCTR(block, iv)
//3.暗号化操作
cipherText := make([]byte,len(plainText))
stream.XORKeyStream(cipherText,plainText)
return cipherText
}
func AesCTR_Decrypt(cipherText,key []byte)[]byte{
//ユーザーが渡したキーが16バイトに適合するかどうかを確認し、適合しない場合は処理します
keylen:=len(key)
if keylen==0{ //ユーザーが渡したキーが空の場合はデフォルトキーを使用します
key=[]byte("wumansgygoaescbc") //デフォルトキー
}else if keylen>0&&keylen<16{ //キーの長さが0から16の間の場合は、0で残りを埋めます
key=append(key,bytes.Repeat([]byte{0},(16-keylen))...)
}else if keylen>16{
key=key[:16]
}
//1.アルゴリズムを指定します:aes
block, err:= aes.NewCipher(key)
if err!=nil{
panic(err)
}
//2.カウンタモードの、底層がブロック生成のキー流のStreamインターフェースを返し、初期ベクトルivの長さはブロックのブロックサイズと等しくなければなりません。
iv := []byte("wumansgygoaesctr")
stream := cipher.NewCTR(block, iv)
//3.復号操作
plainText := make([]byte,len(cipherText))
stream.XORKeyStream(plainText,cipherText)
return plainText
}
//出力
40dbbf4ab999bb36d0d5
helloworld
非対称暗号は公開鍵暗号とも呼ばれます。
1976 年、ディフィとヘルマンは全く新しい暗号思想を提案しました。公開鍵暗号体制の思想です。当時、ほとんどすべての暗号体制は対称暗号体制であり、原理は置換や置換といった比較的単純な方法に基づいていました。公開鍵暗号体制は、これとは完全に異なり、2 つの異なるキー、すなわち公開鍵と秘密鍵を持ち、暗号化の原理も以前の単純な置換や置換ではなく、いくつかの複雑な数学関数です。これらの数学関数はすべて数学的難問に基づいています。一般に、基づいている難問は大きな整数分解問題、離散対数問題、楕円曲線問題の 3 つのカテゴリに分けられます。時には、楕円曲線問題も離散対数問題に分類されます。公開鍵暗号体制は革命的な変革であり、従来の暗号体制のモデルを突破し、従来の暗号体制の 2 つの大きな問題、すなわちキー配布とデジタル署名を解決しました。
1 非対称暗号の概要
従来の暗号体制では、1 つのキーを使用しており、送信者が受信者にキーを渡すコストが非常に高く、リスクも大きいです。受信者が受け取った暗号文が転送中に変更された場合、受信者は暗号文の真偽を判断できません。公開鍵体制は、上記の問題を完璧に解決します。1 対のキーがあり、1 つは公開鍵であり、完全に公開されており、誰でもそのキーを受け取ることができます。もう 1 つは秘密鍵であり、自分で保持し、誰にも伝える必要はありません。公開された公開鍵から秘密鍵を計算することはできないため、秘密鍵は安全です。送信者 A は公開鍵を使用して平文を暗号化し、受信者 B は対応する秘密鍵を使用して復号します。メッセージの完全性とメッセージの出所の正確性を保証するために、メッセージにデジタル署名を行う必要があります。A は暗号文に自分の秘密鍵を使用して再度暗号化し、このプロセスをデジタル署名と呼びます。B は受信した暗号文をその秘密鍵に対応する公開鍵で復号します。このプロセスを検証と呼びます。
したがって、公開鍵暗号体制は 2 つのモデルに分けられます:暗号化解読モデルと署名検証モデル。2 つのモデルは独立して使用することも、混合して使用することもできます。具体的には、通常、送信される暗号文はデジタル署名を必要とします。送信される内容には、暗号文と署名の 2 つの部分が含まれます。受信者は最初に検証を行い、検証が通過した後に復号を行います。
非対称暗号の方法は多くありますが、以下に RSA、DSA、ECDSA の 3 つの暗号方式を説明します。
公開鍵暗号体制の要件#
公開鍵暗号体制が実現するためには、次の要件を満たす必要があります:
1. 1 対のキー、すなわち公開鍵と秘密鍵を生成することが計算上容易であること;
2. 公開鍵を使用して平文を暗号化することが計算上容易であること;
3. 秘密鍵を使用して暗号文を復号することが計算上容易であること;
4. 公開鍵が知られている場合、秘密鍵を計算することができないこと;
5. 公開鍵と暗号文が知られている場合、平文を計算することができないこと;
6. 暗号化と復号の順序を入れ替えることができること。
現在、上記の要件を満たし、公開鍵暗号体制を確立するための困難な問題は多数ありますが、以下の 2 つの一般的な問題を分析します。
1. 大整数分解問題
2 つの大きな素数 p と q が知られている場合、n=pq を求めることは容易ですが、n が知られている場合、p と q を求めることはほぼ不可能です。これが大整数分解問題です。
2. 離散対数問題
2 つの概念、階と原根を理解します。
m > 1 かつ (a, m) = 1 であるとき、a^t ≡ 1 mod m が成り立つ最小の正の整数 t を a の m に対する階と呼び、δm (a) と記述します。
原根は数学記号です。m が正の整数で、a