pikesaku’s blog

個人的な勉強メモです。記載内容について一切の責任は持ちません。

互いに素とは?

ポイント

a, b を共に割り切る正の整数が 1 のみであること

(上記の言い換え)a, b の最大公約数 gcd(a, b) が 1 であること

英語でcoprime(共通点を持たない整数)

記号で a ⊥ b と表す

a,b両方とも素数ではない

例えば、3 と 10 を共に割り切る正の整数は 1 だけなので、これらは互いに素である。

RSAについて(作成中)

ポイント

名前の由来は開発者3人の名前の頭文字

公開鍵暗号の一種

公開鍵暗号 - Wikipedia

暗号化と復号に別個の鍵(手順)を用い、暗号化の鍵を公開できるようにした暗号方式

他にDiffie-Hellman key exchange(DH)があり
公開鍵暗号は、共通鍵暗号の共有鍵の交換で利用される

認証機能あり(デジタル署名で利用)

DHとの違い!DHには認証機能なし!
※openssl ciphersコマンドの結果で、au=DHの暗号化スイートがあるが、これもRSAを利用してる。
static-DHによるSSL/TLS - Qiita

電子署名として使えないDHの鍵ではCSRが作れないため、ダミーのRSA鍵を作り、それを元にCSRを作る。

確認コード

# -*- coding:utf-8 -*-
from sympy import prime
import random
import math
import time

T = int(time.time())

def pr_et(m):
  global T
  print(m + ":" + str(int(time.time()) - T))
  T = int(time.time())


def def_E_D(p1, p2):
  t1 = (p1 - 1)
  t2 = (p2 - 1)
  # t1とt2の最小公倍数
  L = (t1 * t2) // math.gcd(t1, t2)
  pr_et("fin_gen_L " + str(L))

  # 1 < E < L
  # gcd(E,L) = 1
  E = random.choice([ i for i in range(2,L) if math.gcd(i, L) == 1 ])
  pr_et("fin_gen_E " + str(E))

  # 1 < D < L
  # (E×D) mod L = 1
  D = random.choice([ i for i in range(2,L) if (E * i) % L == 1 ])
  pr_et("fin_gen_D " + str(D))
  return E, D


if __name__ == '__main__':
  # 暗号文 = 平文^E mod N
  # 平文 = 暗号文^D mod N
  # E、Nの組み合わせが公開鍵
  # D、Nの組み合わせが秘密鍵
  # Nは2つの大きな素数を掛けたもの
  t =  int(time.time())

  # N、E、D算出用素数。101と1101の指定は小さい値にならないようにする為。
  p1 = prime(random.randint(101,1101))
  p2 = prime(random.randint(101,1101))
  while p1 == p2:
    p2 = prime(random.randint(101, 1101))
  pr_et("fin_gen_p12 " + str(p1) + " " + str(p2))

  N = p1 * p2
  pr_et("fin_gen_N " + str(N))
  E, D = def_E_D(p1, p2)

  # 平文"あ"を数字化。ユニコードのコードポイント利用。
  CP = ord("あ")
  pr_et("fin_gen_CP " + str(CP))

  # 暗号化
  ENC = (CP ** E) % N
  pr_et("fin_gen_ENC " + str(ENC))

  # 復号化
  DEC = (ENC ** D) % N
  pr_et("fin_gen_DEC " + str(DEC))

  if CP == DEC:
    print('Success!')
  else:
    print('Failure!')

確認コードのポイント

必ずSuccessになる。
処理自体は、そんなに複雑ではない。
攻撃者は公開鍵(E,N)と暗号化データ(ENC)は取得可能
Ephemeralデータは使わない!=PFS対応でない

素朴な疑問

①E,N,ENCを使って総当たり計算したら、どのくらい時間かかるのだろう?
②暗号化可能な点は上記で理解できる。ただデジタル署名(復号できる=認証OK)は、どうやって実装してるのだろう?

素朴な疑問①について

確認コードの実行結果

fin_gen_p12 8297 4099:0
fin_gen_N 34009403:0
fin_gen_L 16998504:0
fin_gen_E 12379243:4
fin_gen_D 12788611:2
fin_gen_CP 12354:0
fin_gen_ENC 24181895:99
fin_gen_DEC 12354:285
Success!

そもそも、こんな計算できるの?とも思ったが、できてる。。。

平文 = 暗号文^D mod N
24181895 ** 12788611 % 34009403

E=2379243
N=34009403
ENC=24181895
上記からDECを総当たりで平文出そうとしたら、どれくらい時間かかるの?
う~ん、迷走中。

結局、DECは% Nで求められるので、1 < DEC < N(34009403)になる。
Nは公開鍵に含まれる情報。Nが小さいと、復号化をNパターンでTRYしてみて、結果が自然か?を機械学習で判定できれば、復号化できるのでは?
Nは大きくするのが必須だろう。
メールデータは、最初がReceived: ~とかで始まる前提を活用し、総当たりすれば、Nを少なくできるのでは?
メール本文がhogeだけとかのメールをSMTPSで送ってみて、そのパケットをキャプチャし、復号化をためして見ようかな。。。

Diffie-Hellman key exchangeについて

ポイント

読み方

ディフィー・ヘルマン(ディッフェルと勘違いしてた。。。)

公開鍵暗号の一種

公開鍵暗号 - Wikipedia

暗号化と復号に別個の鍵(手順)を用い、暗号化の鍵を公開できるようにした暗号方式

