OpenSSLでメッセージ認証およびデジタル署名をシュミレーションする


##一、理論部分
###0、このブログを読む前に、知っておくべき知識がある。
データの安全性のために、明文データをアルゴリズムで暗号化する。明文が秘密文データになる（データを盗聴されるのを防ぐため）。

暗号化アルゴリズムは二つに分類される。対称アルゴリズムと非対称アルゴリズムである。

対称アルゴリズムとは、暗号化の両方は同じ秘密鍵とアルゴリズムで暗号化している。

 - 利点：暗号化するスピードが速い。暗号化後のファイルと計算量が小さい。暗号化効率が高いなど。
 - 欠点：同じ秘密鍵のため、あまり安全ではない。秘密鍵数量が多い。デジタル署名をサポートされていない。

非対称アルゴリズムとは、鍵のペアがある。秘密鍵と公開鍵である。公開鍵と秘密鍵は相対的である。公開鍵で暗号化し、秘密鍵で解読する。秘密鍵で暗号化し、公開鍵で解読する。

   - 利点：公開鍵共有、秘密鍵はインターネット上で送信する必要がない。デジタル署名はサポートする。
   - 欠点：暗号化スピードが遅い。暗号化効率が低い。

現在の大部分の暗号化は対称と非対称暗号化の**組み合わせ**で使われている。まず、非対称暗号化で対称暗号化アルゴリズムのキーを暗号化する。次に、対称暗号化アルゴリズムで実際データを暗号化する。
しかし、あるひとつの問題は、データソースの信頼度を検証できないことである。データの信頼度を認証ために、デジタル署名を必要する。

###1、デジタル署名の定義
**デジタル署名（Digital Signature）とは**、書面上の手書き署名のセキュリティ特性を模倣するために用いられる公開鍵暗号技術の一種である。
###2、デジタル署名の原理
デジタル署名は公開鍵暗号化を使用する。秘密鍵暗号化を使用して署名を生成し、公開鍵で署名を検証する。

 - 鍵生成アルゴリズムは署名者の"鍵ペア"（PK, SK）を生成する。PKは公開する検証鍵で、SKは秘密にする署名鍵である。
 - 署名生成アルゴリズムはメッセージと署名鍵SKを入力し、署名を生成する。
 - 署名検証アルゴリズムはメッセージ、検証鍵PK、署名を入力し、承認または拒否を出力する。

###3、認証局(Certificate AuthorityまたはCA,公開鍵証明書認証局)
**CAとは**、他の当事者にデジタル 公開鍵証明書 を発行する実体である。これは、信頼された第三者 の例である。

証明書発行機関をここに導入する。証明書発行機関はCA(Certificate Authority)である。CAは公開鍵を使用する各ユーザーにデジタル証明書を発行する。デジタル証明書の作用は証明書中リストのユーザーが証明書中リストの公開鍵を合法的に所有することである。CAのデジタル署名によって、アタッカーは証明書を偽造したり、改ざんしたりすることができなくなった。

###4、デジタル署名プロセスの詳細
**デジタル署名のトポロジ**
![デジタル署名.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654589/3006e786-606a-b5fa-5b0f-36e6b3c3925a.png)
                                   　　　　　　　　　　　　　　　　（画像ソース：2020 SPOTO ネットワーク；翻訳者：nowyouseeme）
**需要**：BはAと安全に通信したい。Bはデジタル署名で情報源がAであるかを確認する
**前提条件**：PubK-AとPubK-CAは公開の鍵である。CAの授権を受けたら、Bはこれら2つのキーをインターネットから取得できる。
**使用のアルゴリズム**：

- 対称暗号化：AES
- 非対称暗号化：RSA

**名詞の解釈**：

   - Mはメッセージである。
   - Key-Aは対称暗号化の秘密鍵である。
   - PriK-AとPubK-CAはRSAアルゴリズムの公開鍵である。
   - PubK-AとPriK-CAはRSAアルゴリズムの秘密鍵である。
   
