openssl で pfx ファイルの暗号化方式を推測する

(メモ用です)

Windows のバージョンによっては `証明書のエクスポート ウィザード` 画面で、暗号化を選択できる場合があります (`秘密キーをエクスポートします` を選択した場合)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/364126/19a66f24-2247-86e5-b3fb-cffeb71e3c1a.png)

# AES256-SHA256 を選択した場合の問題点

`AES256-SHA256` でエクスポートした pfx を Windows Server 2016 でインポートしようとすると問題が発生しました。

PowerShell の `Import-PfxCertificate` cmdlet で、その pfx をインポートしようとすると、
- `Import-PfxCertificate : The PFX file you are trying to import requires either a different password or membership in an Active Directory principal to which it is protected.` という謎のエラーが発生

`X509Certificate2.Import` でインポートをしようとすると、
- `The specified network password is not correct` という謎のエラーが発生

インポートに使用したパスワードが誤っていないとすれば、どうしてか…

# pfx ファイル形式について知る

pfx ファイルに適用した暗号化方式を知ることができるのでしょうか。

Google 検索していると [Which encryption algorithm is used in password protected *.pfx/PKCS 12 certificates?](https://security.stackexchange.com/a/152901) に求めていた答えがありました

> TL;DR: The PKCS#12 format only specifies the structure of the file, it does not list which algorithms are legal, so the actual encryption algorithm used will depend on which software was used to create the .p12 file.

[Bing 翻訳] `DR: PKCS # 12 形式はファイルの構造を指定するだけで、どのアルゴリズムが有効かはリストされないので、使用される実際の暗号化アルゴリズムは、. p12 ファイルの作成に使用されたソフトウェアによって異なります。`

ということで… 「暗号化に使用した暗号化方式を知るには、正しいパスワードを使って解読に成功する他ない」ということのようです。

更に検索して、pfx ファイルのダンプ方法を見つけました。この出力を見て裏付けが取れました。

```bat
openssl.exe asn1parse -inform der -in CodeSign.pfx -i -dump
```

ダンプの一部

```text
    0:d=0  hl=4 l=6854 cons: SEQUENCE          
    4:d=1  hl=2 l=   1 prim:  INTEGER           :03
    7:d=1  hl=4 l=6770 cons:  SEQUENCE          
   11:d=2  hl=2 l=   9 prim:   OBJECT            :pkcs7-data
   22:d=2  hl=4 l=6755 cons:   cont [ 0 ]        
   26:d=3  hl=4 l=6751 prim:    OCTET STRING      
      0000 - 30 82 1a 5b 30 82 06 51-06 09 2a 86 48 86 f7 0d   0..[0..Q..*.H...
...
      1a50 - d2 3a 16 7c 9d d2 5f 01-09 16 4a d0 d0 ad 82      .:.|.._...J....
 6781:d=1  hl=2 l=  75 cons:  SEQUENCE          
 6783:d=2  hl=2 l=  47 cons:   SEQUENCE          
 6785:d=3  hl=2 l=  11 cons:    SEQUENCE          
 6787:d=4  hl=2 l=   9 prim:     OBJECT            :sha256
 6798:d=3  hl=2 l=  32 prim:    OCTET STRING      
      0000 - 24 51 85 f0 cf 5b 86 af-75 0d 27 b8 c7 f9 55 48   $Q...[..u.'...UH
      0010 - 11 b5 52 00 a2 34 17 e3-39 25 1c f8 ea 02 4c 97   ..R..4..9%....L.
 6832:d=2  hl=2 l=  20 prim:   OCTET STRING      
      0000 - 92 bd 0f 1a a9 ef 70 f6-84 72 68 8c 0f 73 40 6f   ......p..rh..s@o
      0010 - 1f 2e bb d1                                       ....
 6854:d=2  hl=2 l=   2 prim:   INTEGER           :07D0
```

`:pkcs7-data` の中身と思われる `OCTET STRING` がダンプになっているので…
何らかの暗号化が施されているものと考えられます。

ダンプの後方に `:sha256` という文言が見つかりました。
これが、暗号化の指定に関係あるのかどうか検証してみます。

`AES256-SHA256` で暗号化した場合

```text
...
 6811:d=1  hl=2 l=  75 cons:  SEQUENCE
 6813:d=2  hl=2 l=  47 cons:   SEQUENCE
 6815:d=3  hl=2 l=  11 cons:    SEQUENCE
 6817:d=4  hl=2 l=   9 prim:     OBJECT            :sha256
 6828:d=3  hl=2 l=  32 prim:    OCTET STRING
      0000 - 99 5e 94 b6 fc c0 09 dd-b1 cb 03 c6 50 64 68 8d   .^..........Pdh.
      0010 - d9 8e c0 0e 5f 0c 3e 98-83 a5 59 18 1d f2 3b 1b   ...._.>...Y...;.
 6862:d=2  hl=2 l=  20 prim:   OCTET STRING
      0000 - da 13 a3 70 f3 2b e1 fc-cb 2c d5 a7 08 4f 6e e7   ...p.+...,...On.
      0010 - b7 10 98 bf                                       ....
 6884:d=2  hl=2 l=   2 prim:   INTEGER           :07D0
```

`TripleDES-SHA1` で暗号化した場合

```text
...
 6677:d=1  hl=2 l=  59 cons:  SEQUENCE
 6679:d=2  hl=2 l=  31 cons:   SEQUENCE
 6681:d=3  hl=2 l=   7 cons:    SEQUENCE
 6683:d=4  hl=2 l=   5 prim:     OBJECT            :sha1
 6690:d=3  hl=2 l=  20 prim:    OCTET STRING
      0000 - 33 71 f9 6e e5 1e 56 d7-7e d8 6e b4 6d 62 ea 07   3q.n..V.~.n.mb..
      0010 - 45 ad 4f 56                                       E.OV
 6712:d=2  hl=2 l=  20 prim:   OCTET STRING
      0000 - 57 f7 83 26 ac f4 f0 a4-29 a9 7e 6b 79 8c b1 e8   W..&....).~ky...
      0010 - 97 ce c2 17                                       ....
 6734:d=2  hl=2 l=   2 prim:   INTEGER           :07D0
```

結果、関係ありました：

- `:sha1` が含まれる場合、`TripleDES-SHA1` で暗号化した可能性があります
- `:sha256` が含まれる場合、`AES256-SHA256` で暗号化した可能性があります

という訳で、証明書のインポートエラー `The specified network password is not correct` は…

- インポート時のパスワードが正しくても発生し得ます。
  - 「どの暗号化方式を使用して暗号化したか」の情報は pfx ファイルに記載がないということ。
  - Windows のバージョンが古い場合、`AES256-SHA256` で暗号化された pfx ファイルを解読できないのかもしれません。
- その pfx ファイルが `AES256-SHA256` で暗号化しているかどうかは、
  - `openssl.exe asn1parse -inform der -in CodeSign.pfx -i -dump` コマンドの出力に `:sha256` という文言が含まれているかどうかで推測が可能。

という事が分かりました。