Stand Up and Shout!

勉強したことや、思いついたことを気ままに記述します

Pythonでいかにして暗号を破るか

2020年12月23日に『Pythonでいかにして暗号を破るか』が出版されました。

マインドマップによる整理

TBD

目次の俯瞰

Pythonでいかにして暗号を破るか
    第0章 導入
        0.1 本書が想定する読者
        0.2 本書の内容
        0.3 本書の使い方
            0.3.1 ソースコードの入力
            0.3.2 タイプミスの確認
            0.3.3 本書のコーディング規約
            0.3.4 オンライン・リソース
        0.4 Pythonのダウンロードとインストール
            0.4.1 Windowsの場合
            0.4.2 macOSの場合
            0.4.3 Ubuntuの場合
        0.5 pyperclip.pyのダウンロード
        0.6 IDLEを開始する
        0.7 まとめ
    第1章 紙製の暗号ツールをつくる
        1.1 暗号学とは何か?
        1.2 符号 vs. 暗号
        1.3 シーザー暗号
            1.3.1 暗号ホイール
            1.3.2 暗号ホイールで暗号化する
            1.3.3 暗号ホイールで復号する
            1.3.4 算術による暗号化と復号
        1.4 二重暗号化はなぜうまくいかないのか
        1.5 まとめ (練習問題)
    第2章 対話型シェルのプログラミング
        2.1 いくつかの簡単な数式
        2.1.1 整数と浮動小数点数
        2.1.2 式
            2.1.3 演算の順序
            2.1.4 式の評価
        2.2 変数への値の代入
            2.2.1 変数の上書き
            2.2.2 変数名
        2.3 まとめ (練習問題)
    第3章 文字列とプログラムの作成
        3.1 文字列を用いてテキストを操作する
            3.1.1 +演算子による文字列の連結
            3.1.2 *演算子を使った文字列の複製
            3.1.3 インデックスを使用して文字列から文字を取得する
        3.2 print()関数で値を出力する
        3.3 エスケープ文字を表示する
        3.4 一重引用符と二重引用符
        3.5 IDLEのファイルエディターでプログラムを書く
        3.6 “Hello, World!”プログラムのソースコード
        3.7 オンライン差分ツールでソースコードを確認する
        3.8 プログラムにアクセスするためにIDLEを使用する
            3.8.1 プログラムを保存する
            3.8.2 プログラムを実行する
            3.8.3 保存済みのプログラムを開く
        3.9 “Hello, World!”プログラムがどのように動作するのか
            3.9.1 コメント
            3.9.2 ユーザーへの指示を表示する
            3.9.3 ユーザーからの入力を受け取る
            3.9.4 プログラムを終了する
        3.10 まとめ (練習問題)
    第4章 逆暗号
        4.1 逆暗号プログラムのソースコード
        4.2 逆暗号プログラムの実行例
        4.3 コメントと変数を設定する
        4.4 文字列の長さを調べる
        4.5 whileループ
            4.5.1 bool型
            4.5.2 比較演算子
            4.5.3 ブロック
            4.5.4 whileループ文
            4.5.6 文字列の成長
        4.6 input()プロンプトでプログラムを改善する
        4.7 まとめ(練習問題)
    第5章 シーザー暗号
        5.1 シーザー暗号プログラムのソースコード
        5.2 シーザー暗号プログラムの実行例
        5.3 モジュールのインポートと変数の設定
        5.4 定数と変数
        5.5 forループ文
            5.5.1 forループの例
            5.5.2 whileループとforループの等価性
        5.6 if文
            5.6.1 if文の例
            5.6.2 else文
            5.6.3 elif文
        5.7 in演算子とnot in演算子
        5.8 find()文字列メソッド
        5.9 シンボルの暗号化と復号
            5.9.1 ラップアラウンドの処理
            5.9.2 シンボルセットに含まれないシンボルに対する処理
        5.10 変換された文字列の表示とコピー
        5.11 他のシンボルを暗号化する
        5.12 まとめ(練習問題)
    第6章 総当たり攻撃によるシーザー暗号の解読
        6.1 シーザー暗号を解読するプログラムのソースコード
        6.2 シーザー暗号の解読プログラムの例
        6.3 変数を設定する
        6.4 range()関数でループする
        6.5 メッセージを復号する
        6.6 鍵と復号したメッセージを表示するために文字列書式化を使う
        6.7 まとめ(練習問題)
    第7章 転置式暗号で暗号化する
        7.1 転置式暗号の仕組み
            7.1.1 手動でメッセージを暗号化する
            7.1.2 暗号化プログラムを作成する
        7.2 転置式暗号プログラムのソースコード
        7.3 転置式暗号プログラムの実行例
        7.4 def文を使って独自の関数を作成する
            7.4.1 パラメーターを持ち、引数を取る関数を定義する
            7.4.2 関数内でのみに存在するパラメーターを変更する
            7.4.3 main()関数を定義する
        7.5 引数として鍵とメッセージを渡す
        7.6 リスト型
            7.6.1 リスト内の要素に再代入する
            7.6.2 リストのリスト
            7.6.3 リストに対してlen()とin演算子を使用する
            7.6.4 +および*演算子を使った、リストの連結と複製
        7.7 転置式暗号の暗号化のアルゴリズム
        7.8 拡張代入演算子
        7.9 messageを通じてcurrentIndexを移動する
        7.10 join()文字列メソッド
        7.11 返り値とreturn文
            7.11.1 return文の例
            7.11.2 暗号文を返す
        7.12 変数__name__
        7.13 まとめ(練習問題)
    第8章 転置式暗号を復号する
        8.1 紙上で転置式暗号を復号する方法
        8.2 転置式暗号の復号プログラムのソースコード
        8.3 転置式暗号の復号プログラムの実行例
        8.4 モジュールのインポートとmain()関数の設定
        8.5 鍵を使用してメッセージを復号する
            8.5.1 round()、math.ceil()、math.floor()関数
            8.5.2 decryptMessage()関数
            8.5.3 論理演算子
            8.5.4 列と行の変数を調整する
        8.6 main()関数を呼び出す
        8.7 まとめ(練習問題)
    第9章 プログラムテスト用プログラムを作成する
        9.1 転置式暗号のテストプログラムのソースコード
        9.2 転置式暗号のテストプログラムの実行例
        9.3 モジュールをインポートする
        9.4 疑似乱数を作成する
        9.5 ランダムな文字列を作成する
            9.5.1 文字列をランダムな回数分複製する
            9.5.2 リストの変数は参照を使用する
            9.5.3 参照を渡す
            9.5.4 copy.deepcopy()を使用してリストを複製する
            9.5.5 random.shuffle()関数
            9.5.6 文字列をランダムに撹拌する
        9.6 各メッセージをテストする
        9.7 暗号の動作確認とプログラムの終了
        9.8 main()関数を呼び出す
        9.9 テストプログラムをテストする
        9.10 まとめ(練習問題)
    第10章 ファイルの暗号化と復号
        10.1 プレーンテキストファイル
        10.2 転置式ファイル暗号プログラムのソースコード
        10.3 転置式ファイル暗号プログラムの実行例
        10.4 ファイルを操作する
            10.4.1 ファイルを開く
            10.4.2 ファイルへの書き込みとクローズ
            10.4.3 ファイルから読み込む
        10.5 main()関数を設定する
        10.6 ファイルの存在を確認する
            10.6.1 os.path.exists()関数
            10.6.2 os.path.exists()関数で入力ファイルが存在するかどうかを確認する
        10.7 文字列メソッドを使用してユーザー入力をより柔軟にする
            10.7.1 upper()、lower()、title()文字列メソッド
            10.7.2 startswith()とendswith()文字列メソッド
            10.7.3 文字列メソッドをプログラムで使用する
        10.8 入力ファイルを読み込む
        10.9 暗号化や復号のための時間を計測する
            10.9.1 timeモジュールとtime.time()関数
            10.9.2 プログラムでtime.time()関数を使う
        10.10 出力ファイルを書き込む
        10.11 main()関数を呼び出す
        10.12 まとめ(練習問題)
    第11章 プログラムによる英語の検出
        11.1 コンピュータは英語であることをどのようにしてわかるのか?
        11.2 英語検知モジュールのソースコード
        11.3 英語検知モジュールの動作例
        11.4 指示と定数の設定
        11.5 辞書型
            11.5.1 辞書とリストの違い
            11.5.2 辞書の要素を追加・変更する
            11.5.3 辞書に対してlen()関数を使用する
            11.5.4 辞書と一緒にin演算子を使用する
            11.5.5 リストより辞書の方が高速に要素を検索する
            11.5.6 辞書と一緒にループを使用する
        11.6 辞書ファイルを実装する
            11.6.1 split()メソッド
            11.6.2 辞書ファイルを個々の単語に分割する
            11.6.3 辞書データを返す
        11.7 メッセージ内の英単語を数える
            11.7.1 ゼロ除算エラー
            11.7.2 英単語と一致したものを数える
            11.7.3 float()、int()、str()関数と整数の除算
            11.7.4 メッセージ内の英単語の割合を求める
        11.8 非アルファベット文字を削除する
            11.8.1 append()リストメソッド
            11.8.2 アルファベット文字だけの文字列を作成する
        11.9 英単語を検出する
            11.9.1 デフォルト引数を使用する
            11.9.2 割合を計算する
            11.10 まとめ(練習問題)
    第12章 転置式暗号を解読する
        12.1 転置式暗号解読プログラムのソースコード
        12.2 転置式暗号解読プログラムの実行例
        12.3 モジュールをインポートする
        12.4 三重引用符を含む複数行の文字列
        12.5 メッセージを解読した結果を表示する
        12.6 解読されたメッセージを取得する
            12.6.1 strip()文字列メソッド
            12.6.2 strip()文字列メソッドを適用する
            12.6.3 メッセージの解読の失敗
        12.7 main()関数を呼び出す
        12.8 まとめ(練習問題)
    第13章 アフィン暗号のためのモジュラー算術モジュール
        13.1 モジュラー算術
        13.2 モジュラー演算子
        13.3 最大公約数を計算するための約数を見つける
        13.4 多重代入
        13.5 GCDを求めるユークリッドのアルゴリズム
        13.6 乗法暗号とアフィン暗号の仕組みの理解
            13.6.1 妥当な乗法鍵を選択する
            13.6.2 アフィン暗号による暗号化
            13.6.3 アフィン暗号の復号
            13.6.4 モジュラー逆数を求める
            13.6.5 整数除算演算子
        13.7 Cryptomathモジュールのソースコード
        13.8 まとめ(練習問題)
    第14章 アフィン暗号のプログラミング
        14.1 アフィン暗号プログラムのソースコード
        14.2 アフィン暗号プログラムの実行例
        14.3 モジュール、定数、およびmain()関数を設定する
        14.4 鍵の計算と検証
            14.4.1 タプル型
            14.4.2 脆弱な鍵を確認する
            14.4.3 アフィン暗号の鍵の総数はいくつか?
        14.5 暗号化関数を作成する
        14.6 復号関数を作成する
        14.7 ランダムな鍵を生成する
        14.8 main()関数を呼び出す
        14.9 まとめ(練習問題)
    第15章 アフィン暗号を解読する
        15.1 アフィン暗号解読プログラムのソースコード
        15.2 アフィン暗号解読プログラムの実行例
        15.3 モジュール、定数、およびmain()関数を設定する
        15.4 アフィン暗号の解読関数
            15.4.1 指数演算子
            15.4.2 鍵の総数を計算する
            15.4.3 continue文
            15.4.4 コードをスキップするためにcontinueを使う
        15.5 main()関数を呼び出す
        15.6 まとめ(練習問題)
    第16章 単一換字式暗号のプログラミング
        16.1 単一換字式暗号の仕組み
        16.2 単一換字式暗号プログラムのソースコード
        16.3 単一換字式暗号プログラムの実行例
        16.4 モジュール、定数、およびmain()関数を設定する
        16.5 sort()リストメソッド
        16.6 ラッパー関数
        16.7 translateMessage()関数
            16.7.1 isupper()とislower()文字列メソッド
            16.7.2 isupper()で大文字を保持する
        16.8 ランダムな鍵を生成する
        16.9 main()関数を呼び出す
        16.10 まとめ(練習問題)
    第17章 単一換字式暗号を解読する
        17.1 単語パターンを用いて解読する
            17.1.1 単語パターンを検索する
            17.1.2 復号文字の候補を検索する
        17.2 解読プロセスの概要
        17.3 単語パターンのモジュール
        17.4 単一換字式暗号解読プログラムのソースコード
        17.5 単一換字式暗号解読プログラムの実行例
        17.6 モジュールと定数を設定する
        17.7 正規表現で文字を検索する
        17.8 main()関数を設定する
        17.9 ユーザーに解読結果を表示する
        17.10 暗号文字マッピングを作成する
            17.10.1 空のマッピングを作成する
            17.10.2 マッピングに文字を追加する
            17.10.3 2つのマッピングを交差させる
            17.10.4 文字マッピングのヘルパー関数の仕組み
            17.10.5 マッピングで解読された文字を識別する
            17.10.6 removeSolvedLetterFromMapping()関数をテストする
        17.11 hackSimpleSub()関数
            17.11.1 replace()文字列メソッド
            17.11.2 メッセージを復号する
            17.11.3 対話型シェルで復号する
        17.12 main()関数を呼び出す
        17.13 まとめ(練習問題)
    第18章 ヴィジュネル暗号のプログラミング
        18.1 ヴィジュネル暗号で複数の文字鍵を使用する
            18.1.1 長いヴィジュネル暗号の鍵はより安全になる
            18.1.2 辞書式攻撃を防ぐ鍵を選択する
        18.2 ヴィジュネル暗号プログラムのソースコード
        18.3 ヴィジュネル暗号プログラムの実行例
        18.4 モジュール、定数、およびmain()関数を設定する
        18.5 List-Append-Joinプロセスで文字列を作成する
        18.6 メッセージを暗号化・復号する
        18.7 main()関数を呼び出す
        18.8 まとめ(練習問題)
    第19章 頻度分析
        19.1 テキスト内の文字の頻度を分析する
        19.2 文字の頻度とのマッチング
            19.2.1 単一換字式暗号の頻度マッチスコアを計算する
            19.2.2 転置式暗号の頻度マッチスコアを計算する
            19.2.3 ヴィジュネル暗号を頻度分析する
        19.3 文字の頻度分析のためのソースコード
        19.4 ETAOIN順で文字を保持する
        19.5 メッセージ内の文字をカウントする
        19.6 タプルの最初の要素を取得する
        19.7 頻度によって文字を並び替える
            19.7.1 getLetterCount()で文字をカウントする
            19.7.2 出現回数と文字リストの辞書を作成する
            19.7.3 文字リストをETAOINの逆順で並び替える
            19.7.4 出現回数で辞書リストをソートする
            19.7.5 ソートされた文字たちのリストを作成する
        19.8 メッセージの頻度マッチスコアを計算する
        19.9 まとめ(練習問題)
    第20章 ヴィジュネル暗号を解読する
        20.1 ヴィジュネル暗号を辞書式攻撃する
        20.2 ヴィジュネル暗号の辞書式攻撃プログラムのソースコード
        20.3 ヴィジュネル暗号の辞書式攻撃プログラムの実行例
        20.4 ヴィジュネル暗号の辞書式攻撃プログラムについて
        20.5 カシスキー検査で鍵長を発見する
            20.5.1 反復を見つける
            20.5.2 スペーシングの因数を取得する
            20.5.3 文字列からN番目の文字を取得する
            20.5.4 頻度分析でサブ鍵を解読する
            20.5.5 鍵の候補で総当たり攻撃する
        20.6 ヴィジュネル暗号解読プログラムのソースコード
        20.7 ヴィジュネル暗号解読プログラムの実行例
        20.8 モジュールのインポートとmain()関数の設定
        20.9 反復を見つける
        20.10 スペーシングの因数を計算する
            20.10.1 set()関数で重複を削除する
            20.10.2 重複する因数の削除とリストのソート
            20.10.3 もっとも共通する因数を探す
        20.11 もっとも可能性の高い鍵長を見つける
            20.11.1 extend()リストメソッド
            20.11.2 辞書repeatedSeqSpacingsを拡張する
            20.11.3 factorsByCountから因数を取得する
        20.12 同じサブ鍵で暗号化された文字を取得する
        20.13 可能性が高い鍵長で復号を試みる
            20.13.1 print()のためのendキーワード引数
            20.13.2 サイレントモードでのプログラムの実行、またはユーザーへの情報の表示
            20.13.3 サブ鍵の候補の組み合わせを得る
            20.13.4 元の大文字・小文字の書式を維持した復号結果を表示する
        20.14 解読したメッセージを返す
            20.14.1 鍵の候補が見つかったときにループを中断する
            20.14.2 他のすべての鍵長で総当たり攻撃する
        20.15 main()関数を呼び出す
        20.16 解読プログラムの定数を修正する
        20.17 まとめ(練習問題)
    第21章 ワンタイムパッド暗号
        21.1 解読できないワンタイムパッド暗号
            21.1.1 鍵長をメッセージ長と同じにする
            21.1.2 鍵を真にランダムにする
            21.1.3 ツータイムパッドを避ける
            21.1.4 ツータイムパッド暗号はなぜヴィジュネル暗号なのか
        21.2 まとめ(練習問題)
    第22章 素数の検索と生成
        22.1 素数とは何か?
        22.2 素数モジュールのソースコード
        22.3 素数モジュールの実行例
        22.4 試し割りアルゴリズムの仕組み
        22.5 試し割りアルゴリズムによる素数テストを実装する
        22.6 エラトステネスのふるい
        22.7 エラトステネスのふるいで素数を生成する
        22.8 Rabin-Millerの素数テストのアルゴリズム
        22.9 巨大な素数を見つける
        22.10 巨大な素数を生成する
        22.11 まとめ(練習問題)
    第23章 公開鍵暗号の鍵を生成する
        23.1 公開鍵暗号
        23.2 認証の問題
            23.2.1 デジタル署名
            23.2.2 中間者攻撃に注意する
        23.3 公開鍵と秘密鍵を生成するためのステップ
        23.4 公開鍵生成プログラムのソースコード
        23.5 鍵生成プログラムの実行例
        23.6 main()関数を作成する
        23.7 generateKey()関数を使用して鍵を生成する
            23.7.1 eの値を計算する
            23.7.2 dの値を計算する
            23.7.3 鍵を返す
        23.8 makeKeyFiles()関数で鍵ファイルを作成する
        23.9 main()関数を呼び出す
        23.10 ハイブリッド暗号方式
        23.11 まとめ(練習問題)
    第24章 公開鍵暗号のプログラミング
        24.1 公開鍵暗号の仕組み
            24.1.1 ブロックを作成する
            24.1.2 文字列をブロック値に変換する
            24.1.3 公開鍵暗号における暗号化と復号の数学的理論
            24.1.4 ブロック値を文字列に変換する
            24.1.5 なぜ公開鍵暗号を解読できないのか?
        24.2 公開鍵暗号プログラムのソースコード
        24.3 公開鍵暗号プログラムの実行例
        24.4 プログラムを設定する
        24.5 プログラムが暗号化または復号するかどうかを決定する方法
        24.6 getBlocksFromText()で文字列をブロックに変換する
            24.6.1 min()関数とmax()関数
            24.6.2 ブロックをblockIntに格納する
        24.7 復号のためにgetTextFromBlocks()を使う
            24.7.1 insert()リストメソッドを使う
            24.7.2 メッセージリストを結合して単一の文字列にする
        24.8 encryptMessage()関数を作成する
        24.9 decryptMessage()関数を作成する
        24.10 公開鍵や秘密鍵の鍵ファイルから鍵を読み込む
        24.11 ファイルに暗号文を書き込む
        24.12 ファイルを復号する
        24.13 main()関数を呼び出す
        24.14 まとめ
    付録 Pythonコードのデバッグ
        A.1 デバッガーの仕組み
        A.2 逆暗号プログラムをデバッグする
        A.3 ブレークポイントを設定する
        A.4 まとめ
    索引