ECDHP:(P, aP, bP)が与えられた時にabPを求めよ
楕円離散対数問題(ECDLP): P, Aが与えられた時にA=aPとなるaを求めよ
ECDHPやECDLPが難しいとされている
楕円曲線を用いたDH鍵共有がECDH鍵共有
### 中間者攻撃
アリスとボブの間に入って、秘密鍵s, 公開鍵Sのうち、公開鍵Sを書き換える
Dec(s, c) = m
Enc(B, m) = c’
随机应变 ABCD: Always Be Coding and … : хороший
ECDHP:(P, aP, bP)が与えられた時にabPを求めよ
楕円離散対数問題(ECDLP): P, Aが与えられた時にA=aPとなるaを求めよ
ECDHPやECDLPが難しいとされている
楕円曲線を用いたDH鍵共有がECDH鍵共有
### 中間者攻撃
アリスとボブの間に入って、秘密鍵s, 公開鍵Sのうち、公開鍵Sを書き換える
Dec(s, c) = m
Enc(B, m) = c’
RSA暗号は冪乗の余りが持つ性質を利用した暗号
二つの素数pとqを選び、その二つをかけてn = pxqとする
整数2を選ぶ e.g. e=65537
e x d = (p-1)x(q-1)で割ったあまりとなるような整数dを探す
dが秘密鍵で nとeのペア(n, e)が公開鍵
nの素因数分解ができような大きなnを選ぶ必要がある
落としどつき一方向関数という
RSA暗号の基本方式は安全ではないとされ、RSA-OAEPが推奨されている
### OpenSSLによるRSA暗号の鍵の作り方
$ openssl version
OpenSSL 1.1.1f 31 Mar 2020
秘密鍵ファイルの作成
$ openssl genrsa 2048 > sec-test-key.txt
Generating RSA private key, 2048 bit long modulus (2 primes)
…………+++++
………………………………………..+++++
e is 65537 (0x010001)
公開鍵の作成
$ openssl rsa -pubout < sec-test-key.txt > pub-test-key.txt
writing RSA key
確認方法
$ openssl rsa -text -pubin -noout < pub-test-key.txt
RSA Public-Key: (2048 bit)
Modulus:
00:ac:d4:b1:05:d5:86:6d:83:4a:34:65:62:b9:b9:
d3:08:eb:23:ec:8f:11:4b:5d:f1:90:59:cd:b0:0f:
83:15:a5:90:09:f2:d6:13:9f:89:b4:98:cb:7c:1d:
// 省略
df:5b:ce:c4:03:55:14:b8:d2:30:7d:f3:99:03:96:
df:eb:cb:69:79:e3:b8:12:e4:80:b3:b3:7a:71:e9:
09:b9
Exponent: 65537 (0x10001)
$ openssl rsa -text -noout < sec-test-key.txt
RSA Private-Key: (2048 bit, 2 primes)
※privateExponentが秘密鍵を示す
Pythonによる動作確認
def convert_to_int(s): return int("".join(s.split()).replace(":",""),16)
n=convert_to_int("""
00:ac:d4:b1:05:d5:86:6d:83:4a:34:65:62:b9:b9:
d3:08:eb:23:ec:8f:11:4b:5d:f1:90:59:cd:b0:0f:
83:15:a5:90:09:f2:d6:13:9f:89:b4:98:cb:7c:1d:
81:13:d6:f8:f2:b7:b0:ac:03:3d:d5:00:f6:10:0f:
// 省略
14:0a:71:96:e1:0d:48:ee:8b:b1:74:ed:3b:c2:15:
3e:47:d9:1b:8c:5a:d3:a3:89:7a:20:37:6d:42:23:
3b:d2:3f:7a:5b:e4:75:c2:b7:89:d7:6b:48:8e:bd:
df:5b:ce:c4:03:55:14:b8:d2:30:7d:f3:99:03:96:
df:eb:cb:69:79:e3:b8:12:e4:80:b3:b3:7a:71:e9:
09:b9
""")
d=convert_to_int("""
00:8d:04:d6:94:2e:0f:8b:97:ce:9a:46:07:72:07:
7f:7c:0d:70:b8:7a:5b:e0:24:fd:0f:8d:56:d9:4b:
2e:e8:20:b9:10:85:05:cb:e9:26:d1:26:c3:11:b8:
79:33:98:fa:74:01:11:b4:a8:c8:70:de:61:e7:e4:
// 省略
b1:a2:ae:51:87:38:48:4b:70:ce:90:9b:3c:10:d0:
37:8b:84:73:56:c7:25:e2:f7:7e:ca:9a:eb:09:47:
42:52:6a:3b:d4:c3:04:87:27:8e:54:93:af:4b:04:
4e:02:23:1b:24:0a:49:63:ce:b8:5d:fd:7b:5d:c6:
13:26:3a:00:75:9c:51:bd:1d:cb:f2:40:c3:a2:6c:
ad:01
""")
e=65537
m=123456789
c=pow(m,e,n)
c
x=pow(c,d,n)
x
有限体と拡大体はAESや楕円曲線暗号など様々な暗号技術を実装しようとしたときに必要となる知識
加減乗除の四則演算ができる集合を体という
実数の集合や分数の集合は体なので実数体や有理数体という 有限個の集合からなる体は有限体という
### 拡大体
共通鍵暗号AES、ディスク暗号化XTS-AES、認証付き暗号で紹介するAES-GCMなどではF2の拡大体の演算が使われる
素数p未満の集合{0, 1, …, p-1}に四則演算の規則を入れたものを有限体Fpという
有限体F2をk個まとめて新たな四則演算を入れたものをF2の拡大体F2kという
有限体や拡大体は様々な暗号技術で利用されている
鍵共有とは秘匿されていない通信経路を用いて安全に秘密情報を共有するための仕組み
L 1976年に鍵共有方法、公開鍵暗号、署名の概念を発表
### 冪乗
(g^a)^b = g^ab = g^ba = (g^b)^a
xをnで割った余りがrの時、r = x mod nと書く 。プログラミング言語では x % n と表記する
冪乗の性質を使ってアリスとボブは鍵共有をする(DH鍵交換という)
1. アリスとボブでgとnを決めて固定する
2. アリスは秘密の値aを決めて A = g^a mod n を求めてボブに渡す
3. ボブも秘密の値bを決めて B = g^b mod n を求めてアリスに渡す
4. アリスはボブからもらったBから s = B^a mod n を求める
5. ボブもアリスからもらったAから s’ = A^b mod n を求める
冪乗の性質から s = s’ = g^ab(mod n)となる これがアリスとボブで共有した値で、共通鍵暗号の秘密鍵など二人だけしか知らない秘密の情報として利用する
DH鍵共有の安全性… DHP(DH Problem)はスーパーコンピュータでも解けないだろうとされている
ある向きの計算は簡単だが、その逆向きの計算が難しい関数を一方向性関数という
DH鍵共有はDHPやDLPといった数学的な問題の困難さを安全性の根拠にしている
TMP(Trusted Platform Module)はパソコンやスマートフォンに組み込まれているセキュリティ専用チップ
TMPはTCGが定めていて、TMP2.0は標準規格になっている
XTS-AESはブロック暗号AESを使った暗号方法の一つで、WindowsのBitLocker, macOSのFileVault2, Linuzのdm-cryptなどディスク暗号化ソフトウェアで利用される
安全に暗号通信するには平文の情報を漏らさないだけでなく暗号文の改竄攻撃も想定しなければならない
確率的アルゴリズムは安全な暗号文を作るために必要
暗号を繰り返し使って安全であるためには、同じ平文を暗号化して毎回異なる暗号文にならないといけない
EBCモードで暗号化すると、16バイトずつ暗号化しているので同じパターンが現れると同じ暗号データになってしまう
-> CBCモードでの暗号化が開発された
-> 同じ値を出力するのを決定的アルゴリズムという。一方、毎回異なる出力をするアルゴリズムを確率的アルゴリズム(CBCモード)という
### ECB(Electronic CodeBook)モード
平文をブロックに分割し、それぞれを暗号化して暗号文を作る方式
### CBC(Cipher Block Chaining)モード
CBCモードは平文をそのまま暗号化するのではなく、一つ前の暗号文ブロックと排他的論理和をとってから暗号化する
先頭の平文ブロックには一つ前の暗号文が無いので初期化ベクトルを用いる
### CTR(CounTeR)モード
ブロック暗号を使って擬似乱数を生成し、ストリーム暗号として利用するモード
CBCモードは大きな平文があった時にそれを分割して複数CPUを使って暗号化を並列処理することはできない
CTRモードは各暗号文が独立なので複数CPUを使って並列処理できる
CBCモードは以前はよく使われていたが最近は避けられる傾向にある
サーバは暗号に関するエラー情報を不用意に返さないようにする
平文をある決まったサイズに分割し、その分割した固まりごとに暗号化する方法
端数があれば、パディングと呼ばれる方法で一つのブロックを作って処理する
ブロックごとに暗号化モードに応じた処理を行う
1970年にDESと呼ばれるブロック暗号が使われていた(64ビット、鍵長は56ビット)
DESに変わる標準的暗号としてAES(Advanced Encryption Standard)が選出された
### AES概要
AESブロックは128ビットで鍵長は128, 192, 256ビットを選べる
AESの暗号化は、秘密鍵の初期設定後(AddRoundKey)、ラウンド関数と呼ばれる処理を一定回数繰り返す
最後に最終ラウンド関数と呼ばれる処理をして暗号化が完了する
ラウンド関数は鍵長に応じて9、11、13回行う。鍵長が大きいほど処理に時間がかかる
AESが理想的なブロック暗号なら全数探索のO(2^128)の計算コストがかかる
1. RoundKeyを作成する
2. 128ビットである1ブロックを8ビットずつの16個のデータX0からX15に分割する
3. 4×4のマス目の正方形に入れる
4. Roudkeyとマス目のデータの排他的論理和を取る
### ラウンド関数
ラウンド関数はSubBytes, ShiftRows, MixColumnsとAddRoundKeyを順番に処理する
L SubBytesはS -Boxという換字表による換字式暗号を行う
ShiftRows: 横の列ごとデータを左にずらす
MixColumns: 縦の列ごとにある決められた行列Aを掛ける演算をする(行列の成分)
最終ラウンド関数: MixColumnsを除いたSubByte, ShiftRows, AddRoundKeyの処理をする
AES-NI: IntelやAMDのCPUに搭載されているAESを高速処理するための専用命令 ARMアーキテクチャでも同様の専用命令を搭載していることがある
// 鍵
$key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
// 初期ベクトル
$iv = 'bbbbbbbbbbbbbbbb';
$str = 'hello world';
// 暗号化
$str = openssl_encrypt($str, 'AES-256-CBC', $key, 0, $iv);
echo "${str}\n";
// 複合する
$str = openssl_decrypt($str, 'AES-256-CBC', $key, 0, $iv);
echo "${str}\n";
$ php index.php
9due8hN1Y3j3t6sx/WnryA==
hello world
include("chilkat_9_5_0.php");
$crypt = new CkCrypt2();
$crypt->put_CryptAlgorithm('chacha20');
$crypt->put_KeyLength(256);
$crypt->put_EncodingMode('hex');
$ivHex = '000000000000000000000002';
$crypt->SetEncodedIV($ivHex, 'hex');
$crypt->put_InitialCount(42);
$keyHex = '1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0';
$crypt->SetEncodedKey($keyHex, 'hex');
$plainText = ''Twas brillig, and the slithy toves\nDid gyre and gimble in the wabe:\nAll mimsy were the borogoves,\nAnd the mome raths outgrabe.'';
$encStr = $crypt->ecnryptStringENC($plainText);
print $encStr . "\n";
$decStr = $crypt->decryptStringENC($encStr);
print $decStr . "\n";
// 暗号化したい文字列
$str = "保つのに時があり,捨てるのに時がある。";
// ワンタイムパッド
$pad = [
12,20,148,22,87,91,239,187,206,215,103,207,192,46,75,243,
204,61,121,210,145,167,108,78,166,129,109,239,138,134,150,196,
217,63,158,201,204,66,181,198,54,0,0,130,163,212,57,167,
169,115,170,50,109,116,173,177,252,242,233,3,33,28,139,73,
];
function convert($str, $pad){
$res = "";
for($i=0; $i<strlen($str); $i++) {
$c = ord(substr($str, $i, 1));
$cx = $c ^ $pad[$i];
$res .= chr($cx);
}
return $res;
}
$enc = convert($str, $pad);
echo "暗号化した文字列:{$enc}\n";
$dec = convert($enc, $pad);
echo "復号化した文字列:{$dec}\n";
for ($i = 0; $i < 10; $i++){
print(mt_rand().'<br>');
}
for ($i = 0; $i < 10; $i++){
print(mt_rand(1, 6).'<br>');
}
1772070118
2025234455
909739598
265570849
205762700
1249037110
503159177
1157558449
1270711055
1797668593
5
3
1
4
3
2
4
3
2
6