> **ステップⅠ**：まずは、あるメッセージＭ（以下はMと略称する）の内容データ量が大きい且つ内容が機密である。AはAESでＭを暗号化する。暗号化されたＭはＭ'と表記する。次に、AはPriK-AでAESのパスワードを暗号化する。最後、AはCAに公開鍵PubK-AとID情報一緒に提出する。

> **ステップⅡ**：まずは、CAは公開鍵PubK-Aを入手後、SHA1やMD5でPubK-Aのhash値を計算する、そしてPriK-CAでPubK-Aのhash値を署名にデジタル署名を生成する。次に、CAはAのID情報を審査する。最後、PubK-A、審査済みのID情報とデジタル署名一緒にまとめてAの公開鍵証明書（デジタル証明書：CA暗号化後のファイル）として包装し、Aに返却する。

> **ステップⅢ**：この時、ＢはAにＭの送信を要求した。AはＭ'、公開鍵証明書と暗号化したAESのパスワード一緒にＢに送信する。

> **ステップⅣ**：まず、BはＭ'、公開鍵証明書と暗号化したAESのパスワードを入手後、Aの公開鍵証明書を開けてPubK-Aをもらう。そして、SHA1やMD5でPubK-Aのhash値H1を計算する。次に、PubK-CAで公開鍵証明書中のデジタル署名を解読したhash値H2を得る。最後、hash値H1とhash値H2を比較する。二つのhash値が同じであれば、認証を成功したことになる。それ以外の場合は失敗したことになる。

> **ステップⅤ**：これまでのところ、PubK-Aをもらう。このキーを使用して、暗号化したAESのパスワードを解読できる。そして、AESのパスワードをもらう。AESのパスワードでＭ'を解読する。最後に、明文Ｍを得る。

**メモ**：ステップⅡとステップⅣ中のHash値を計算する方法は同じであるべきである。さもなくば、検証に失敗する。
##二、実験部分
###1、実験環境：

- システム：windows 10ファミリー版
- opensslバージョン： 0.9.8h 28 May 2008

###2、実験前に準備したもの：


- Key-AはAES暗号化の秘密鍵だ（password.txt）；

- PubK-AとPubK-CAはRSAアルゴリズムの秘密鍵で、公開ではない。
- PriK-AとPriK-CAはRSAアルゴリズムの公開鍵で、公開できる。

- 明文：test.txt。
![test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654589/25b647a7-7790-755a-c0bd-b3c6f3feae5b.png)

- AESのパスワードファイル：password.txt。（password：123456）
![PASSWORD.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654589/ccabab2d-0b5f-f3fb-880b-c9d62bde30dc.png)
- BはAにtest.txtという名前のファイルの送信を要求した。仮説test.txtの内容は大量のデータがあり且つ内容が秘密なので、対称暗号化アルゴリズムでtxtファイルを暗号化にする必要がある。非対称暗号化アルゴリズムで対称暗号化アルゴリズムの秘密鍵を暗号化する。ここにAESとRSAアルゴリズムを使用している。

###3、実験ステップ
> **ステップ1**：まず、Aはメッセージの内容を対称暗号使用する。ここにAES暗号使用する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654589/551bbe32-ce64-a8f8-36ce-6c053902c22b.png)

```shell
OpenSSL> enc -aes256 -in test.txt -out aes256_test.txt -pass file:password.txt
```
>暗号化後のファイルの内容は：
![aes.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654589/406c3288-f004-7306-0a76-e22fdae2c7f6.png)
> **ステップ2**：次には、RSAでAES暗号化するパスワードを暗号化する。パスワードはPASSWORD.txtというの名前のファイル内に書き込みする、PubK-Aでこのファイルを暗号化する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654589/76ce039d-e086-7212-d41d-67afe08ecedb.png)