他にRSAがあり。
公開鍵暗号は、共通鍵暗号の共有鍵の交換で利用される

素数

正の約数が 1 と自分自身のみ

原子根

(3 以上の)素数 p と 1 以上 p 未満の整数 r が以下の性質を満たすとき r を p に対する原始根と呼ぶ。
「r,r2,⋯,rp−2 のいずれもが p で割って余り 1 でない」
★よく分からないけど、素数に対し存在する、ある条件に合致する整数と考える。
★一つの素数に対し複数存在することあり。例) 素数7の場合、5,3

送受信者間で交換する情報

確認コード

# -*- coding:utf-8 -*-
from sympy import prime
import random
import sym
from sympy.ntheory import is_primitive_root

if __name__ == '__main__':
  # 素数をランダムに設定(100~1100番目の範囲で)
  P = prime(random.randint(101,1101))
  # 選択した素数に対する原始根をランダムに設定
  G = random.choice([i for i in range(1,P) if is_primitive_root(i, P)])
  # 送信者側の乱数設定
  A = random.randint(1,P - 2)
  # 受信者側の乱数設定
  B = random.randint(1,P - 2)
  # 送信者が受信者に以下を通知
  GA_MOD_P = G ** A % P
  # 受信者が送信者に以下を通知
  GB_MOD_P = G ** B % P
  # 送信者が共有鍵を計算
  A_SKEY = GB_MOD_P ** A % P
  # 受信者が共有鍵を計算
  B_SKEY = GA_MOD_P ** B % P
  # 送信者と受信者の共有鍵が同一であることを確認
  if A_SKEY == B_SKEY:
    print('Success!')
  else:
    print('Failure!')

確認コードのポイント

・必ずSuccessになる
・数学の理論として、GB_MOD_P ** A % PとGA_MOD_P ** B % Pが同じになる点を利用し共通鍵を交換
・やりとりする情報は全てephemeral(短命の)=PFS対応
・Opensslの暗号化スイートでDHとDHEがあり。
・DHは証明書のDHパラメタを利用(static DH)
・DHEはDHパラメタを動的に生成

・A,Bが秘密鍵、G,P,GA_MOD_P,GB_MOD_Pが公開鍵



※参考URL
Pythonで数学の勉強:初等整数論 - Qiita
Ntheory Class Reference - SymPy 1.11 documentation
夜でもアッサム: SSL(TLS)のDHとDHEの違い

いつか理解できるように!

理解してるつもりの SSL/TLS でも、もっと理解したら面白かった話 · けんごのお屋敷
Diffie-Hellman で鍵交換しましょ★ - ✲゚。.ヾ(⌒(ノ'ω')ノ☆.。


いつか理解したいページなのでメモ

ネットワーク通信技術について(GRE、IPSEC)

はじめに

図は参考URLからの引用です。

GREとは?

GRE(Generic Routing Encapsulation)とは
RFC 2784 - Generic Routing Encapsulation (GRE)
RFC 1701 - Generic Routing Encapsulation (GRE)
【図解】tunnelインタフェースの使われ方 〜IPアドレス設定やVPNのトンネリング、OSPFのVirtual-Linkの代替、等〜│SEの道標
[改訂新版]SDN/OpenFlowで進化する仮想ネットワーク入門 - 伊勢 幸一 - Google ブックス
※標準化されたのがrfc2784

トンネルプロトコルの一つで、拠点間VPNで利用される

Layer2トンネリング→L2F、PPTPL2TP
Layer3トンネリング→GREIPsec

IPデータグラムの中にパケットをカプセル化

各拠点のNW間をPoint To Pointで接続。両方の終端ルータでカプセル化解除

拠点間のNW通信で、カプセル化したパケットのNW情報は使われない(=隠ぺい)

暗号化はしない

MTUケア必要(GREヘッダとカプセル化されたIPヘッダの分)

動作イメージ

f:id:pikesaku:20200501163730p:plain

f:id:pikesaku:20200501163908p:plain

※トンネルIFに設定したIPアドレスはあまり意味がない。参考URLに説明あり。

パケット/GREヘッダフォーマット

f:id:pikesaku:20200501163515p:plain

f:id:pikesaku:20200501163108p:plain

Checksumの中にトンネルIFに設定したIPが入る(実質意味のないIPアドセス)

IPSECとは?

PCのMTU設定について

PPPoEだとMTUが原因で遅くなる可能性あり。

「フレッツ 光ネクスト」を利用する際のMTU値はいくつに設定すべきですか。 | よくあるご質問|フレッツ光公式|NTT西日本

MTUを小さくする必要あり。
理由はPPPoEである為。

NUROの推奨MTUは1500

NURO光のMTU設定値は?|実際の速度は800M以上! NURO光の実測や評判は?


何故??

NURO 光はIPv6に完全対応!IPoE接続で納得の速さを実現 | NURO 光
OCN|PPPoE方式とIPoE方式との違い IPoE(IPv6)インターネット接続申込受付

どうやらPPPoEでなく、IPoEを使ってるから

IPoEは認証不要(回線自体で認証される)
余計なヘッダが不要なので、MTUに影響しないよう。

最適MTUの探索と調整

Windows環境でMTUの設定の方法 - Qiita

ping -f -l 1472 -n 1 www.nic.or.jp

netsh interface ipv4 show interface

netsh interface ipv4 set interface 数字 mtu=設定値
設定値は-lの数値プラスIPヘッダ20Byte、イーサネットフレーム8Byteを足した値
※-lは送信データのサイズ