こんにちは!CryptoGamesというブロックチェーンゲーム企業でエンジニアをしているかるでねです!
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。
このブログ以外でも情報発信しているので、よければ他の記事も見ていってください。
https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58
今回の記事では、ブロックチェーンを学んでいる際に出てきた暗号方式である、「共通鍵暗号方式」について理解していこうとおもいます。
「ブロックチェーン実践入門: ビットコインからイーサリアム、DApp開発まで」という本のなかで、自分が理解できなかった部分を、ググりまくって理解してこの記事にまとめています。
今回の主題は「共通鍵暗号方式」です。
「共通鍵暗号方式についてなんとなくしか理解できていない」
「共通鍵暗号方式についてもっと深く理解したい」
このような方の参考になれば幸いです。
前置きは不要だと思うので早速本題に入っていきましょう!
共通鍵暗号方式
説明
一言で説明すると以下のようになります。
データの暗号と復号(暗号化した文をもとに戻す)に同じ鍵を使用する。
言葉だけでは不安という方のために図でもみてみましょう。
「かるでね」というメッセージを鍵を使って暗号化して、暗号化した同じ鍵を使って復号化することで「かるでね」という文字が出てきます。
このようにすることでインターネット上で他の人に内容を知られることなく、渡したい相手にだけ渡すことができます。
「暗号化」と「復号化」に同じ鍵を使うため、比較的処理が高速になります。
ただし以下のような問題点があります。
通信相手が増えると鍵が増加する
通信相手の数だけ鍵が必要になってしまうため、管理が大変になってしまいます。
鍵が漏洩する可能性がある
インターネットを通じて鍵を渡すため、その鍵が第3者に漏洩してしまう恐れがある。
「送信者」、または「受信者」のどちらかの鍵が漏洩すると、暗号化したメッセージを盗み見たり、別のメッセージを暗号して受信者に渡すことができてしまう。
参考
ケルクホフスの原理
どのように暗号化されたかを知られても、安全であるべきという理論。
鍵以外の情報が知られなければ、情報が知られないようにしないといけない。
通常、「平文(暗号化する前の文章)」はネットワークを通っている間に盗聴されるなど危険なので、鍵で暗号化することにより盗聴されてもわからないようになる。
XOR関数
2つのうち片方が「正」で片方が「偽」の場合は「正」で、両方「正」または両方「偽」の場合は「偽」となる。
わかりづらいので表と図にしてみましょう。
左の表は「1」が「正」で、「0」が「偽」になっていて、先ほどの説明と一致していることが確認できるはずです。
右のベン図のオレンジ色部分が「正」の部分になります。
以下のような「交換律」、「結合律」なども成り立つことを頭の中にれておくとこの後が理解しやすい。
参考
ストリーム暗号
説明
「平文(暗号化もとのデータ)」データを1ビット・1バイト単位でXORして暗号化し、「復号(暗号文を平文に戻す)」は逆に暗号文を鍵とXORする暗号化方法のことです。
1ビット、1バイトごとに暗号化するため、異なる鍵が生成されます。
擬似乱数生成器とシードを使って文字をずらしていくという手順を取ります。
シード値で乱数を固定して、そのシード値を送信者と受信者で共有します。
メリット
- 誤り伝搬が少なく同期がしやすい。
- 受信したデータから逐次「復号(暗号文を平文に戻す)」できるため、処理時間が短く済む。
同期には以下の2つの方法があります。
外部同期型
送信者と受信者が常に同期した状態でデータのやり取りを行う「外部同期型」では、削除、挿入、再送が起きた場合同期が遮断されるので検知が容易という特徴があります。
自己同期型(非同期)
同期がずれた際に自動で修復できる「自己同期型(非同期)」では、1ビットの誤りが他のビットにも伝搬してしまうという特徴があります。
デメリット
- 疑似乱数生成器は過去に何度も攻撃を受けていて使用が推奨されていないものがある。
具体的には以下のようなものです。
ポイント
- SSL
- TLS
- WEP/WPA
- RC4
気になる方はぜひ自分で調べてみてください!
また、1ビットの情報が、対応する暗号文の1ビットの情報にしか写像されないため、拡散性がなく安全性が低いというデメリットもあります。
ブロック暗号
説明
平文(暗号化もとの文章)を64ビット、128ビット、256ビットなど大きなブロックに分割して、同じ鍵を使って暗号化する方法です。
暗号文ブロックも同じ長さになります。
同じ平文ブロックを暗号化すると同じ出力が得られるますが、暗号文から元のデータが推測できてしまうため危険です。
暗号利用モード
平文の単一ブロックに対する演算をどのように繰り返し適用するかを決めるためのものです。
平文がブロック長にみたない時は、「パディング」を行って足りない分のデータを埋めるという方法を取ります。
気になる方は自分で調べてみてください!
ECBモード
- 平文ブロックを暗号化したものがそのまま暗号文ブロックになる。
- 同じ平文ブロックを暗号化すると、同じ出力が得られるため機密性が低い。
CBCモード
- 1つ前の暗号文ブロックと平文ブロックをXORして暗号化。
CFBモード
- 1つ前の暗号文ブロックを暗号化した値と平文ブロックをXORして暗号ブロックとする。
OFBモード
- 暗号アルゴリズムの出力(鍵ストリーム)と平文ブロックをXORして、暗号ブロックとする。
- 「鍵ストリーム」とは、1つ前の暗号ブロックを暗号アルゴリズムで暗号化した値。
CTRモード
- 1ずつ増加していくカウンタを暗号化して、「鍵ストリーム」を作りだし、それを平文ブロックをXORして、暗号ブロックとする。
- 前半の8バイトは固定されていて、後半の8バイトがカウントアップされていく。
メリット
- 入力となる全ての平文ビットが複数の暗号文ブロックに拡散されるため、拡散性が高いです。
デメリット
- ストリーム暗号よりも暗号化と復号化に時間がかかってしまう。
- 1ビットのエラーがブロック全体を破損しかねない。
参考
疑似乱数生成器
複雑で予測できないように見える数字を出力するためのアルゴリズムのことです。
「疑似」とついているように真の乱数ではないが、あまり気にしなくても問題ありません。
以下の重要な特徴があります。
ポイント
- 0と1が同じ頻度で出現する。
- 規則性がないという、「無作為性」。
- 前の出力から次の出力を予測することができないという、「予測不可能性」。
- 狙って特定の出力ができないという、「再現不可能性」。
ワンタイムパッド
秘密鍵の事前共有を前提とする共有鍵暗号方式の1つのことです。
しかし、以下のような実用性に問題があります。
ポイント
- ストリーム暗号では鍵が平文と同じ長さになる。
- 1GBのファイルを暗号化するのに、鍵も1GBにになり容量が単純計算で倍になってしまう。
- 送信者と受信者でどうやって秘密鍵を安全共有するのか?(鍵配送問題)
- そもそも安全に共有できるならば暗号化する必要はないのでは?
最後に
どうだったでしょうか?
「共通鍵暗号方式」についての理解が多少は深まったのではないでしょうか?
「ヒーヒー」言いながら調べまくってまとめたのでもしかしたら理解が足りていない部分があるかもしれないです。
間違っている部分があったら優しくここのコメントかDMで教えていただけると嬉しいです🙇♂️
普段はPythonをメインに情報発信をしています。
Twitterの方もフォローしていただけると嬉しいです!
Tweets by cardene777