```shell
OpenSSL> rsautl -encrypt -in password.txt -inkey PubK-A.key -pubin -out PubK-A_password.txt`
```
>暗号化後のファイルの内容は：
![rsa_passwd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654589/ef30ead6-c4d7-8991-3c5f-d7dbe3097c12.png)
> **ステップ3**：AはPriK-A.keyファイルをCAに渡してデジタル署名を行う。
１）CAはPriK-CA.keyを使用してSHA1計算のhash値を得る且つ署名
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654589/a8b9fed6-976c-0f62-35fd-2b9817e29c57.png)

```shell
OpenSSL> dgst -sign PriK-CA.key -sha1 -out sha1_rsa_ca.sign PriK-A.key
C:\TEST>type sha1_rsa_ca.sign
```
>2）CAはsha1_rsa_ca.sign（デジタル署名ファイル：このファイルはPriK-A.keyのはhash値がある）、PriK-A.keyとある審査済みのメッセージ一緒にまとめてAの公開鍵証明書（CA暗号化後のファイル）として包装し、Aに返却する。
> **ステップ4**：この時、Aは公開鍵証明書、aes256_test.txtとPubK-A_password.txtをＢに送信する。Ｂは公開鍵証明書をもらった後、まず、PriK-A.keyにhash値Ⅰを計算する。次に、PubK-CA.keyでsha1_rsa_ca.signファイルに解読してhash値Ⅱをもらう。最後、hash値Ⅰとhash値Ⅱを比較する。二つのhash値が同じであれば、認証を成功したことになる。それ以外の場合は失敗したことになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654589/efc151ec-f222-91d4-20d4-159b6d9834f0.png)

```shell
OpenSSL> dgst -verify PubK-CA.key -sha1 -signature sha1_rsa_ca.sign PriK-A.key
```
>  **ステップ5**：これまでのところ、ＢはPriK-A.keyを得った、このキーを使用して、PubK-A_password.txtファイルを復号化し、AESアルゴリズムのパスワード明文を取得できます。 そして、test_aes256.txtファイルをAESパスワードで復号化して、test.txtのプ明文をもらう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654589/e45e20eb-10a1-c3ab-747f-68ffc1a86e4d.png)


```shell
OpenSSL>  rsautl -decrypt -in PubK-A_password.txt -inkey PriK-A.key -out dec_password.txt
Loading 'screen' into random state - done
OpenSSL> enc -aes256 -d -in aes256_test.txt -out dec_test.txt -pass file:dec_password.txt
```
>暗号化後のファイルの内容は：
![aes_dec.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654589/51afd711-7377-015b-c396-73a25cd64576.png)
![test_dec.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654589/71aa067f-945c-ff6f-e082-cedd3040a3d6.png)

**最後の比較**：Aの明文とＢが解読した明文を比較する。ファイルの内容は同じである。
![heika.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654589/e55573bc-46e3-3fac-e8c0-60088f80b589.png)
##三、メモと参考文献
**メモ**：

- sha1を使ってhash値を検証する。md5の検証方法はsha1と同じである。コマンド中のsha1をmd5に交換すればよい。
- RSAキーペアの生成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654589/dd7a22ed-c516-4f64-0eee-7a61ba33330b.png)

**最新情報**：一番人気のある接続とリモートサーバを管理するユーティリティOpenSSHはこのほど、SHA-1の検証方案に対するサポートを放棄すると発表した。最近の半年間で新たな衝突攻撃方法が現れたので、SHA-1のクラックコストを11万ドルと5万ドル以下に低減できる。具体的な情報は下記のリンクに詳しい。
https://www.zdnet.com/article/openssh-to-deprecate-sha-1-logins-due-to-security-risk/

以上
転載はソースを説明してください。読んでくれてありがとうございます。
**参考文献**：

   - [ OpenSSL documentation](https://www.openssl.org/docs/manmaster/man1/req.html)