pkilintとは
pkilintは、DigiCertが2023年5月に開発したASN.1を使用してエンコードされたドキュメントのリンティングフレームワーク。
pkilintはASN.1構造、「ドキュメント」タイプのリンターを素早く作成し、準拠状況やPolicyを確認するための非常に拡張可能なツールボックスである。
認証局の自己監査や外部監査でも利用できると思われる。
インストール方法
Linux環境が必要で、Python 3.9以降がインストールされている必要がある。
ここでは、Rocky Linux v.8.9を使用する。
[root@localhost ~]# cat /etc/redhat-release
Rocky Linux release 8.9 (Green Obsidian)
[root@localhost ~]# python3 --version
Python 3.6.8
[root@localhost bin]# dnf install python39
メタデータの期限切れの最終確認: 1:42:00 前の 2024年xx月xx日 xx時xx分xx秒 に実施しました。
依存関係が解決しました。
================================================================================
パッケージ Arch バージョン Repo サイズ
================================================================================
インストール:
python39 x86_64 3.9.18-1.module+el8.9.0+1581+c29ce980 appstream 33 k
依存関係のインストール:
python39-libs x86_64 3.9.18-1.module+el8.9.0+1581+c29ce980 appstream 8.2 M
python39-pip-wheel
noarch 20.2.4-8.module+el8.9.0+1581+c29ce980 appstream 1.1 M
python39-setuptools-wheel
noarch 50.3.2-5.module+el8.9.0+1581+c29ce980 appstream 496 k
弱い依存関係のインストール:
python39-pip noarch 20.2.4-8.module+el8.9.0+1581+c29ce980 appstream 1.9 M
python39-setuptools
noarch 50.3.2-5.module+el8.9.0+1581+c29ce980 appstream 870 k
モジュールストリームの有効化中:
python39 3.9
トランザクションの概要
================================================================================
インストール 6 パッケージ
ダウンロードサイズの合計: 12 M
インストール後のサイズ: 45 M
これでよろしいですか? [y/N]: y
パッケージのダウンロード:
(1/6): python39-3.9.18-1.module+el8.9.0+1581+c2 334 kB/s | 33 kB 00:00
(2/6): python39-pip-wheel-20.2.4-8.module+el8.9 2.9 MB/s | 1.1 MB 00:00
(3/6): python39-setuptools-50.3.2-5.module+el8. 2.5 MB/s | 870 kB 00:00
(4/6): python39-pip-20.2.4-8.module+el8.9.0+158 2.1 MB/s | 1.9 MB 00:00
(5/6): python39-setuptools-wheel-50.3.2-5.modul 3.0 MB/s | 496 kB 00:00
(6/6): python39-libs-3.9.18-1.module+el8.9.0+15 5.8 MB/s | 8.2 MB 00:01
--------------------------------------------------------------------------------
合計 5.8 MB/s | 12 MB 00:02
トランザクションの確認を実行中
トランザクションの確認に成功しました。
トランザクションのテストを実行中
トランザクションのテストに成功しました。
トランザクションを実行中
準備 : 1/1
インストール中 : python39-setuptools-wheel-50.3.2-5.module+el8.9.0+15 1/6
インストール中 : python39-pip-wheel-20.2.4-8.module+el8.9.0+1581+c29c 2/6
インストール中 : python39-libs-3.9.18-1.module+el8.9.0+1581+c29ce980. 3/6
インストール中 : python39-3.9.18-1.module+el8.9.0+1581+c29ce980.x86_6 4/6
scriptletの実行中: python39-3.9.18-1.module+el8.9.0+1581+c29ce980.x86_6 4/6
インストール中 : python39-setuptools-50.3.2-5.module+el8.9.0+1581+c29 5/6
scriptletの実行中: python39-setuptools-50.3.2-5.module+el8.9.0+1581+c29 5/6
インストール中 : python39-pip-20.2.4-8.module+el8.9.0+1581+c29ce980.n 6/6
scriptletの実行中: python39-pip-20.2.4-8.module+el8.9.0+1581+c29ce980.n 6/6
検証 : python39-3.9.18-1.module+el8.9.0+1581+c29ce980.x86_6 1/6
検証 : python39-libs-3.9.18-1.module+el8.9.0+1581+c29ce980. 2/6
検証 : python39-pip-20.2.4-8.module+el8.9.0+1581+c29ce980.n 3/6
検証 : python39-pip-wheel-20.2.4-8.module+el8.9.0+1581+c29c 4/6
検証 : python39-setuptools-50.3.2-5.module+el8.9.0+1581+c29 5/6
検証 : python39-setuptools-wheel-50.3.2-5.module+el8.9.0+15 6/6
インストール済み:
python39-3.9.18-1.module+el8.9.0+1581+c29ce980.x86_64
python39-libs-3.9.18-1.module+el8.9.0+1581+c29ce980.x86_64
python39-pip-20.2.4-8.module+el8.9.0+1581+c29ce980.noarch
python39-pip-wheel-20.2.4-8.module+el8.9.0+1581+c29ce980.noarch
python39-setuptools-50.3.2-5.module+el8.9.0+1581+c29ce980.noarch
python39-setuptools-wheel-50.3.2-5.module+el8.9.0+1581+c29ce980.noarch
完了しました!
[root@localhost bin]# dnf module enable python39
メタデータの期限切れの最終確認: 1:42:43 前の 2024年xx月xx日 xx時xx分xx秒 に実施しました。
依存関係が解決しました。
行うべきことはありません。
完了しました!
[root@localhost bin]# dnf module list | grep python
libselinux-python 2.8 common Python 2 bindings for libselinux
python27 2.7 [d] common [d] Python programming language, version 2.7
python36 3.6 [d][e] build, common [d] Python programming language, version 3.6
python38 3.8 [d] build, common [d] Python programming language, version 3.8
python39 3.9 [d][e] build, common [d] Python programming language, version 3.9
[root@localhost bin]# dnf module enable python39
メタデータの期限切れの最終確認: 1:45:15 前の 2024年xx月xx日 xx時xx分xx秒 に実施しました。
依存関係が解決しました。
行うべきことはありません。
完了しました!
[root@localhost bin]# dnf module list | grep python
libselinux-python 2.8 common Python 2 bindings for libselinux
python27 2.7 [d] common [d] Python programming language, version 2.7
python36 3.6 [d][e] build, common [d] Python programming language, version 3.6
python38 3.8 [d] build, common [d] Python programming language, version 3.8
python39 3.9 [d][e] build, common [d] Python programming language, version 3.9
[root@localhost bin]# alternatives --list | grep python
python auto /usr/libexec/no-python
python3 auto /usr/bin/python3.6
[root@localhost bin]# alternatives --display python3
python3 -ステータスは自動です。
リンクは現在 /usr/bin/python3.6 を指しています。
/usr/bin/python3.6 - 優先度 1000000
スレーブ easy_install-3: /usr/bin/easy_install-3.6
スレーブ pip-3: /usr/bin/pip-3.6
スレーブ pip3: /usr/bin/pip3.6
スレーブ pydoc-3: /usr/bin/pydoc3.6
スレーブ pydoc3: /usr/bin/pydoc3.6
スレーブ pyvenv-3: /usr/bin/pyvenv-3.6
スレーブ python3-man: /usr/share/man/man1/python3.6.1.gz
/usr/bin/python3.11 - 優先度 31100
スレーブ easy_install-3: (null)
スレーブ pip-3: (null)
スレーブ pip3: (null)
スレーブ pydoc-3: /usr/bin/pydoc3.11
スレーブ pydoc3: /usr/bin/pydoc3.11
スレーブ pyvenv-3: (null)
スレーブ python3-man: /usr/share/man/man1/python3.11.1.gz
/usr/bin/python3.9 - 優先度 3900
スレーブ easy_install-3: /usr/bin/easy_install-3.9
スレーブ pip-3: /usr/bin/pip-3.9
スレーブ pip3: /usr/bin/pip3.9
スレーブ pydoc-3: /usr/bin/pydoc3.9
スレーブ pydoc3: /usr/bin/pydoc3.9
スレーブ pyvenv-3: (null)
スレーブ python3-man: /usr/share/man/man1/python3.9.1.gz
現在の「最適」バージョンは /usr/bin/python3.6 です。
[root@localhost bin]# alternatives --set python3 /usr/bin/python3.9
[root@localhost bin]# alternatives --list | grep python
python auto /usr/libexec/no-python
python3 manual /usr/bin/python3.9
[root@localhost bin]# python3 --version
Python 3.9.18
pkilint のパッケージの依存関係がマシンにグローバルにインストールされているパッケージと競合しないようにするには、pipx を使用して pkilint 用に別の Python 環境を作成するのが良い。
pipx ホームページの指示に従って pipx をインストールする。
[root@localhost ~]# python3 -m pip install --user pipx
WARNING: Running pip install with root privileges is generally not a good idea. Try `python3 -m pip install --user` instead.
Collecting pipx
Downloading pipx-1.4.3-py3-none-any.whl (65 kB)
|████████████████████████████████| 65 kB 3.3 MB/s
Collecting userpath!=1.9.0,>=1.6
Downloading userpath-1.9.2-py3-none-any.whl (9.1 kB)
Collecting packaging>=20
Downloading packaging-24.0-py3-none-any.whl (53 kB)
|████████████████████████████████| 53 kB 4.4 MB/s
Collecting tomli; python_version < "3.11"
Downloading tomli-2.0.1-py3-none-any.whl (12 kB)
Collecting argcomplete>=1.9.4
Downloading argcomplete-3.2.3-py3-none-any.whl (42 kB)
|████████████████████████████████| 42 kB 2.6 MB/s
Collecting platformdirs>=2.1
Downloading platformdirs-4.2.0-py3-none-any.whl (17 kB)
Collecting click
Downloading click-8.1.7-py3-none-any.whl (97 kB)
|████████████████████████████████| 97 kB 5.9 MB/s
Installing collected packages: click, userpath, packaging, tomli, argcomplete, platformdirs, pipx
WARNING: The script userpath is installed in '/root/.local/bin' which is not on PATH.
Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
WARNING: The script pipx is installed in '/root/.local/bin' which is not on PATH.
Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed argcomplete-3.2.3 click-8.1.7 packaging-24.0 pipx-1.4.3 platformdirs-4.2.0 tomli-2.0.1 userpath-1.9.2
[root@localhost ~]# python3 -m pipx ensurepath
Success! Added /root/.local/bin to the PATH environment variable.
Consider adding shell completions for pipx. Run 'pipx completions' for
instructions.
You will need to open a new terminal or re-login for the PATH changes to take
effect.
Otherwise pipx is ready to go! ✨ 🌟 ✨
一度、端末(Terminal)画面を閉じ、新しく開く。これを行わないと、pipxが認識されない。
[root@localhost ~]# pipx install pkilint
installed package pkilint 0.9.10, installed using Python 3.9.18
These apps are now globally available
- lint_cabf_serverauth_cert
- lint_cabf_smime_cert
- lint_crl
- lint_ocsp_response
- lint_pkix_cert
- lint_pkix_signer_signee_cert_chain
done! ✨ 🌟 ✨
インストールが完了すると、バンドルされたコマンドラインアプリケーションとPython APIがマシンで使用できるようになる。
アップグレード
pipx upgrade pkilint
利用方法
S/MIME証明書 検査でERRORなしの場合
[root@localhost ドキュメント]# lint_cabf_smime_cert lint -d smime.cer
CertificatePolicyQualifierValidator @ certificate.tbsCertificate.extensions.3.extnValue.certificatePolicies.1
pkix.certificate_policies_policy_has_qualifier (NOTICE)
SubjectKeyIdentifierValidator @ certificate.tbsCertificate.extensions.6.extnValue.subjectKeyIdentifier
pkix.subject_key_identifier_method_1_identified (INFO)
S/MIME証明書 検査でERRORありの場合
(TLSサーバー証明書を読み込んでErrorを出現)
[root@localhost ドキュメント]# lint_cabf_smime_cert lint -d google.co.jp.crt
CommonNameValidator @ certificate.tbsCertificate.subject.rdnSequence.0.0.value.x520CommonName
cabf.smime.common_name_value_unknown_source (ERROR): Unknown CN value source: "*.google.co.jp"
AllowedExtendedKeyUsageValidator @ certificate.tbsCertificate.extensions.1.extnValue.extKeyUsageSyntax
cabf.smime.emailprotection_eku_missing (ERROR)
cabf.smime.prohibited_eku_present (ERROR): Prohibited EKU(s) present: 1.3.6.1.5.5.7.3.1
SubjectKeyIdentifierValidator @ certificate.tbsCertificate.extensions.3.extnValue.subjectKeyIdentifier
pkix.subject_key_identifier_method_1_identified (INFO)
SubjectAlternativeNameContainsEmailAddressValidator @ certificate.tbsCertificate.extensions.6.extnValue.subjectAltName
cabf.smime.san_does_not_contain_email_address (ERROR)
SubjectAlternativeNameProhibitedGeneralNameTypesValidator @ certificate.tbsCertificate.extensions.6.extnValue.subjectAltName
cabf.smime.prohibited_generalname_type_present (ERROR): Prohibited GeneralName type(s) present: dNSName
GeneralNameDnsNameSyntaxValidator @ certificate.tbsCertificate.extensions.6.extnValue.subjectAltName.0.dNSName
pkix.invalid_domain_name_syntax (ERROR): Invalid domain name syntax: "*.google.co.jp"
RequiredPolicyIdentifierValidator @ certificate.tbsCertificate.extensions.7.extnValue.certificatePolicies
cabf.smime.no_required_reserved_policy_oid (ERROR): Required policy OID 2.23.140.1.5.1.3 is missing
TLSサーバー証明書 検査でERRORなしの場合
[root@localhost ドキュメント]# lint_cabf_serverauth_cert lint -d google.co.jp.crt
DvSubcriberAttributeAllowanceValidator @ certificate.tbsCertificate.subject.rdnSequence
cabf.serverauth.dv.common_name_attribute_present (WARNING)
SubjectKeyIdentifierValidator @ certificate.tbsCertificate.extensions.3.extnValue.subjectKeyIdentifier
pkix.subject_key_identifier_method_1_identified (INFO)
SubscriberExtensionAllowanceValidator @ certificate.tbsCertificate.extensions
cabf.serverauth.subscriber.subject_key_identifier_extension_present (WARNING)
上記検査で使用したTLSサーバー証明書は以下のコマンドでダウンロード。(3階層の証明書ファイルとしてダウンロードされるので、TLSサーバー証明書の部分を抜き出す必要がある)
[root@localhost ドキュメント]# openssl s_client -connect www.google.co.jp:443 -showcerts -servername www.google.co.jp >/root/ドキュメント/www.google.co.jp.cer
depth=2 C = US, O = Google Trust Services LLC, CN = GTS Root R1
verify return:1
depth=1 C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
verify return:1
depth=0 CN = *.google.co.jp
verify return:1
read:errno=0
証明書の内容表示。
[root@localhost ドキュメント]# openssl x509 -text -in google.co.jp.crt
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
d0:f4:fa:14:49:5d:db:f7:12:fc:1c:75:ba:fa:22:e8
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = US, O = Google Trust Services LLC, CN = GTS CA 1C3
Validity
Not Before: Feb 19 08:21:08 2024 GMT
Not After : May 13 08:21:07 2024 GMT
Subject: CN = *.google.co.jp
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:d4:4a:3b:fa:e1:76:f9:72:37:db:6b:09:17:a2:
01:7a:22:a1:21:09:92:5d:4f:92:fa:eb:0e:b8:6e:
50:a8:b5:bb:b2:de:22:ce:55:e3:c3:98:e5:dd:55:
7a:f8:bc:c6:2f:f3:c0:24:ed:dd:38:88:56:ce:55:
c0:c4:65:3e:db
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Key Identifier:
43:C2:96:90:4E:0C:16:71:89:86:D1:C0:55:1C:E4:95:A1:D5:97:76
X509v3 Authority Key Identifier:
keyid:8A:74:7F:AF:85:CD:EE:95:CD:3D:9C:D0:E2:46:14:F3:71:35:1D:27
Authority Information Access:
OCSP - URI:http://ocsp.pki.goog/gts1c3
CA Issuers - URI:http://pki.goog/repo/certs/gts1c3.der
X509v3 Subject Alternative Name:
DNS:*.google.co.jp, DNS:google.co.jp
X509v3 Certificate Policies:
Policy: 2.23.140.1.2.1
Policy: 1.3.6.1.4.1.11129.2.5.3
X509v3 CRL Distribution Points:
Full Name:
URI:http://crls.pki.goog/gts1c3/QqFxbi9M48c.crl
CT Precertificate SCTs:
Signed Certificate Timestamp:
Version : v1 (0x0)
Log ID : 76:FF:88:3F:0A:B6:FB:95:51:C2:61:CC:F5:87:BA:34:
B4:A4:CD:BB:29:DC:68:42:0A:9F:E6:67:4C:5A:3A:74
Timestamp : Feb 19 09:21:09.417 2024 GMT
Extensions: none
Signature : ecdsa-with-SHA256
30:45:02:21:00:A4:62:D4:A4:DA:2D:16:2A:55:4E:3B:
59:FC:61:68:09:E6:03:0C:90:74:13:FA:FE:7A:13:F4:
90:4A:16:31:32:02:20:32:AC:11:8F:69:07:D9:37:DD:
B4:2C:25:05:EB:41:37:5A:F4:C3:78:51:96:BF:FD:30:
38:1D:31:95:97:36:AC
Signed Certificate Timestamp:
Version : v1 (0x0)
Log ID : A2:E2:BF:D6:1E:DE:2F:2F:07:A0:D6:4E:6D:37:A7:DC:
65:43:B0:C6:B5:2E:A2:DA:B7:8A:F8:9A:6D:F5:17:D8
Timestamp : Feb 19 09:21:09.399 2024 GMT
Extensions: none
Signature : ecdsa-with-SHA256
30:45:02:20:2C:5B:F7:CC:33:E7:18:C4:1D:6A:29:FD:
82:91:F5:44:0C:15:76:42:9A:E2:62:68:F3:0D:DB:FB:
98:67:26:3B:02:21:00:CC:9F:05:96:54:71:F5:A9:85:
24:48:39:91:5F:E4:B8:82:66:20:7D:D0:76:39:55:89:
FD:BD:9B:DD:C1:42:DE
Signature Algorithm: sha256WithRSAEncryption
d1:60:a7:10:a2:6a:d7:5f:a3:7b:10:54:e3:9b:a6:fa:c4:b7:
91:0e:1d:46:04:f1:80:53:16:00:c4:41:82:c8:ba:37:cf:5b:
9b:c0:94:15:88:ae:fc:1e:4b:0a:10:95:f2:a5:14:4a:5b:c8:
37:9e:6d:96:b0:16:7f:02:cf:3f:23:91:0a:2f:03:3b:a8:4c:
66:03:84:f5:e2:6b:26:38:68:01:97:5c:b6:ff:99:9c:8c:89:
04:e2:f9:1e:71:9b:c6:e7:28:31:ba:f3:2f:40:70:b3:37:a5:
1f:f1:c6:26:a6:a3:a5:7b:43:b8:a4:d5:8b:af:59:be:b9:b8:
60:a2:93:0d:0e:de:4e:84:c6:49:68:32:8c:10:4e:c7:97:89:
2a:5d:ef:67:a2:a9:0d:0f:98:6f:ba:58:53:cb:28:f0:85:c3:
d4:cd:04:94:7a:cb:e2:ca:94:ce:ba:df:36:e3:b9:e2:0d:e5:
e5:7b:e1:65:bd:15:e2:d4:f9:7b:b3:12:3d:dc:5e:74:16:86:
0b:0b:4c:a7:e1:78:82:97:d5:bb:91:55:90:09:2c:ca:7e:62:
7d:28:77:d4:cc:60:a0:c0:6a:e3:d7:ae:28:1e:6c:78:c5:c9:
7b:d0:50:2a:32:0f:08:53:50:d9:5f:73:64:c4:62:86:82:36:
ea:10:4b:67
-----BEGIN CERTIFICATE-----
MIIEljCCA36gAwIBAgIRAND0+hRJXdv3Evwcdbr6IugwDQYJKoZIhvcNAQELBQAw
RjELMAkGA1UEBhMCVVMxIjAgBgNVBAoTGUdvb2dsZSBUcnVzdCBTZXJ2aWNlcyBM
TEMxEzARBgNVBAMTCkdUUyBDQSAxQzMwHhcNMjQwMjE5MDgyMTA4WhcNMjQwNTEz
MDgyMTA3WjAZMRcwFQYDVQQDDA4qLmdvb2dsZS5jby5qcDBZMBMGByqGSM49AgEG
CCqGSM49AwEHA0IABNRKO/rhdvlyN9trCReiAXoioSEJkl1PkvrrDrhuUKi1u7Le
Is5V48OY5d1Vevi8xi/zwCTt3TiIVs5VwMRlPtujggJ1MIICcTAOBgNVHQ8BAf8E
BAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4E
FgQUQ8KWkE4MFnGJhtHAVRzklaHVl3YwHwYDVR0jBBgwFoAUinR/r4XN7pXNPZzQ
4kYU83E1HScwagYIKwYBBQUHAQEEXjBcMCcGCCsGAQUFBzABhhtodHRwOi8vb2Nz
cC5wa2kuZ29vZy9ndHMxYzMwMQYIKwYBBQUHMAKGJWh0dHA6Ly9wa2kuZ29vZy9y
ZXBvL2NlcnRzL2d0czFjMy5kZXIwJwYDVR0RBCAwHoIOKi5nb29nbGUuY28uanCC
DGdvb2dsZS5jby5qcDAhBgNVHSAEGjAYMAgGBmeBDAECATAMBgorBgEEAdZ5AgUD
MDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmxzLnBraS5nb29nL2d0czFjMy9R
cUZ4Ymk5TTQ4Yy5jcmwwggEEBgorBgEEAdZ5AgQCBIH1BIHyAPAAdgB2/4g/Crb7
lVHCYcz1h7o0tKTNuyncaEIKn+ZnTFo6dAAAAY3Aq1EpAAAEAwBHMEUCIQCkYtSk
2i0WKlVOO1n8YWgJ5gMMkHQT+v56E/SQShYxMgIgMqwRj2kH2TfdtCwlBetBN1r0
w3hRlr/9MDgdMZWXNqwAdgCi4r/WHt4vLweg1k5tN6fcZUOwxrUuotq3iviabfUX
2AAAAY3Aq1EXAAAEAwBHMEUCICxb98wz5xjEHWop/YKR9UQMFXZCmuJiaPMN2/uY
ZyY7AiEAzJ8FllRx9amFJEg5kV/kuIJmIH3QdjlVif29m93BQt4wDQYJKoZIhvcN
AQELBQADggEBANFgpxCiatdfo3sQVOObpvrEt5EOHUYE8YBTFgDEQYLIujfPW5vA
lBWIrvweSwoQlfKlFEpbyDeebZawFn8Czz8jkQovAzuoTGYDhPXiayY4aAGXXLb/
mZyMiQTi+R5xm8bnKDG68y9AcLM3pR/xxiamo6V7Q7ik1YuvWb65uGCikw0O3k6E
xkloMowQTseXiSpd72eiqQ0PmG+6WFPLKPCFw9TNBJR6y+LKlM663zbjueIN5eV7
4WW9FeLU+XuzEj3cXnQWhgsLTKfheIKX1buRVZAJLMp+Yn0od9TMYKDAauPXrige
bHjFyXvQUCoyDwhTUNlfc2TEYoaCNuoQS2c=
-----END CERTIFICATE-----
TLSサーバー証明書 検査でERRORありの場合
(S/MIME証明書を読み込んでErrorを出現)
[root@localhost ドキュメント]# lint_cabf_serverauth_cert lint -d smime.cer
SubscriberValidityPeriodValidator @ certificate.tbsCertificate.validity.notBefore
cabf.certificate_validity_period_exceeds_398_days (ERROR): Validity period of 761 days, 0:00:01 exceeds maximum value of 398 days, 0:00:00
DvSubcriberAttributeAllowanceValidator @ certificate.tbsCertificate.subject.rdnSequence
cabf.serverauth.dv.common_name_attribute_present (WARNING)
SubscriberCommonNameValidator @ certificate.tbsCertificate.subject.rdnSequence.0.0.value.x520CommonName
cabf.serverauth.subscriber_common_name_unknown_source (ERROR): Unknown source for value of common name: "xxxx@xxxxx.co.jp"
SubscriberSanGeneralNameTypeValidator @ certificate.tbsCertificate.extensions.2.extnValue.subjectAltName.0
cabf.serverauth.prohibited_san_type (ERROR): Prohibited SAN GeneralName type: rfc822Name
SubscriberPoliciesValidator @ certificate.tbsCertificate.extensions.3.extnValue.certificatePolicies
cabf.serverauth.subscriber_missing_reserved_policy_oid (ERROR): Required policy OID "2.23.140.1.2.1" missing
CertificatePolicyQualifierValidator @ certificate.tbsCertificate.extensions.3.extnValue.certificatePolicies.1.policyQualifiers.0
cabf.serverauth.certificate_policy_qualifier_present (WARNING)
SubscriberEkuAllowanceValidator @ certificate.tbsCertificate.extensions.4.extnValue.extKeyUsageSyntax
cabf.serverauth.subscriber.emailprotection_eku_present (ERROR)
cabf.serverauth.subscriber.serverauth_eku_absent (ERROR)
SubjectKeyIdentifierValidator @ certificate.tbsCertificate.extensions.6.extnValue.subjectKeyIdentifier
pkix.subject_key_identifier_method_1_identified (INFO)
SubscriberKeyUsageValidator @ certificate.tbsCertificate.extensions.7.extnValue.keyUsage
cabf.serverauth.subscriber_rsa_digitalsignature_and_keyencipherment_present (WARNING)
SubscriberExtensionAllowanceValidator @ certificate.tbsCertificate.extensions
cabf.serverauth.subscriber.subject_key_identifier_extension_present (WARNING)
CRL 検査でERRORなしの場合
(DER形式でも、PEM形式でも検査可能)
[root@localhost ドキュメント]# lint_crl lint -t CRL -p BR -s ALL -f TEXT google-pem.crl
crt.sh IDから検査
TLSサーバー証明書証明書
crt.sh IDを指定してpkilintを実行できる。
curl -s [https://crt.sh/?d=crt.sh ID] | lint_cabf_serverauth_cert lint -d - -s ERROR
(Example)
curl -s https://crt.sh/?d=12428602531 | lint_cabf_serverauth_cert lint -d - -s ERROR
(Example)
curl -s https://crt.sh/?d=12428602531 | lint_cabf_serverauth_cert lint -d - -s INFO
help画面
S/MIME証明書
[root@localhost ドキュメント]# lint_cabf_smime_cert lint -h
usage: lint_cabf_smime_cert lint [-h]
(-d | -g | -t {MAILBOX-LEGACY,ORGANIZATION-LEGACY,SPONSORED-LEGACY,INDIVIDUAL-LEGACY,MAILBOX-MULTIPURPOSE,ORGANIZATION-MULTIPURPOSE,SPONSORED-MULTIPURPOSE,INDIVIDUAL-MULTIPURPOSE,MAILBOX-STRICT,ORGANIZATION-STRICT,SPONSORED-STRICT,INDIVIDUAL-STRICT})
[-m MAPPING] [-o] [-s {FATAL,ERROR,WARNING,NOTICE,INFO,DEBUG,ALL}] [-f {TEXT,CSV,JSON}]
file
positional arguments:
file The certificate to lint
optional arguments:
-h, --help show this help message and exit
-d, --detect Detect the type of S/MIME certificate from reserved CA/B Forum policy OID. If the type cannot be detected,
then refuse to lint the certificate.
-g, --guess Detect the type of S/MIME certificate from reserved CA/B Forum policy OID. If the type cannot be detected,
then use heuristics to determine the type of S/MIME certificate.
-t {MAILBOX-LEGACY,ORGANIZATION-LEGACY,SPONSORED-LEGACY,INDIVIDUAL-LEGACY,MAILBOX-MULTIPURPOSE,ORGANIZATION-MULTIPURPOSE,SPONSORED-MULTIPURPOSE,INDIVIDUAL-MULTIPURPOSE,MAILBOX-STRICT,ORGANIZATION-STRICT,SPONSORED-STRICT,INDIVIDUAL-STRICT}, --type {MAILBOX-LEGACY,ORGANIZATION-LEGACY,SPONSORED-LEGACY,INDIVIDUAL-LEGACY,MAILBOX-MULTIPURPOSE,ORGANIZATION-MULTIPURPOSE,SPONSORED-MULTIPURPOSE,INDIVIDUAL-MULTIPURPOSE,MAILBOX-STRICT,ORGANIZATION-STRICT,SPONSORED-STRICT,INDIVIDUAL-STRICT}
The type (validation level and generation) of S/MIME certificate
-m MAPPING, --mapping MAPPING
Mapping file which contains OID to validation level and generation mappings. Each line of the mapping file
starts with a policy OID followed by a non-numeric character and the certificate type to which the OID maps
(see -t/--type option for possible values)
-o, --output Output the type of S/MIME certificate to standard error. This option may be useful when using the --detect,
--guess, or --mapping options.
-s {FATAL,ERROR,WARNING,NOTICE,INFO,DEBUG,ALL}, --severity {FATAL,ERROR,WARNING,NOTICE,INFO,DEBUG,ALL}
The finding severity threshold; findings with a lesser severity will not be reported.
-f {TEXT,CSV,JSON}, --format {TEXT,CSV,JSON}
The format in which results will be output.
TLSサーバー証明書
[root@localhost ~]# lint_cabf_serverauth_cert lint -s -h?
usage: lint_cabf_serverauth_cert lint [-h]
(-d | -t {ROOT-CA,INTERNAL-CROSS-CA,EXTERNAL-CROSS-CA,NON-TLS-CA,PRECERT-SIGNING-CA,INTERNAL-UNCONSTRAINED-TLS-CA,INTERNAL-CONSTRAINED-TLS-CA,EXTERNAL-UNCONSTRAINED-TLS-CA,EXTERNAL-UNCONSTRAINED-EV-TLS-CA,EXTERNAL-CONSTRAINED-TLS-CA,EXTERNAL-CONSTRAINED-EV-TLS-CA,DV-FINAL-CERTIFICATE,IV-FINAL-CERTIFICATE,OV-FINAL-CERTIFICATE,EV-FINAL-CERTIFICATE,OCSP-RESPONDER,DV-PRE-CERTIFICATE,IV-PRE-CERTIFICATE,OV-PRE-CERTIFICATE,EV-PRE-CERTIFICATE})
[-o] [-r]
[-s {FATAL,ERROR,WARNING,NOTICE,INFO,DEBUG,ALL}]
[-f {TEXT,CSV,JSON}]
file
lint_cabf_serverauth_cert lint: error: argument -s/--severity: expected one argument
CRL
[root@localhost ドキュメント]# lint_crl lint -h
usage: lint_crl lint [-h] -t {CRL,ARL} -p {PKIX,BR} [-s {FATAL,ERROR,WARNING,NOTICE,INFO,DEBUG,ALL}] [-f {TEXT,CSV,JSON}] file
positional arguments:
file The CRL file to lint
optional arguments:
-h, --help show this help message and exit
-t {CRL,ARL}, --type {CRL,ARL}
The type of CRL (whether the CRL in question is a CRL or an ARL)
-p {PKIX,BR}, --profile {PKIX,BR}
The profile against which to lint
-s {FATAL,ERROR,WARNING,NOTICE,INFO,DEBUG,ALL}, --severity {FATAL,ERROR,WARNING,NOTICE,INFO,DEBUG,ALL}
The finding severity threshold; findings with a lesser severity will not be reported.
-f {TEXT,CSV,JSON}, --format {TEXT,CSV,JSON}
The format in which results will be output.
Scriptファイルの作成例
指定フォルダー内にある証明書について全件検査する方法。
S/MIME証明書(smime.sh)
審査対象ファイルを入れるフォルダー:/root/ドキュメント/smime
#!/bin/bash
folder_path=/root/ドキュメント/smime
output_file="PKILINT_SMIME_"
start_date=$(date +'%Y%m%d-%H%M%S')
output_file+=$start_date
output_file+=".txt"
> $output_file
echo "START $start_date"
echo "START $start_date" >> $output_file
i_count=0
i_error=0
i_ok=0
for file in "$folder_path"/*; do
((i_count++))
if [ -f "$file" ]; then
program_output=$(lint_cabf_smime_cert lint -d "$file")
if [[ "$program_output" == *"ERROR"* ]]; then
echo "ERROR " "(" "$i_count" ")" "$file"
echo "ERROR " "(" "$i_count" ")" "$file" >> $output_file
echo $program_output >> $output_file
((i_error++))
elif [[ "$program_output" == *"FATAL"* ]]; then
echo "FATAL " "(" "$i_count" ")" "$file"
echo "FATAL " "(" "$i_count" ")" "$file" >> $output_file
echo $program_output >> $output_file
((i_error++))
elif [[ "$program_output" == "" ]]; then
echo "NO OUTPUT " "(" "$i_count" ")" "$file"
echo "NO OUTPUT " "(" "$i_count" ")" "$file" >> $output_file
echo $program_output >> $output_file
((i_error++))
else
echo "OK " "(" "$i_count" ")" "$file"
#To display output, remove the # below
#echo "OK " "(" "$i_count" ")" "$file" >> $output_file
#echo $program_output
#echo $program_output >> $output_file
((i_ok++))
fi
fi
done
echo "All:$i_count"
echo "All:$i_count" >> $output_file
echo "OK:$i_ok"
echo "OK:$i_ok" >> $output_file
echo "ERROR:$i_error"
echo "ERROR:$i_error" >> $output_file
end_date=$(date +'%Y%m%d-%H%M%S')
echo "END $end_date"
echo "END $end_date" >> $output_file
echo "$output_file"
TLSサーバー証明書(serverauth.sh)
審査対象ファイルを入れるフォルダー:/root/ドキュメント/serverauth
#!/bin/bash
folder_path=/root/ドキュメント/serverauth
output_file="PKILINT_SERVERAUTH_"
start_date=$(date +'%Y%m%d-%H%M%S')
output_file+=$start_date
output_file+=".txt"
> $output_file
echo "START $start_date"
echo "START $start_date" >> $output_file
i_count=0
i_error=0
i_ok=0
for file in "$folder_path"/*; do
((i_count++))
if [ -f "$file" ]; then
program_output=$(lint_cabf_serverauth_cert lint -d "$file")
if [[ "$program_output" == *"ERROR"* ]]; then
echo "ERROR " "(" "$i_count" ")" "$file"
echo "ERROR " "(" "$i_count" ")" "$file" >> $output_file
echo $program_output >> $output_file
((i_error++))
elif [[ "$program_output" == *"FATAL"* ]]; then
echo "FATAL " "(" "$i_count" ")" "$file"
echo "FATAL " "(" "$i_count" ")" "$file" >> $output_file
echo $program_output >> $output_file
((i_error++))
elif [[ "$program_output" == "" ]]; then
echo "NO OUTPUT " "(" "$i_count" ")" "$file"
echo "NO OUTPUT " "(" "$i_count" ")" "$file" >> $output_file
echo $program_output >> $output_file
((i_error++))
else
echo "OK " "(" "$i_count" ")" "$file"
#To display output, remove the # below
#echo "OK " "(" "$i_count" ")" "$file" >> $output_file
#echo $program_output
#echo $program_output >> $output_file
((i_ok++))
fi
fi
done
echo "All:$i_count"
echo "All:$i_count" >> $output_file
echo "OK:$i_ok"
echo "OK:$i_ok" >> $output_file
echo "ERROR:$i_error"
echo "ERROR:$i_error" >> $output_file
end_date=$(date +'%Y%m%d-%H%M%S')
echo "END $end_date"
echo "END $end_date" >> $output_file
echo "$output_file"
1ファイルにPEMファイルが複数行記載されている場合の分割方法
「input.txt」のサンプル
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
「devide.sh」の記載内容
#!/usr/bin/env python3
import os
#Delete All Files
def delete_all_files_in_folder(folder_path):
for filename in os.listdir(folder_path):
file_path = os.path.join(folder_path, filename)
if os.path.isfile(file_path):
os.remove(file_path)
print(f"Delete file: {file_path}")
#Make PEM File(one line)
def split_file_by_lines_for_loop(input_file, output_path_name):
with open(input_file, 'r') as file:
lines = file.readlines()
for i, line in enumerate(lines):
output_file = f"{output_path_name}/output_{str(i+1).zfill(8)}.cer"
with open(output_file, 'w') as output:
output.write(line)
print(f"Make file'{output_file}'")
#Make PEM File(Line break after 64 characters)
def process_all_files_in_folder(folder_path):
file_list = os.listdir(folder_path)
i_count=0
for filename in file_list:
input_file = os.path.join(folder_path, filename)
if os.path.isfile(input_file):
#Display read and write files
print(f"r: {input_file}")
output_file = output_path + filename
print(f"w: {output_file}")
with open(input_file, 'r') as infile:
content1 = infile.read()
#Line break every 64 characters
lines = [content1[i:i+64] for i in range(0, len(content1), 64)]
with open(output_file, 'w') as outfile:
for line in lines:
outfile.write(line + '\n')
#Add END to the end
def append_to_file(output_file, content3):
with open(output_file, 'a') as file:
file.write(content3 + '\n')
content_to_append = '-----END CERTIFICATE-----'
append_to_file(output_file, content_to_append)
#Add BEGIN first
def prepend_to_file(output_file, content2):
with open(output_file, 'r+') as file:
original_content2 = file.read()
#Move to beginning of file
file.seek(0, 0)
file.write(content2 + '\n' + original_content2)
content2_to_prepend = '-----BEGIN CERTIFICATE-----'
prepend_to_file(output_file, content2_to_prepend)
#Deleting a line with just a newline
def remove_empty_lines_isspace(file_name):
with open(file_name, 'r') as file:
lines = file.readlines()
lines = [line for line in lines if not line.isspace()]
with open(file_name, 'w') as file:
file.writelines(lines)
remove_empty_lines_isspace(output_file)
#Run the program
input_multi_file_name = 'input.txt'
input_path = '/root/ドキュメント/output1/'
input_path_name = 'output1'
output_path = '/root/ドキュメント/output2/'
delete_all_files_in_folder(input_path)
delete_all_files_in_folder(output_path)
split_file_by_lines_for_loop(input_multi_file_name, input_path_name)
process_all_files_in_folder(input_path)