├── .gitignore ├── README.md ├── changelog.md ├── cpct ├── .idea │ ├── cpct.iml │ ├── dataSources.xml │ ├── misc.xml │ └── modules.xml ├── Procfile ├── cpct │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── fpkilint │ ├── binary_utils.py │ ├── cert_utils.py │ ├── certificate_policies.py │ ├── der2ascii │ ├── der2ascii.darwin │ ├── der2ascii.exe │ ├── display_maps.py │ ├── html_output.py │ ├── name_utils.py │ ├── profile_conformance.py │ ├── profiles │ │ ├── common-ssp │ │ │ ├── 1.8 │ │ │ │ ├── ssp-01-self-signed.json │ │ │ │ ├── ssp-02-self-issued-ca.json │ │ │ │ ├── ssp-03-cross-certificate.json │ │ │ │ ├── ssp-05-ee-signature.json │ │ │ │ ├── ssp-06-key-management.json │ │ │ │ ├── ssp-07-device.json │ │ │ │ ├── ssp-08-piv-card-auth.json │ │ │ │ ├── ssp-09-piv-auth.json │ │ │ │ ├── ssp-10-piv-content-signing.json │ │ │ │ ├── ssp-11-derived-piv-auth.json │ │ │ │ └── ssp-12-delegated-ocsp.json │ │ │ ├── 1.9 │ │ │ │ ├── ssp-01-self-signed.json │ │ │ │ ├── ssp-02-self-issued-ca.json │ │ │ │ ├── ssp-03-cross-certificate.json │ │ │ │ ├── ssp-05-ee-signature.json │ │ │ │ ├── ssp-06-key-management.json │ │ │ │ ├── ssp-07-device-no-pol-check.json │ │ │ │ ├── ssp-07-device.json │ │ │ │ ├── ssp-08-piv-card-auth.json │ │ │ │ ├── ssp-09-piv-auth.json │ │ │ │ ├── ssp-10-piv-content-signing.json │ │ │ │ ├── ssp-11-derived-piv-auth.json │ │ │ │ └── ssp-12-delegated-ocsp.json │ │ │ ├── 2.0 │ │ │ │ ├── ssp-01-self-signed.json │ │ │ │ ├── ssp-02-self-issued-ca.json │ │ │ │ ├── ssp-03-cross-certificate.json │ │ │ │ ├── ssp-04-intermediate-ca.json │ │ │ │ ├── ssp-05-piv-content-signing.json │ │ │ │ ├── ssp-06-piv-auth.json │ │ │ │ ├── ssp-07-piv-card-auth.json │ │ │ │ ├── ssp-08-ee-signature.json │ │ │ │ ├── ssp-09-key-management.json │ │ │ │ ├── ssp-10-derived-piv-auth.json │ │ │ │ ├── ssp-11-auth.json │ │ │ │ ├── ssp-12-device.json │ │ │ │ ├── ssp-13-delegated-ocsp.json │ │ │ │ ├── ssp-15-pivi-content-signing.json │ │ │ │ ├── ssp-16-pivi-authentication.json │ │ │ │ └── ssp-17-pivi-card-auth.json │ │ │ ├── 2.1 │ │ │ │ ├── ssp-01-self-signed.json │ │ │ │ ├── ssp-02-self-issued-ca.json │ │ │ │ ├── ssp-03-cross-certificate.json │ │ │ │ ├── ssp-04-intermediate-ca.json │ │ │ │ ├── ssp-05-piv-content-signing.json │ │ │ │ ├── ssp-06-piv-auth.json │ │ │ │ ├── ssp-07-piv-card-auth.json │ │ │ │ ├── ssp-08-ee-signature.json │ │ │ │ ├── ssp-09-key-management.json │ │ │ │ ├── ssp-10-derived-piv-auth.json │ │ │ │ ├── ssp-11-auth.json │ │ │ │ ├── ssp-12-device.json │ │ │ │ ├── ssp-13-delegated-ocsp.json │ │ │ │ ├── ssp-15-pivi-content-signing.json │ │ │ │ ├── ssp-16-pivi-authentication.json │ │ │ │ └── ssp-17-pivi-card-auth.json │ │ │ └── 2.2 │ │ │ │ ├── ssp-01-self-signed.json │ │ │ │ ├── ssp-02-self-issued-ca.json │ │ │ │ ├── ssp-03-cross-certificate.json │ │ │ │ ├── ssp-04-intermediate-ca.json │ │ │ │ ├── ssp-05-piv-content-signing.json │ │ │ │ ├── ssp-06-piv-auth.json │ │ │ │ ├── ssp-07-piv-card-auth.json │ │ │ │ ├── ssp-08-ee-signature.json │ │ │ │ ├── ssp-09-key-management.json │ │ │ │ ├── ssp-10-derived-piv-auth.json │ │ │ │ ├── ssp-11-auth.json │ │ │ │ ├── ssp-12-device.json │ │ │ │ ├── ssp-13-delegated-ocsp.json │ │ │ │ ├── ssp-15-pivi-content-signing.json │ │ │ │ ├── ssp-16-pivi-authentication.json │ │ │ │ └── ssp-17-pivi-card-auth.json │ │ ├── fbca │ │ │ ├── 1.8 │ │ │ │ ├── 1-self-signed-ca.json │ │ │ │ ├── 2-key-roll-over-ca.json │ │ │ │ ├── 3-cross-certificate.json │ │ │ │ ├── 5-ee-signature.json │ │ │ │ └── 6-ee-key-management.json │ │ │ ├── 1.9 │ │ │ │ ├── 1-self-signed-ca.json │ │ │ │ ├── 2-key-roll-over-ca.json │ │ │ │ ├── 3-cross-certificate.json │ │ │ │ ├── 5-ee-signature.json │ │ │ │ └── 6-ee-key-management.json │ │ │ └── 2.0 │ │ │ │ ├── 1-self-signed-ca.json │ │ │ │ ├── 2-key-roll-over-ca.json │ │ │ │ ├── 3-cross-certificate.json │ │ │ │ ├── 5-ee-signature.json │ │ │ │ ├── 6-ee-key-management.json │ │ │ │ ├── pivi-04-card-auth.json │ │ │ │ ├── pivi-05-authentication.json │ │ │ │ ├── pivi-08-content-signing.json │ │ │ │ └── pivi-09-delegated-ocsp.json │ │ ├── pivi │ │ │ ├── 1.2 │ │ │ │ ├── pivi-01-self-signed.json │ │ │ │ ├── pivi-02-cross-certificate.json │ │ │ │ ├── pivi-04-card-auth.json │ │ │ │ ├── pivi-05-authentication.json │ │ │ │ ├── pivi-06-signature.json │ │ │ │ ├── pivi-07-key-management.json │ │ │ │ ├── pivi-08-content-signing.json │ │ │ │ └── pivi-09-delegated-ocsp.json │ │ │ └── 1.3 │ │ │ │ ├── pivi-01-self-signed.json │ │ │ │ ├── pivi-02-cross-certificate.json │ │ │ │ ├── pivi-04-card-auth.json │ │ │ │ ├── pivi-05-authentication.json │ │ │ │ ├── pivi-06-signature.json │ │ │ │ ├── pivi-07-key-management.json │ │ │ │ ├── pivi-08-content-signing.json │ │ │ │ └── pivi-09-delegated-ocsp.json │ │ └── template.json │ ├── strapdown_output.py │ └── text2html.py ├── manage.py ├── manifest.yml ├── profiles │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── profiles.json │ ├── static │ │ ├── GSAStar.jpg │ │ ├── check-circle.svg │ │ ├── cio-logo-gif.gif │ │ ├── dropzone.js │ │ ├── help.png │ │ ├── idm_logo.png │ │ └── style.css │ ├── templates │ │ ├── contact-us.html │ │ ├── help.html │ │ ├── privacy-policy.html │ │ ├── result.html │ │ └── upload.html │ ├── tests.py │ └── views.py ├── requirements.txt ├── runtime.txt └── staticfiles │ ├── GSAStar.554ed8897b06.jpg │ ├── GSAStar.jpg │ ├── check-circle.d8739c607554.svg │ ├── check-circle.d8739c607554.svg.gz │ ├── check-circle.svg │ ├── check-circle.svg.gz │ ├── cio-logo-gif.5df75addbfd6.gif │ ├── cio-logo-gif.gif │ ├── dropzone.ca03e492beaa.js │ ├── dropzone.ca03e492beaa.js.gz │ ├── dropzone.js │ ├── dropzone.js.gz │ ├── help.fffff73b616d.png │ ├── help.png │ ├── idm_logo.3d0213b576f4.png │ ├── idm_logo.png │ ├── staticfiles.json │ ├── strapdown.css │ └── strapdown.js ├── docs ├── SysDiag.pptx ├── Workflow.pdf ├── cpct_contact_us.md ├── cpct_privacy_policy.md ├── cpct_user_help.md ├── cpcthelp.md ├── profile-config.xlsx └── sample.md └── testdata ├── README.md ├── certs ├── README.md ├── parse_cert_base64.cer ├── parse_cert_binary.cer ├── parse_cert_not_cert.p7b ├── parse_cert_not_cert.pem └── parse_cert_pem.cer └── profiles └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # test files 2 | *_test.* 3 | cpct/fpkilint/test/ 4 | cpct/fpkilint/cmd/ 5 | 6 | # Byte-compiled / optimized / DLL files 7 | __pycache__/ 8 | *.py[cod] 9 | *$py.class 10 | 11 | # C extensions 12 | *.so 13 | 14 | # Distribution / packaging 15 | .Python 16 | build/ 17 | develop-eggs/ 18 | dist/ 19 | downloads/ 20 | eggs/ 21 | .eggs/ 22 | lib/ 23 | lib64/ 24 | parts/ 25 | sdist/ 26 | var/ 27 | wheels/ 28 | *.egg-info/ 29 | .installed.cfg 30 | *.egg 31 | MANIFEST 32 | 33 | # PyInstaller 34 | # Usually these files are written by a python script from a template 35 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 36 | *.manifest 37 | *.spec 38 | 39 | # Installer logs 40 | pip-log.txt 41 | pip-delete-this-directory.txt 42 | 43 | # Unit test / coverage reports 44 | htmlcov/ 45 | .tox/ 46 | .coverage 47 | .coverage.* 48 | .cache 49 | nosetests.xml 50 | coverage.xml 51 | *.cover 52 | .hypothesis/ 53 | .pytest_cache/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | db.sqlite3 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # pyenv 81 | .python-version 82 | 83 | # celery beat schedule file 84 | celerybeat-schedule 85 | 86 | # SageMath parsed files 87 | *.sage.py 88 | 89 | # Environments 90 | .env 91 | .venv 92 | env/ 93 | venv/ 94 | ENV/ 95 | env.bak/ 96 | venv.bak/ 97 | 98 | # Spyder project settings 99 | .spyderproject 100 | .spyproject 101 | 102 | # Rope project settings 103 | .ropeproject 104 | 105 | # mkdocs documentation 106 | /site 107 | 108 | # mypy 109 | .mypy_cache/ 110 | 111 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 112 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 113 | 114 | # User-specific stuff 115 | cpct/.idea/**/workspace.xml 116 | cpct/.idea/**/tasks.xml 117 | cpct/.idea/**/usage.statistics.xml 118 | cpct/.idea/**/dictionaries 119 | cpct/.idea/**/shelf 120 | cpct/.idea/workspace.xml 121 | cpct/.idea/tasks.xml 122 | cpct/.idea/usage.statistics.xml 123 | cpct/.idea/dictionaries 124 | cpct/.idea/shelf 125 | 126 | # Sensitive or high-churn files 127 | cpct/.idea/**/dataSources/ 128 | cpct/.idea/**/dataSources.ids 129 | cpct/.idea/**/dataSources.local.xml 130 | cpct/.idea/**/sqlDataSources.xml 131 | cpct/.idea/**/dynamic.xml 132 | cpct/.idea/**/uiDesigner.xml 133 | cpct/.idea/**/dbnavigator.xml 134 | cpct/.idea/dataSources/ 135 | cpct/.idea/dataSources.ids 136 | cpct/.idea/dataSources.local.xml 137 | cpct/.idea/sqlDataSources.xml 138 | cpct/.idea/dynamic.xml 139 | cpct/.idea/uiDesigner.xml 140 | cpct/.idea/dbnavigator.xml 141 | 142 | # not needed 143 | .idea/ 144 | .idea/fpkilint.iml 145 | 146 | # Gradle 147 | cpct/.idea/**/gradle.xml 148 | cpct/.idea/**/libraries 149 | 150 | # CMake 151 | cmake-build-*/ 152 | 153 | # Mongo Explorer plugin 154 | cpct/.idea/**/mongoSettings.xml 155 | 156 | # File-based project format 157 | *.iws 158 | 159 | # IntelliJ 160 | out/ 161 | 162 | # mpeltonen/sbt-idea plugin 163 | .idea_modules/ 164 | 165 | # JIRA plugin 166 | atlassian-ide-plugin.xml 167 | 168 | # Cursive Clojure plugin 169 | cpct/.idea/replstate.xml 170 | 171 | # Crashlytics plugin (for Android Studio and IntelliJ) 172 | com_crashlytics_export_strings.xml 173 | crashlytics.properties 174 | crashlytics-build.properties 175 | fabric.properties 176 | 177 | # Editor-based Rest Client 178 | cpct/.idea/httpRequests 179 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Certificate Profile Conformance Tool (CPCT) 2 | 3 | CPCT is capable of analyzing a certificate’s conformance to a pre-defined certificate profile. User input consists of a certificate and a profile selection. After processing the certificate, CPCT outputs a table similar in formatting to the certificate format tables often included in Certificate Profile documents, but including additional analysis content indicating PASS or specific text describing the non-conformance. 4 | 5 | [Example output](https://github.com/GSA/fpkilint/blob/dev/docs/sample.md) 6 | 7 | The tool is capable of analyzing certificates for conformance with the FPKI profiles described in the documents available on the [Federal Public Key Infrastructure (FPKI) web page](https://playbooks.idmanagement.gov/fpki/) 8 | 9 | #### Running the CPCT Application 10 | 11 | To better serve the FPKI community, the CPCT was transitioned from an online application to an application that is hosted and run from the user’s workstation. Users can now access the CPCT application directly from their local hard drive using Docker Desktop. A link to more information on how to access the CPCT application is provided below. 12 | 13 | [Step-by-step Instructions on How Run the CPCT Tool](https://playbooks.idmanagement.gov/fpki/tools/cpct/#accessing-the-cpct-application) 14 | 15 | #### Common Policy Framework 16 | [Certificate Policy for the Federal PKI Common Policy Framework (FCPF)](https://www.idmanagement.gov/docs/fpki-x509-cert-policy-common.pdf) 17 | 18 | [X.509 Certificate and CRL Extensions Profile for the Shared Service Provider (SSP) Program](https://www.idmanagement.gov/docs/fpki-x509-cert-profile-common.pdf) 19 | 20 | #### Federal Bridge 21 | [X.509 Certificate and CRL Extensions Profile](https://www.idmanagement.gov/docs/fpki-x509-cert-profiles-fbca.pdf) 22 | 23 | [X.509 Certificate and CRL Extensions Profile for Personal Identity Verification Interoperable (PIV-I) Credentials](https://www.idmanagement.gov/docs/fpki-x509-cert-profiles-pivi.pdf) 24 | 25 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # FPKI Lint Change Log 2 | Updated: 01/12/2024 3 | 4 | ## Updates and modifications 5 | 6 | - Updated version numbers for Common-SSP v2.1, 2.2, and FBCA v2.0 to correct version. 7 | - Updated dropdown list to reflect correct version number. 8 | - Updated each `more_info_url` to the url of profile's PDF document. 9 | 10 | ## Common Profile v2.2 11 | 12 | | Profiles Affected | Common Profile Changes | 13 | |:--------------------------|:---------------| 14 | | All profiles except Worksheet 1 | Authority Information Access & Certificate Revocation List Distribution Point - Require HTTP URI first | 15 | | All profiles except worksheet 1 | Authority Information Access - Allow .cer | 16 | | All Profiles | DN Encoding: Allow only printableString and/or UTF8 | 17 | | Worksheet 1-3 | | 18 | | Worksheet 6-11, 16-17 | Allow Subject Directory Attributes (e.g., citizenship) | 19 | | Worksheet 3 | Cross Certificate: | 20 | | Worksheet 4 | Intermediate Certificate (new profile): | 21 | | Worksheet 13 | OCSP Responder Certificate, EKU must be marked critical | 22 | | Worksheet 8,9 | Signature Certificates and Key Management Certificates | 23 | 24 | ## Bridge Profile v2.0 25 | 26 | | Profiles Affected | Bridge Profile Changes | 27 | |:--------------------------|:----------------------| 28 | | Worksheet 8, 9 | | 29 | | Worksheet 4-7 and Worksheet 10-17 | Several new profiles were drafted to include: 30 | | All except Worksheet 1 | 31 | | All except Worksheet 1 | Authority Information Access - Allow .cer | 32 | | All Worksheets | DN Encoding: Allow only printableString and/or UTF8 | 33 | | Worksheet 6,7,11,16 | Optionally allow Subject Directory Attributes (e.g., citizenship) for authentication certificates (General, PIV-I, PIV-I card authentication) | 34 | | Worksheet 3, 4 | Cross Certificate Clarify appropriate use of requireExplicitPolicy and inhibitPolicyMapping | 35 | | Worksheet 13 | OCSP Responder Certificate EKU must be marked critical | 36 | | None | Section 8 References – removed and FBCA CP Appendix D is linked | 37 | 38 | -------------------------------------------------------------------------------- /cpct/.idea/cpct.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | -------------------------------------------------------------------------------- /cpct/.idea/dataSources.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | sqlite.xerial 6 | true 7 | true 8 | $PROJECT_DIR$/cpct/settings.py 9 | org.sqlite.JDBC 10 | jdbc:sqlite:D:\Source\Python\cpct\db.sqlite3 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /cpct/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /cpct/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /cpct/Procfile: -------------------------------------------------------------------------------- 1 | web: gunicorn cpct.wsgi --workers 2 -------------------------------------------------------------------------------- /cpct/cpct/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/cpct/__init__.py -------------------------------------------------------------------------------- /cpct/cpct/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for cpct project. 3 | 4 | Generated by 'django-admin startproject' using Django 2.0.1. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.0/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/2.0/ref/settings/ 11 | """ 12 | 13 | import os 14 | import sys 15 | 16 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 17 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 18 | 19 | 20 | # Quick-start development settings - unsuitable for production 21 | # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ 22 | 23 | # SECURITY WARNING: keep the secret key used in production secret! 24 | SECRET_KEY = '' 25 | 26 | # SECURITY WARNING: don't run with debug turned on in production! 27 | 28 | if 'win' in sys.platform: 29 | DEBUG = True 30 | ALLOWED_HOSTS = ['127.0.0.1'] 31 | else: 32 | DEBUG = False 33 | ALLOWED_HOSTS = ['cpct.app.cloud.gov', 'cpct.cfapps.io'] 34 | 35 | # Application definition 36 | 37 | INSTALLED_APPS = [ 38 | # 'django.contrib.auth', 39 | # 'django.contrib.contenttypes', 40 | # 'django.contrib.sessions', 41 | # 'django.contrib.messages', 42 | 'whitenoise.runserver_nostatic', 43 | 'django.contrib.staticfiles', 44 | 'profiles.apps.ProfilesConfig', 45 | ] 46 | 47 | MIDDLEWARE = [ 48 | 'django.middleware.security.SecurityMiddleware', 49 | 'whitenoise.middleware.WhiteNoiseMiddleware', 50 | # 'django.contrib.sessions.middleware.SessionMiddleware', 51 | 'django.middleware.common.CommonMiddleware', 52 | 'django.middleware.csrf.CsrfViewMiddleware', 53 | # 'django.contrib.auth.middleware.AuthenticationMiddleware', 54 | # 'django.contrib.messages.middleware.MessageMiddleware', 55 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 56 | ] 57 | 58 | ROOT_URLCONF = 'cpct.urls' 59 | 60 | TEMPLATES = [ 61 | { 62 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 63 | 'DIRS': [os.path.join(BASE_DIR, 'templates')] 64 | , 65 | 'APP_DIRS': True, 66 | 'OPTIONS': { 67 | 'context_processors': [ 68 | 'django.template.context_processors.debug', 69 | 'django.template.context_processors.request', 70 | # 'django.contrib.auth.context_processors.auth', 71 | # 'django.contrib.messages.context_processors.messages', 72 | ], 73 | }, 74 | }, 75 | ] 76 | 77 | WSGI_APPLICATION = 'cpct.wsgi.application' 78 | 79 | 80 | # Database 81 | # https://docs.djangoproject.com/en/2.0/ref/settings/#databases 82 | 83 | DATABASES = { 84 | 'default': { 85 | 'ENGINE': 'django.db.backends.sqlite3', 86 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 87 | } 88 | } 89 | 90 | 91 | # Password validation 92 | # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators 93 | 94 | AUTH_PASSWORD_VALIDATORS = [ 95 | { 96 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 97 | }, 98 | { 99 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 100 | }, 101 | { 102 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 103 | }, 104 | { 105 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 106 | }, 107 | ] 108 | 109 | 110 | # Internationalization 111 | # https://docs.djangoproject.com/en/2.0/topics/i18n/ 112 | 113 | LANGUAGE_CODE = 'en-us' 114 | 115 | TIME_ZONE = 'UTC' 116 | 117 | USE_I18N = True 118 | 119 | USE_L10N = True 120 | 121 | USE_TZ = True 122 | 123 | if 'win' in sys.platform: 124 | # must be false to run without https in debugger 125 | SESSION_COOKIE_SECURE = True 126 | CSRF_COOKIE_SECURE = False 127 | CSRF_COOKIE_HTTPONLY = True 128 | else: 129 | SESSION_COOKIE_SECURE = True 130 | CSRF_COOKIE_SECURE = True 131 | CSRF_COOKIE_HTTPONLY = True 132 | SECURE_HSTS_INCLUDE_SUBDOMAINS = True 133 | SECURE_HSTS_SECONDS = 31536000 134 | SECURE_HSTS_PRELOAD = True 135 | 136 | 137 | # Static files (CSS, JavaScript, Images) 138 | # https://docs.djangoproject.com/en/2.0/howto/static-files/ 139 | 140 | STATIC_URL = '/static/' 141 | STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') 142 | STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' 143 | WHITENOISE_ALLOW_ALL_ORIGINS = False 144 | 145 | -------------------------------------------------------------------------------- /cpct/cpct/urls.py: -------------------------------------------------------------------------------- 1 | """CPCT URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/2.0/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | # from django.contrib import admin 17 | from django.urls import path 18 | from django.conf.urls import include, url 19 | from profiles.views import * 20 | 21 | urlpatterns = [ 22 | url(r'^$', dashboard, name='dashboard'), 23 | url(r'^file/', upload_file, name='upload'), 24 | url(r'^help/', help, name='help'), 25 | url(r'^privacy-policy/', privacy, name='privacy-policy'), 26 | url(r'^contact-us/', contact, name='contact-us'), 27 | ] 28 | -------------------------------------------------------------------------------- /cpct/cpct/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for CPCT project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | from django.core.wsgi import get_wsgi_application 12 | 13 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cpct.settings") 14 | 15 | application = get_wsgi_application() 16 | -------------------------------------------------------------------------------- /cpct/fpkilint/binary_utils.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import sys 3 | from asn1crypto import parser 4 | 5 | 6 | def der2ascii(binary_der): 7 | if sys.platform == 'win32' or sys.platform == 'cygwin': 8 | completed_process = subprocess.run(["der2ascii.exe"], input=binary_der, stdout=subprocess.PIPE) 9 | elif sys.platform == 'darwin': 10 | completed_process = subprocess.run(["fpkilint/der2ascii.darwin"], input=binary_der, stdout=subprocess.PIPE) 11 | else: 12 | completed_process = subprocess.run(["fpkilint/der2ascii"], input=binary_der, stdout=subprocess.PIPE) 13 | return completed_process.stdout.decode("utf-8") 14 | 15 | 16 | -------------------------------------------------------------------------------- /cpct/fpkilint/cert_utils.py: -------------------------------------------------------------------------------- 1 | import base64 2 | from asn1crypto import pem, x509 3 | from fpkilint.name_utils import get_general_name_string, get_general_name_type, get_short_name_from_dn 4 | 5 | 6 | def parse_certificate(byte_data): 7 | 8 | if not isinstance(byte_data, bytes): 9 | raise TypeError("byte_data must be a byte string") 10 | 11 | if byte_data[0] == 0x4D: # 'M': 12 | byte_data = base64.b64decode(byte_data) 13 | 14 | if pem.detect(byte_data): 15 | file_type, headers, byte_data = pem.unarmor(byte_data) 16 | 17 | if file_type != 'CERTIFICATE': 18 | raise TypeError("CERTIFICATE expected, but got {}".format(file_type)) 19 | 20 | if byte_data[0] != 0x30: 21 | raise TypeError("Leading byte is not 0x30 - this is not a certificate") 22 | 23 | if byte_data[1] & 0xF0 != 0x80: 24 | raise TypeError("Second byte is not 0x8n - this is not a certificate") 25 | 26 | x509cert = x509.Certificate.load(byte_data) 27 | x509cert.issuer # forces lazy parse to occur now 28 | 29 | return x509cert 30 | 31 | 32 | def parse_tbs_certificate(byte_data): 33 | """ 34 | :param byte_data - certificate data to parse - can be pem or binary, a signed cert or a tbs cert: 35 | :return: x509.TbsCertificate 36 | """ 37 | 38 | if not isinstance(byte_data, bytes): 39 | raise TypeError("byte_data must be a byte string") 40 | if len(byte_data) < 64: 41 | raise TypeError("byte_data too short to be a certificate") 42 | 43 | if byte_data[0] == 0x4D: # 'M': 44 | byte_data = base64.b64decode(byte_data) 45 | 46 | if pem.detect(byte_data): 47 | file_type, headers, byte_data = pem.unarmor(byte_data) 48 | 49 | if file_type != 'CERTIFICATE': 50 | raise TypeError("CERTIFICATE expected, but got {}".format(file_type)) 51 | 52 | if byte_data[0] != 0x30: 53 | raise TypeError("Leading byte is not 0x30 - this is not a certificate") 54 | 55 | if byte_data[1] & 0xF0 != 0x80: 56 | raise TypeError("Second byte is not 0x8n - this is not a certificate") 57 | 58 | tag = byte_data[2 + (byte_data[1] & 0x0F)] 59 | if tag == 0x30: 60 | x509cert = x509.Certificate.load(byte_data) 61 | tbs_certificate = x509cert['tbs_certificate'] 62 | elif tag == 0xA0: 63 | tbs_certificate = x509.TbsCertificate.load(byte_data) 64 | else: 65 | raise TypeError("Data is not a Certificate nor a TbsCertificate") 66 | 67 | tbs_certificate['serial_number'] # forces lazy parse to occur now 68 | 69 | return tbs_certificate 70 | 71 | 72 | def get_5280_method_1_key_id(cert): 73 | """ 74 | :param cert: x509.Certificate 75 | :return: rfc5280 method 1 key id 76 | """ 77 | if not cert.public_key.sha1 == cert['tbs_certificate']['subject_public_key_info'].sha1: 78 | print('hmmmmm') 79 | 80 | return cert.public_key.sha1 81 | 82 | 83 | def is_policy_in_policies(policy_oid_string, certificate_policies): 84 | 85 | if not isinstance(certificate_policies, x509.CertificatePolicies): 86 | raise TypeError("certificate_policies must be a x509.CertificatePolicies") 87 | 88 | if not isinstance(policy_oid_string, str): 89 | raise TypeError("policy_oid_string must be a string") 90 | 91 | oid = x509.PolicyIdentifier(policy_oid_string) 92 | pi = x509.PolicyInformation({'policy_identifier': oid}) 93 | 94 | if pi.native in certificate_policies.native: 95 | return True 96 | 97 | return False 98 | 99 | 100 | def get_extension_list(tbs_cert, oid=None): 101 | if oid and not isinstance(oid, str): 102 | raise TypeError("oid must be dotted oid string") 103 | 104 | if not isinstance(tbs_cert, x509.TbsCertificate): 105 | raise TypeError("cert must be x509.TbsCertificate") 106 | 107 | extensions = tbs_cert['extensions'] 108 | extension_list = list() 109 | 110 | for e in extensions: 111 | if oid is None or e['extn_id'].dotted == oid: 112 | extension_list.append([e, e['critical'].native]) 113 | 114 | return extension_list 115 | 116 | 117 | def get_extension_and_criticality(tbs_cert, oid): 118 | if not isinstance(oid, str): 119 | raise TypeError("oid must be dotted oid string") 120 | 121 | ext_list = get_extension_list(tbs_cert, oid) 122 | 123 | if len(ext_list) == 0: 124 | return None, False 125 | 126 | return ext_list[0][0], ext_list[0][1] 127 | 128 | 129 | def get_short_name_from_cert(cert, name_for_subject=True): 130 | 131 | if isinstance(cert, x509.Certificate): 132 | cert = cert['tbs_certificate'] 133 | 134 | if name_for_subject: 135 | name = cert['subject'] 136 | else: 137 | name = cert['issuer'] 138 | 139 | if len(name.contents) > 2: 140 | return get_short_name_from_dn(name) 141 | 142 | # try the alt name... 143 | alt_name_value = None 144 | 145 | if name_for_subject: 146 | extension, critical = get_extension_and_criticality(cert, '2.5.29.17') 147 | if extension is not None: 148 | alt_name_value = extension['extn_value'].parsed 149 | 150 | else: 151 | extension, critical = get_extension_and_criticality(cert, '2.5.29.18') 152 | if extension is not None: 153 | alt_name_value = extension['extn_value'].parsed 154 | 155 | alt_name_string = "NULL" 156 | 157 | if alt_name_value: 158 | 159 | desired_alt_names = [ 160 | 'dns_name', 161 | 'rfc822_name', 162 | 'other_name_upn', 163 | 'uniform_resource_identifier_chuid', 164 | 'other_name_piv_fasc_n', 165 | 'uniform_resource_identifier_http', 166 | 'uniform_resource_identifier_https', 167 | 'uniform_resource_identifier_ldap', 168 | 'uniform_resource_identifier_ldaps', 169 | 'uniform_resource_identifier', 170 | 'directory_name', 171 | ] 172 | 173 | if len(alt_name_value) > 0: 174 | general_name = alt_name_value[0] 175 | alt_name_string = get_general_name_type(general_name) 176 | 177 | if len(alt_name_value) == 1: 178 | return alt_name_value 179 | 180 | for desired_type in desired_alt_names: 181 | for general_name in alt_name_value: 182 | if desired_type == get_general_name_type(general_name): 183 | return get_general_name_string(general_name) 184 | 185 | return alt_name_string 186 | -------------------------------------------------------------------------------- /cpct/fpkilint/der2ascii: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/fpkilint/der2ascii -------------------------------------------------------------------------------- /cpct/fpkilint/der2ascii.darwin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/fpkilint/der2ascii.darwin -------------------------------------------------------------------------------- /cpct/fpkilint/der2ascii.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/fpkilint/der2ascii.exe -------------------------------------------------------------------------------- /cpct/fpkilint/display_maps.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | 4 | general_name_display_map = { 5 | 'x400_address': 'X400 Address', 6 | 'registered_id': 'Registered ID', 7 | 'edi_party_name': 'EDI Party Name', 8 | 'dns_name': 'DNS Name', 9 | 'directory_name': 'Directory Name', 10 | 'rfc822_name': 'Email', 11 | 'ip_address': 'IP Address', 12 | 'other_name': 'Other Name', 13 | 'uniform_resource_identifier': 'URI', 14 | 'other_name_upn': 'UPN', 15 | 'other_name_piv_fasc_n': 'FASC-N', 16 | 'uniform_resource_identifier_chuid': 'UUID', 17 | 'uniform_resource_identifier_http': 'HTTP URI', 18 | 'uniform_resource_identifier_ldap': 'LDAP URI', 19 | 'uniform_resource_identifier_https': 'HTTPS URI', 20 | 'uniform_resource_identifier_ldaps': 'LDAPS URI', 21 | } 22 | 23 | other_name_display_map = { 24 | '1.3.6.1.4.1.311.20.2.3': 'UPN', 25 | '2.16.840.1.101.3.6.6': 'FASC-N', 26 | } 27 | 28 | directory_string_type_display_map = { 29 | 'printable_string': 'Printable', 30 | 'utf8_string': 'UTF8', 31 | 'bmp_string': 'BMP', 32 | 'teletex_string': 'Teletex', 33 | 'universal_string': 'Universal', 34 | 'ia5_string': 'IA5', 35 | } 36 | 37 | dn_name_component_display_map = { 38 | 'common_name': 'CN', 39 | 'surname': 'SN', 40 | 'serial_number': 'Serial', 41 | 'country_name': 'C', 42 | 'locality_name': 'L', 43 | 'state_or_province_name': 'State', 44 | 'street_address': 'Street', 45 | 'organization_name': 'O', 46 | 'organizational_unit_name': 'OU', 47 | 'title': 'Title', 48 | 'business_category': 'Business Category', 49 | 'postal_code': 'Postal Code', 50 | 'telephone_number': 'Telephone Number', 51 | 'name': 'Name', 52 | 'given_name': 'GN', 53 | 'initials': 'Initials', 54 | 'generation_qualifier': 'Generation Qualifier', 55 | 'unique_identifier': 'Unique ID', 56 | 'dn_qualifier': 'DN Qual', 57 | 'pseudonym': 'Pseudonym', 58 | 'email_address': 'Email', 59 | 'incorporation_locality': 'Incorporation Locality', 60 | 'incorporation_state_or_province': 'Incorporation State/Province', 61 | 'incorporation_country': 'Incorporation Country', 62 | 'domain_component': 'DC', 63 | 'name_distinguisher': 'Name Distinguisher', 64 | 'organization_identifier': 'Organization Identifier', 65 | '0.9.2342.19200300.100.1.1': 'User ID', 66 | '2.23.133.2.3': 'TPMVersion', 67 | '2.23.133.2.2': 'TPMModel', 68 | '2.23.133.2.1': 'TPMManufacturer', 69 | } 70 | 71 | eku_display_map = { 72 | # https://tools.ietf.org/html/rfc5280#page-45 73 | '2.5.29.37.0': 'Any Extended Key Usage', 74 | '1.3.6.1.5.5.7.3.1': 'Server Authentication', 75 | '1.3.6.1.5.5.7.3.2': 'Client Authentication', 76 | '1.3.6.1.5.5.7.3.3': 'Code Signing', 77 | '1.3.6.1.5.5.7.3.4': 'Email Protection', 78 | '1.3.6.1.5.5.7.3.5': 'IPSEC End System', 79 | '1.3.6.1.5.5.7.3.6': 'IPSEC Tunnel', 80 | '1.3.6.1.5.5.7.3.7': 'IPSEC User', 81 | '1.3.6.1.5.5.7.3.8': 'Time Stamping', 82 | '1.3.6.1.5.5.7.3.9': 'OCSP Signing', 83 | # http://tools.ietf.org/html/rfc3029.html#page-9 84 | '1.3.6.1.5.5.7.3.10': 'DVCS', 85 | # http://tools.ietf.org/html/rfc6268.html#page-16 86 | '1.3.6.1.5.5.7.3.13': 'EAP over PPP', 87 | '1.3.6.1.5.5.7.3.14': 'EAP over LAN', 88 | # https://tools.ietf.org/html/rfc5055#page-76 89 | '1.3.6.1.5.5.7.3.15': 'SCVP Server', 90 | '1.3.6.1.5.5.7.3.16': 'SCVP Client', 91 | # https://tools.ietf.org/html/rfc4945#page-31 92 | '1.3.6.1.5.5.7.3.17': 'IPSEC IKE', 93 | # https://tools.ietf.org/html/rfc5415#page-38 94 | '1.3.6.1.5.5.7.3.18': 'CAPWAP ac', 95 | '1.3.6.1.5.5.7.3.19': 'CAPWAP wtp', 96 | # https://tools.ietf.org/html/rfc5924#page-8 97 | '1.3.6.1.5.5.7.3.20': 'SIP Domain', 98 | # https://tools.ietf.org/html/rfc6187#page-7 99 | '1.3.6.1.5.5.7.3.21': 'Secure Shell Client', 100 | '1.3.6.1.5.5.7.3.22': 'Secure Shell Server', 101 | # https://tools.ietf.org/html/rfc6494#page-7 102 | '1.3.6.1.5.5.7.3.23': 'send router', 103 | '1.3.6.1.5.5.7.3.24': 'send proxied router', 104 | '1.3.6.1.5.5.7.3.25': 'send owner', 105 | '1.3.6.1.5.5.7.3.26': 'send proxied owner', 106 | # https://tools.ietf.org/html/rfc6402#page-10 107 | '1.3.6.1.5.5.7.3.27': 'CMC CA', 108 | '1.3.6.1.5.5.7.3.28': 'CMC RA', 109 | '1.3.6.1.5.5.7.3.29': 'CMC Archive', 110 | # https://tools.ietf.org/html/draft-ietf-sidr-bgpsec-pki-profiles-15#page-6 111 | '1.3.6.1.5.5.7.3.30': 'bgpspec router', 112 | # https://msdn.Microsoft.com/en-us/library/windows/desktop/aa378132(v=vs.85).aspx 113 | # and https://support.Microsoft.com/en-us/kb/287547 114 | '1.3.6.1.4.1.311.10.3.1': 'Microsoft Trust List Signing', 115 | '1.3.6.1.4.1.311.10.3.2': 'Microsoft time stamp signing', 116 | '1.3.6.1.4.1.311.10.3.3': 'Microsoft server gated', 117 | '1.3.6.1.4.1.311.10.3.3.1': 'Microsoft serialized', 118 | '1.3.6.1.4.1.311.10.3.4': 'Microsoft EFS', 119 | '1.3.6.1.4.1.311.10.3.4.1': 'Microsoft EFS recovery', 120 | '1.3.6.1.4.1.311.10.3.5': 'Microsoft whql', 121 | '1.3.6.1.4.1.311.10.3.6': 'Microsoft nt5', 122 | '1.3.6.1.4.1.311.10.3.7': 'Microsoft oem whql', 123 | '1.3.6.1.4.1.311.10.3.8': 'Microsoft embedded nt', 124 | '1.3.6.1.4.1.311.10.3.9': 'Microsoft root list signer', 125 | '1.3.6.1.4.1.311.10.3.10': 'Microsoft qualified subordination', 126 | '1.3.6.1.4.1.311.10.3.11': 'Microsoft key recovery', 127 | '1.3.6.1.4.1.311.10.3.12': 'Microsoft Doc Signing', 128 | '1.3.6.1.4.1.311.10.3.13': 'Microsoft Lifetime signing', 129 | '1.3.6.1.4.1.311.10.3.14': 'Microsoft mobile device software', 130 | '1.3.6.1.4.1.311.3.10.3.1': 'Microsoft Signer of CTLs', 131 | '1.3.6.1.4.1.311.3.10.3.2': 'Microsoft Signer of TimeStamps', 132 | '1.3.6.1.4.1.311.3.10.3.3': 'Microsoft Can use strong encryption in export environment', 133 | '1.3.6.1.4.1.311.3.10.3.4': 'Microsoft Can use encrypted file systems (EFS)', 134 | '1.3.6.1.4.1.311.3.10.3.5': 'Microsoft Can use Windows Hardware Compatible (WHQL)', 135 | '1.3.6.1.4.1.311.3.10.3.6': 'Microsoft Signed by the NT5 Build Lab', 136 | '1.3.6.1.4.1.311.3.10.3.7': 'Microsoft Signed by an OEM of WHQL', 137 | '1.3.6.1.4.1.311.3.10.3.8': 'Microsoft Signed by the Embedded NT', 138 | '1.3.6.1.4.1.311.3.10.3.9': 'Microsoft Signer of a CTL containing trusted roots', 139 | '1.3.6.1.4.1.311.3.10.3.10': 'Microsoft Key Recovery', 140 | '1.3.6.1.4.1.311.3.10.3.11': 'Microsoft Key Recovery', 141 | '1.3.6.1.4.1.311.3.10.3.12': 'Microsoft Document Signing', 142 | # https://opensource.Apple.com/source 143 | # - /Security/Security-57031.40.6/Security/libsecurity keychain/lib/SecPolicy.cpp 144 | # - /libsecurity cssm/libsecurity cssm-36064/lib/oidsalg.c 145 | '1.2.840.113635.100.1.2': 'Apple x509 basic', 146 | '1.2.840.113635.100.1.3': 'Apple ssl', 147 | '1.2.840.113635.100.1.4': 'Apple local cert gen', 148 | '1.2.840.113635.100.1.5': 'Apple csr gen', 149 | '1.2.840.113635.100.1.6': 'Apple revocation crl', 150 | '1.2.840.113635.100.1.7': 'Apple revocation ocsp', 151 | '1.2.840.113635.100.1.8': 'Apple smime', 152 | '1.2.840.113635.100.1.9': 'Apple eap', 153 | '1.2.840.113635.100.1.10': 'Apple software update signing', 154 | '1.2.840.113635.100.1.11': 'Apple IPSEC', 155 | '1.2.840.113635.100.1.12': 'Apple ichat', 156 | '1.2.840.113635.100.1.13': 'Apple resource signing', 157 | '1.2.840.113635.100.1.14': 'Apple pkinit client', 158 | '1.2.840.113635.100.1.15': 'Apple pkinit server', 159 | '1.2.840.113635.100.1.16': 'Apple code signing', 160 | '1.2.840.113635.100.1.17': 'Apple package signing', 161 | '1.2.840.113635.100.1.18': 'Apple id validation', 162 | '1.2.840.113635.100.1.20': 'Apple time stamping', 163 | '1.2.840.113635.100.1.21': 'Apple revocation', 164 | '1.2.840.113635.100.1.22': 'Apple passbook signing', 165 | '1.2.840.113635.100.1.23': 'Apple mobile store', 166 | '1.2.840.113635.100.1.24': 'Apple escrow service', 167 | '1.2.840.113635.100.1.25': 'Apple profile signer', 168 | '1.2.840.113635.100.1.26': 'Apple qa profile signer', 169 | '1.2.840.113635.100.1.27': 'Apple test mobile store', 170 | '1.2.840.113635.100.1.28': 'Apple otapki signer', 171 | '1.2.840.113635.100.1.29': 'Apple test otapki signer', 172 | '1.2.840.113625.100.1.30': 'Apple id validation record signing policy', 173 | '1.2.840.113625.100.1.31': 'Apple smp encryption', 174 | '1.2.840.113625.100.1.32': 'Apple test smp encryption', 175 | '1.2.840.113635.100.1.33': 'Apple server authentication', 176 | '1.2.840.113635.100.1.34': 'Apple pcs escrow service', 177 | # missing from asn1crypto 178 | '1.3.6.1.4.1.311.20.2.2': 'MS Smart Card Logon', 179 | '2.16.840.1.101.3.6.8': 'id-PIV-cardAuth', 180 | '2.16.840.1.101.3.6.7': 'id-PIV-content-signing', 181 | '2.16.840.1.101.3.8.7': 'id-fpki-pivi-content-signing', 182 | '1.3.6.1.5.2.3.4': 'id-pkinit-KPClientAuth', 183 | '1.3.6.1.5.2.3.5': 'id-pkinit-KPKdc', 184 | '1.3.6.1.4.1.311.20.2.1': 'MS Enrollment Agent', 185 | '1.3.6.1.4.1.311.21.6': 'MS Key Recovery Agent', # Enhanced Key Usage for key recovery agent certificate 186 | '1.2.840.113583.1.1.5': 'Adobe PDF Signing', 187 | '2.23.133.8.1': 'Endorsement Key Certificate', 188 | '1.3.6.1.5.5.8.2.2': 'IKE Intermediate', 189 | # https://pub.carillon.ca/CertificatePolicy.pdf 190 | '1.3.6.1.4.1.25054.3.5.1': 'Carillon LSAP Code Signing', 191 | '1.3.6.1.4.1.25054.3.4.1': 'Carillon CIV Authentication', 192 | '1.3.6.1.4.1.25054.3.4.2': 'Carillon CIV Content Signing', 193 | # Air Canada 194 | '1.3.6.1.4.1.49507.1.10.1': 'Air Canada CIV Card Authentication', 195 | '1.3.6.1.4.1.49507.1.10.2': 'Air Canada CIV Content Signing', 196 | } 197 | 198 | key_usage_display_map = OrderedDict([ 199 | ('digital_signature', 'digitalSignature (0)'), 200 | ('non_repudiation', 'nonRepudiation (1)'), 201 | ('key_encipherment', 'keyEncipherment (2)'), 202 | ('data_encipherment', 'dataEncipherment (3)'), 203 | ('key_agreement', 'keyAgreement (4)'), 204 | ('key_cert_sign', 'keyCertSign (5)'), 205 | ('crl_sign', 'cRLSign (6)'), 206 | ('encipher_only', 'encipherOnly (7)'), 207 | ('decipher_only', 'decipherOnly (8)'), 208 | ]) 209 | 210 | qualifiers_display_map = { 211 | 'certification_practice_statement': 'CPS URI', 212 | 'user_notice': 'User Notice', 213 | 'notice_ref': 'Ref', 214 | 'explicit_text': 'Explicit Text', 215 | } 216 | 217 | crldp_display_map = { 218 | 'full_name': 'Full Name', 219 | 'name_relative_to_crl_issuer': 'Name Relative to Issuer', 220 | } 221 | 222 | 223 | reason_flags_display_map = OrderedDict([ 224 | (0, 'Unspecified (0)'), 225 | (1, 'Key Compromise (1)'), 226 | (2, 'CA Compromise (2)'), 227 | (3, 'Affiliation Changed (3)'), 228 | (4, 'Superseded (4)'), 229 | (5, 'Cessation of Operation (5)'), 230 | (6, 'Certificate Hold (6)'), 231 | (7, 'Privilege Withdrawn (7)'), 232 | (8, 'AA Compromise (8)'), 233 | ]) 234 | 235 | 236 | access_method_display_map = { 237 | 'time_stamping': 'Time STamping', 238 | 'ca_issuers': 'Certification Authority Issuers', 239 | 'ca_repository': 'CA Repository', 240 | 'ocsp': 'On-line Certificate Status Protocol' 241 | } 242 | 243 | public_key_algorithm_display_map = { 244 | # https://tools.ietf.org/html/rfc8017 245 | '1.2.840.113549.1.1.1': 'RSA', 246 | '1.2.840.113549.1.1.7': 'RSAES-OAEP', 247 | '1.2.840.113549.1.1.10': 'RSASSA-PSS', 248 | # https://tools.ietf.org/html/rfc3279#page-18 249 | '1.2.840.10040.4.1': 'DSA', 250 | # https://tools.ietf.org/html/rfc3279#page-13 251 | '1.2.840.10045.2.1': 'EC', 252 | # https://tools.ietf.org/html/rfc3279#page-10 253 | '1.2.840.10046.2.1': 'DH', 254 | } 255 | 256 | map_extension_oid_to_display = { 257 | '2.5.29.9': 'Subject Directory Attributes', 258 | '2.5.29.14': 'Key Identifier', 259 | '2.5.29.15': 'Key Usage', 260 | '2.5.29.16': 'Private Key Usage Period', 261 | '2.5.29.17': 'Subject Alt Name', 262 | '2.5.29.18': 'Issuer Alt Name', 263 | '2.5.29.19': 'Basic Constraints', 264 | '2.5.29.30': 'Name Constraints', 265 | '2.5.29.31': 'CRL Distribution Points', 266 | '2.5.29.32': 'Certificate Policies', 267 | '2.5.29.33': 'Policy Mappings', 268 | '2.5.29.35': 'Authority Key Identifier', 269 | '2.5.29.36': 'Policy Constraints', 270 | '2.5.29.37': 'Extended Key Usage', 271 | '2.5.29.46': 'Freshest CRL', 272 | '2.5.29.54': 'Inhibit Any Policy', 273 | '1.3.6.1.5.5.7.1.1': 'Authority Information Access', 274 | '1.3.6.1.5.5.7.1.11': 'Subject Information Access', 275 | # Https://Tools.Ietf.Org/Html/Rfc7633 276 | '1.3.6.1.5.5.7.1.24': 'TLS Feature', 277 | '1.3.6.1.5.5.7.48.1.5': 'OCSP No Check', 278 | # Entrust 279 | '1.2.840.113533.7.65.0': 'Entrust Version Extension', 280 | '2.16.840.1.114027.30.1': 'Entrust Exportable Private Key', 281 | # Netscape 282 | '2.16.840.1.113730.1.1': 'Netscape Certificate Type', 283 | '2.16.840.1.113730.1.2': 'Netscape Base Url', 284 | '2.16.840.1.113730.1.3': 'Netscape Revocation Url', 285 | '2.16.840.1.113730.1.4': 'Netscape CaRevocation Url', 286 | '2.16.840.1.113730.1.7': 'Netscape Cert Renewal Url', 287 | '2.16.840.1.113730.1.8': 'Netscape CA Policy Url', 288 | '2.16.840.1.113730.1.12': 'Netscape SSL Server Name', 289 | '2.16.840.1.113730.1.13': 'Netscape Comment', 290 | # missing from asn1crypto 291 | '1.3.6.1.4.1.311.21.7': 'Microsoft Certificate Template Information', 292 | # Application Policies extension -- same encoding as szOID_CERT_POLICIES 293 | '1.3.6.1.4.1.311.21.10': 'Microsoft Application Policies', 294 | # Application Policy Mappings -- same encoding as szOID_POLICY_MAPPINGS 295 | '1.3.6.1.4.1.311.21.11': 'Microsoft Application Policy Mappings', 296 | # Application Policy Constraints -- same encoding as szOID_POLICY_CONSTRAINTS 297 | '1.3.6.1.4.1.311.21.12': 'Microsoft Application Policy Constraints', 298 | '1.3.6.1.4.1.311.21.1': 'Microsoft CA Version', 299 | '1.3.6.1.4.1.311.20.2': 'Microsoft Certificate Template Name', 300 | '1.2.840.113549.1.9.15': 'S/Mime Capabilities', 301 | '1.3.6.1.4.1.311.21.2': 'Microsoft Previous CA Cert Hash', 302 | '1.3.6.1.4.1.11129.2.4.2': 'Signed Certificate Timestamp', 303 | '1.3.6.1.4.1.25054.3.6.1': 'Carillon Applicability Extension', # https://pub.carillon.ca/CertificatePolicy.pdf 304 | 305 | '1.3.6.1.4.1.11129.2.4.3': 'CT Pre-Cert Poison Extension', # RFC 6962 306 | 307 | '1.3.6.1.5.5.7.1.3': 'Qualified Certificate Statements', # https://tools.ietf.org/html/rfc3739#section-3.2.6 308 | } 309 | -------------------------------------------------------------------------------- /cpct/fpkilint/html_output.py: -------------------------------------------------------------------------------- 1 | 2 | from fpkilint.profile_conformance import * 3 | from fpkilint.text2html import text_to_html 4 | import json 5 | 6 | # _header = "FieldContentAnalysis" 7 | #_cols = "|:-------- |: -------------------------------------- |:--------------------------------------------------- |\n" 8 | # _all_was_good = "" 9 | _extension_is_critical = "Critical = TRUE
" 10 | 11 | def analyze_certificate(cert, profile_file): 12 | 13 | _add_profile_url = True 14 | _add_profile_string = True 15 | 16 | with open('fpkilint/profiles/' + profile_file) as json_data: 17 | json_profile = json.load(json_data) 18 | 19 | output_rows, other_extensions_rows, profile_info = check_cert_conformance(cert, json_profile) 20 | 21 | cert_type = None 22 | profile_string = None 23 | profile_url = None 24 | short_name = get_short_name_from_cert(cert) 25 | 26 | if profile_info is not None: 27 | if 'cert_type' in profile_info and len(profile_info['cert_type'].value) > 0: 28 | cert_type = profile_info['cert_type'].value 29 | if _add_profile_string and 'name' in profile_info and len(profile_info['name'].value) > 0: 30 | profile_string = profile_info['name'].value 31 | if 'version' in profile_info and len(profile_info['version'].value) > 0: 32 | profile_string += " v" + profile_info['version'].value 33 | if 'date' in profile_info and len(profile_info['date'].value) > 0: 34 | profile_string += " " + profile_info['date'].value 35 | if _add_profile_url and 'more_info_url' in profile_info and len(profile_info['more_info_url'].value) > 0: 36 | profile_url = profile_info['more_info_url'].value 37 | 38 | rows = [] 39 | for i, (key, r) in enumerate(other_extensions_rows.items()): 40 | output_rows[key] = r 41 | 42 | for key, r in output_rows.items(): 43 | name = r.row_name 44 | 45 | if r.extension_is_critical: 46 | content = _extension_is_critical 47 | else: 48 | content = "" 49 | 50 | content += text_to_html(r.content, lint_cert_indent, lint_cert_newline) 51 | 52 | # Analysis 53 | if r.analysis: 54 | analysis = text_to_html(r.analysis, lint_cert_indent, lint_cert_newline) 55 | else: 56 | analysis = None 57 | 58 | rows.append({'name': name, 'content': content, 'analysis': analysis}) 59 | 60 | return rows, cert_type, profile_string, profile_url, short_name 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /cpct/fpkilint/name_utils.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | from asn1crypto import x509 3 | from fpkilint.display_maps import * 4 | import textwrap 5 | import urllib.parse 6 | 7 | from asn1crypto.core import ( 8 | AbstractString, 9 | Any, 10 | BitString, 11 | BMPString, 12 | Boolean, 13 | CharacterString, 14 | Choice, 15 | Concat, 16 | GeneralizedTime, 17 | GeneralString, 18 | GraphicString, 19 | IA5String, 20 | Integer, 21 | Null, 22 | NumericString, 23 | ObjectIdentifier, 24 | OctetBitString, 25 | OctetString, 26 | ParsableOctetString, 27 | PrintableString, 28 | Sequence, 29 | SequenceOf, 30 | Set, 31 | SetOf, 32 | TeletexString, 33 | UniversalString, 34 | UTCTime, 35 | UTF8String, 36 | VisibleString, 37 | VideotexString, 38 | VOID, 39 | ) 40 | 41 | 42 | def is_name_type_in_dn(oid_string, x509_name): 43 | if not isinstance(x509_name, x509.Name): 44 | raise TypeError("name must be an x509.Name") 45 | 46 | rdn_seq = x509_name.chosen 47 | if len(rdn_seq): 48 | for rdn in rdn_seq: 49 | for name in rdn: 50 | if name['type'].dotted == oid_string: 51 | return True 52 | 53 | return False 54 | 55 | 56 | def get_rdn_values_from_dn(oid_string, x509_name): 57 | if not isinstance(x509_name, x509.Name): 58 | raise TypeError("name must be an x509.Name") 59 | 60 | rdn_values = [] 61 | 62 | rdn_seq = x509_name.chosen 63 | if len(rdn_seq): 64 | for rdn in rdn_seq: 65 | for name in rdn: 66 | if name['type'].dotted == oid_string: 67 | rdn_values.append(name) 68 | 69 | return rdn_values 70 | 71 | 72 | def get_pretty_dn_name_component(name_type): 73 | 74 | # name_type = NameType 75 | return dn_name_component_display_map.get(name_type.native, name_type.native) 76 | 77 | 78 | def get_abstract_string_type(abstract_string): 79 | 80 | if isinstance(abstract_string, PrintableString): 81 | string_type = 'Printable' 82 | elif isinstance(abstract_string, UTF8String): 83 | string_type = 'UTF8' 84 | elif isinstance(abstract_string, IA5String): 85 | string_type = 'IA5' 86 | elif isinstance(abstract_string, BMPString): 87 | string_type = 'BMP' 88 | elif isinstance(abstract_string, VisibleString): 89 | string_type = 'Visible' 90 | elif isinstance(abstract_string, TeletexString): 91 | string_type = 'Teletex' 92 | elif isinstance(abstract_string, UniversalString): 93 | string_type = 'Universal' 94 | elif isinstance(abstract_string, GeneralString): 95 | string_type = 'General' 96 | elif isinstance(abstract_string, NumericString): 97 | string_type = 'Numeric' 98 | else: 99 | string_type = abstract_string.__class__.__name__ 100 | print('No case for ' + string_type + ' in get_abstract_string_type') 101 | 102 | return string_type 103 | 104 | 105 | class type_and_value(Sequence): 106 | _fields = [ 107 | ('oid', ObjectIdentifier, {}), 108 | ('value', Any, {}) 109 | ] 110 | 111 | 112 | def get_name_type_and_value_string_type(nameTypeAndValue): 113 | if not isinstance(nameTypeAndValue, x509.NameTypeAndValue): 114 | raise TypeError('Expected asn1crypto.x509.NameTypeAndValue') 115 | 116 | string_type, value = split_name_type_and_value(nameTypeAndValue) 117 | return string_type 118 | 119 | 120 | def split_name_type_and_value(nameTypeAndValue): 121 | if not isinstance(nameTypeAndValue, x509.NameTypeAndValue): 122 | raise TypeError('Expected asn1crypto.x509.NameTypeAndValue') 123 | 124 | # this code side steps any auto correcting that is happening in asn1crypto 125 | # example: auto correcting EmailAddress encoded as printable string to IA5 126 | name_type_and_value = type_and_value.load(nameTypeAndValue.dump()) 127 | value = name_type_and_value['value'].parsed 128 | 129 | if isinstance(value, AbstractString): 130 | return get_abstract_string_type(value), value 131 | else: 132 | warnings.warn('NameTypeAndValue did not contain an AbstractString?') 133 | 134 | return 'Unknown', value 135 | 136 | 137 | # type = Name e.g. subject = tbs_cert['subject'] 138 | def get_pretty_dn(name, rdn_separator=None, type_value_separator=None, include_oid=None, include_string_type=None): 139 | 140 | if not isinstance(name, x509.Name): 141 | raise TypeError("name must be an x509.Name") 142 | 143 | s = "" 144 | if rdn_separator is None: 145 | rdn_separator = ", " 146 | 147 | if type_value_separator is None: 148 | type_value_separator = "=" 149 | 150 | if include_oid is None: 151 | include_oid = False 152 | 153 | if include_string_type is None: 154 | include_string_type = False 155 | 156 | string_type = '' 157 | 158 | rdn_seq = name.chosen # type = RDNSequence 159 | if len(rdn_seq): 160 | rdn_list = list() 161 | for rdn in rdn_seq: 162 | rdn_list.append(rdn) 163 | 164 | rdn_list.reverse() 165 | 166 | for rdn2 in rdn_list: 167 | for name2 in rdn2: 168 | if s: 169 | s += rdn_separator 170 | s += get_pretty_dn_name_component(name2['type']) 171 | if include_oid is True: 172 | s += ' ({})'.format(name2['type']) 173 | 174 | if include_string_type is True: 175 | string_type = '({}) '.format(get_name_type_and_value_string_type(name2)) 176 | 177 | s += '{}{}{}'.format(type_value_separator, string_type, name2.native['value']) 178 | else: 179 | s = "None" 180 | 181 | return s 182 | 183 | 184 | other_name_type_map = { 185 | '1.3.6.1.4.1.311.20.2.3': '_upn', 186 | '2.16.840.1.101.3.6.6': '_piv_fasc_n', 187 | } 188 | 189 | 190 | def get_general_name_string(general_name, multiline=None, indent_string=None, type_separator=None, include_string_type=None, value_only=None): 191 | if multiline is None: 192 | multiline = False 193 | if indent_string is None: 194 | indent_string = ' ' 195 | if type_separator is None: 196 | type_separator = ' = ' 197 | if include_string_type is None: 198 | include_string_type = False 199 | if value_only is None: 200 | value_only = False 201 | 202 | if value_only is False: 203 | general_name_string = "{}: ".format(general_name_display_map.get(general_name.name, "Unknown Name Type")) 204 | else: 205 | general_name_string = '' 206 | 207 | if general_name.name == 'uniform_resource_identifier': 208 | 209 | if general_name.native[0:9] == 'urn:uuid:': 210 | general_name_string += "(UUID) " + general_name.native 211 | else: 212 | general_name_string += urllib.parse.quote(general_name.native, safe="%/:=&?~#+!$,;'@()*[]") 213 | 214 | elif general_name.name == 'directory_name': 215 | 216 | rdn_separator = ", " 217 | 218 | if multiline is True: 219 | general_name_string += '\n' 220 | general_name_string += indent_string 221 | rdn_separator = ",{}{}".format('\n', indent_string) 222 | 223 | general_name_string += get_pretty_dn(general_name.chosen, rdn_separator, type_separator, False, include_string_type) 224 | 225 | elif general_name.name == 'other_name': 226 | other_oid = general_name.chosen['type_id'].dotted 227 | general_name_string += "{}: ".format(other_name_display_map.get(other_oid, other_oid)) 228 | 229 | if isinstance(general_name.native['value'], str): 230 | general_name_string += general_name.native['value'] 231 | elif isinstance(general_name.native['value'], bytes): 232 | general_name_string += get_der_display_string(general_name.native['value'], "", multiline) 233 | else: 234 | general_name_string += get_der_display_string(general_name.chosen.children[1].contents, "DER: ", multiline) 235 | 236 | elif general_name.name == 'dns_name': 237 | general_name_string += general_name.native 238 | else: 239 | if isinstance(general_name.native, str): 240 | general_name_string += general_name.native 241 | elif isinstance(general_name.native, bytes): 242 | general_name_string += get_der_display_string(general_name.native, "Binary:", multiline) 243 | else: 244 | general_name_string += get_der_display_string(general_name.contents, "DER: ", multiline) 245 | 246 | return general_name_string 247 | 248 | 249 | def get_general_name_type(general_name): 250 | general_name_type = general_name.name 251 | 252 | if general_name.name == 'uniform_resource_identifier': 253 | 254 | if general_name.native[0:9] == 'urn:uuid:': 255 | general_name_type += "_chuid" 256 | elif general_name.native[0:7] == 'http://': 257 | general_name_type += "_http" 258 | elif general_name.native[0:7] == 'ldap://': 259 | general_name_type += "_ldap" 260 | elif general_name.native[0:7] == 'https://': 261 | general_name_type += "_https" 262 | elif general_name.native[0:7] == 'ldaps://': 263 | general_name_type += "_ldaps" 264 | 265 | elif general_name.name == 'directory_name': 266 | # nothing 267 | x = 0 268 | elif general_name.name == 'other_name': 269 | other_oid = general_name.chosen['type_id'].dotted 270 | general_name_type += other_name_type_map.get(other_oid, "") 271 | 272 | return general_name_type 273 | 274 | 275 | def get_short_name_from_dn(name): 276 | rdns = [ 277 | 'common_name', 278 | 'name', 279 | 'email_address', 280 | 'given_name', 281 | 'surname', 282 | '0.9.2342.19200300.100.1.1', 283 | 'serial_number', 284 | 'street_address', 285 | 'organizational_unit_name', 286 | 'organization_name', 287 | 'locality_name' 288 | ] 289 | 290 | if len(name.contents) <= 2: 291 | return "NULL" 292 | 293 | for rdn in rdns: 294 | if rdn in name.native: 295 | tmp_name = name.native[rdn] 296 | if isinstance(tmp_name, list): 297 | return tmp_name[len(tmp_name) - 1] 298 | else: 299 | return tmp_name 300 | 301 | return name.native[next(reversed(name.native))] 302 | 303 | 304 | def binary_to_hex_string(byte_value, multi_line=None): 305 | if not isinstance(byte_value, bytes): 306 | return "You must pass in bytes..." 307 | 308 | hex_string = "" 309 | 310 | if multi_line is not True: 311 | hex_string += ''.join('%02X' % c for c in byte_value) 312 | else: 313 | hex_string += textwrap.fill(' '.join('%02X' % c for c in byte_value), 43) 314 | 315 | return hex_string 316 | 317 | 318 | def get_der_display_string(byte_value, preface=None, multi_line=None): 319 | if not isinstance(byte_value, bytes): 320 | return "You must pass in bytes..." 321 | 322 | if preface is None: 323 | der_display_string = "DER: " 324 | else: 325 | der_display_string = preface 326 | 327 | if multi_line is not True: 328 | der_display_string += binary_to_hex_string(byte_value) 329 | else: 330 | der_display_string += '\n' 331 | der_display_string += binary_to_hex_string(byte_value, True) 332 | 333 | return der_display_string 334 | -------------------------------------------------------------------------------- /cpct/fpkilint/profiles/pivi/1.2/pivi-06-signature.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Section": "profile", 4 | "Item": "name", 5 | "Value": "Personal Identity Verification Interoperable (PIV-I)", 6 | "OID": "" 7 | }, 8 | { 9 | "Section": "profile", 10 | "Item": "version", 11 | "Value": "1.2", 12 | "OID": "" 13 | }, 14 | { 15 | "Section": "profile", 16 | "Item": "date", 17 | "Value": "7/17/2017", 18 | "OID": "" 19 | }, 20 | { 21 | "Section": "profile", 22 | "Item": "cert_type", 23 | "Value": "PIV-I Signature", 24 | "OID": "" 25 | }, 26 | { 27 | "Section": "profile", 28 | "Item": "more_info_url", 29 | "Value": "https://www.idmanagement.gov/fpki", 30 | "OID": "" 31 | }, 32 | { 33 | "Section": "signature_algorithm", 34 | "Item": "alg_md2_rsa", 35 | "Value": "1", 36 | "OID": "1.2.840.113549.1.1.2" 37 | }, 38 | { 39 | "Section": "signature_algorithm", 40 | "Item": "alg_md5_rsa", 41 | "Value": "1", 42 | "OID": "1.2.840.113549.1.1.4" 43 | }, 44 | { 45 | "Section": "signature_algorithm", 46 | "Item": "alg_sha1_rsa", 47 | "Value": "1", 48 | "OID": "1.2.840.113549.1.1.5" 49 | }, 50 | { 51 | "Section": "signature_algorithm", 52 | "Item": "alg_rsassa_pss", 53 | "Value": "1", 54 | "OID": "1.2.840.113549.1.1.10" 55 | }, 56 | { 57 | "Section": "signature_algorithm", 58 | "Item": "alg_sha256_rsa", 59 | "Value": "0", 60 | "OID": "1.2.840.113549.1.1.11" 61 | }, 62 | { 63 | "Section": "signature_algorithm", 64 | "Item": "alg_sha384_rsa", 65 | "Value": "0", 66 | "OID": "1.2.840.113549.1.1.12" 67 | }, 68 | { 69 | "Section": "signature_algorithm", 70 | "Item": "alg_sha512_rsa", 71 | "Value": "1", 72 | "OID": "1.2.840.113549.1.1.13" 73 | }, 74 | { 75 | "Section": "signature_algorithm", 76 | "Item": "alg_sha224_rsa", 77 | "Value": "1", 78 | "OID": "1.2.840.113549.1.1.14" 79 | }, 80 | { 81 | "Section": "signature_algorithm", 82 | "Item": "alg_sha1_dsa", 83 | "Value": "1", 84 | "OID": "1.2.840.10040.4.3" 85 | }, 86 | { 87 | "Section": "signature_algorithm", 88 | "Item": "alg_sha1_ec", 89 | "Value": "1", 90 | "OID": "1.2.840.10045.4.1" 91 | }, 92 | { 93 | "Section": "signature_algorithm", 94 | "Item": "alg_sha224_ec", 95 | "Value": "1", 96 | "OID": "1.2.840.10045.4.3.1" 97 | }, 98 | { 99 | "Section": "signature_algorithm", 100 | "Item": "alg_sha256_ec", 101 | "Value": "0", 102 | "OID": "1.2.840.10045.4.3.2" 103 | }, 104 | { 105 | "Section": "signature_algorithm", 106 | "Item": "alg_sha384_ec", 107 | "Value": "0", 108 | "OID": "1.2.840.10045.4.3.3" 109 | }, 110 | { 111 | "Section": "signature_algorithm", 112 | "Item": "alg_sha512_ec", 113 | "Value": "1", 114 | "OID": "1.2.840.10045.4.3.4" 115 | }, 116 | { 117 | "Section": "signature_algorithm", 118 | "Item": "other_algs", 119 | "Value": "1", 120 | "OID": "" 121 | }, 122 | { 123 | "Section": "version", 124 | "Item": "min_version", 125 | "Value": "2", 126 | "OID": "" 127 | }, 128 | { 129 | "Section": "serial_number", 130 | "Item": "min_length", 131 | "Value": "0", 132 | "OID": "" 133 | }, 134 | { 135 | "Section": "serial_number", 136 | "Item": "max_length", 137 | "Value": "0", 138 | "OID": "" 139 | }, 140 | { 141 | "Section": "issuer", 142 | "Item": "base_dn", 143 | "Value": "", 144 | "OID": "" 145 | }, 146 | { 147 | "Section": "issuer", 148 | "Item": "require_geo_political_or_dc", 149 | "Value": "1", 150 | "OID": "" 151 | }, 152 | { 153 | "Section": "issuer", 154 | "Item": "values_country", 155 | "Value": "", 156 | "OID": "2.5.4.6" 157 | }, 158 | { 159 | "Section": "issuer", 160 | "Item": "values_organization", 161 | "Value": "", 162 | "OID": "2.5.4.10" 163 | }, 164 | { 165 | "Section": "issuer", 166 | "Item": "values_organizational_unit", 167 | "Value": "", 168 | "OID": "2.5.4.11" 169 | }, 170 | { 171 | "Section": "issuer", 172 | "Item": "values_distinguished_name_qualifier", 173 | "Value": "", 174 | "OID": "2.5.4.46" 175 | }, 176 | { 177 | "Section": "issuer", 178 | "Item": "rdn_country", 179 | "Value": "0", 180 | "OID": "2.5.4.6" 181 | }, 182 | { 183 | "Section": "issuer", 184 | "Item": "rdn_organization", 185 | "Value": "0", 186 | "OID": "2.5.4.10" 187 | }, 188 | { 189 | "Section": "issuer", 190 | "Item": "rdn_organizational_unit", 191 | "Value": "0", 192 | "OID": "2.5.4.11" 193 | }, 194 | { 195 | "Section": "issuer", 196 | "Item": "rdn_distinguished_name_qualifier", 197 | "Value": "0", 198 | "OID": "2.5.4.46" 199 | }, 200 | { 201 | "Section": "issuer", 202 | "Item": "rdn_state_or_province_name", 203 | "Value": "0", 204 | "OID": "2.5.4.8" 205 | }, 206 | { 207 | "Section": "issuer", 208 | "Item": "rdn_common_name", 209 | "Value": "0", 210 | "OID": "2.5.4.3" 211 | }, 212 | { 213 | "Section": "issuer", 214 | "Item": "rdn_serial_number", 215 | "Value": "0", 216 | "OID": "2.5.4.5" 217 | }, 218 | { 219 | "Section": "issuer", 220 | "Item": "rdn_locality", 221 | "Value": "0", 222 | "OID": "2.5.4.7" 223 | }, 224 | { 225 | "Section": "issuer", 226 | "Item": "rdn_title", 227 | "Value": "0", 228 | "OID": "2.5.4.12" 229 | }, 230 | { 231 | "Section": "issuer", 232 | "Item": "rdn_surname", 233 | "Value": "0", 234 | "OID": "2.5.4.4" 235 | }, 236 | { 237 | "Section": "issuer", 238 | "Item": "rdn_given_name", 239 | "Value": "0", 240 | "OID": "2.5.4.42" 241 | }, 242 | { 243 | "Section": "issuer", 244 | "Item": "rdn_initials", 245 | "Value": "0", 246 | "OID": "2.5.4.43" 247 | }, 248 | { 249 | "Section": "issuer", 250 | "Item": "rdn_pseudonym", 251 | "Value": "0", 252 | "OID": "2.5.4.65" 253 | }, 254 | { 255 | "Section": "issuer", 256 | "Item": "rdn_generation_qualifier", 257 | "Value": "0", 258 | "OID": "2.5.4.44" 259 | }, 260 | { 261 | "Section": "issuer", 262 | "Item": "rdn_street_address", 263 | "Value": "0", 264 | "OID": "2.5.4.9" 265 | }, 266 | { 267 | "Section": "issuer", 268 | "Item": "rdn_business_category", 269 | "Value": "0", 270 | "OID": "2.5.4.15" 271 | }, 272 | { 273 | "Section": "issuer", 274 | "Item": "rdn_postal_code", 275 | "Value": "0", 276 | "OID": "2.5.4.17" 277 | }, 278 | { 279 | "Section": "issuer", 280 | "Item": "rdn_telephone_number", 281 | "Value": "0", 282 | "OID": "2.5.4.20" 283 | }, 284 | { 285 | "Section": "issuer", 286 | "Item": "rdn_organization_identifier", 287 | "Value": "0", 288 | "OID": "2.5.4.97" 289 | }, 290 | { 291 | "Section": "issuer", 292 | "Item": "rdn_unique_identifier", 293 | "Value": "0", 294 | "OID": "2.5.4.45" 295 | }, 296 | { 297 | "Section": "issuer", 298 | "Item": "rdn_userid", 299 | "Value": "0", 300 | "OID": "0.9.2342.19200300.100.1.1" 301 | }, 302 | { 303 | "Section": "validity", 304 | "Item": "validity_period_maximum", 305 | "Value": "1097", 306 | "OID": "" 307 | }, 308 | { 309 | "Section": "validity", 310 | "Item": "validity_period_generalized_time", 311 | "Value": "0", 312 | "OID": "" 313 | }, 314 | { 315 | "Section": "subject", 316 | "Item": "base_dn", 317 | "Value": "", 318 | "OID": "" 319 | }, 320 | { 321 | "Section": "subject", 322 | "Item": "require_geo_political_or_dc", 323 | "Value": "0", 324 | "OID": "" 325 | }, 326 | { 327 | "Section": "subject", 328 | "Item": "permitted_string_types_dir_string", 329 | "Value": "UTF8;Printable", 330 | "OID": "" 331 | }, 332 | { 333 | "Section": "subject", 334 | "Item": "permitted_string_types", 335 | "Value": "", 336 | "OID": "" 337 | }, 338 | { 339 | "Section": "subject", 340 | "Item": "values_country", 341 | "Value": "", 342 | "OID": "2.5.4.6" 343 | }, 344 | { 345 | "Section": "subject", 346 | "Item": "values_organization", 347 | "Value": "", 348 | "OID": "2.5.4.10" 349 | }, 350 | { 351 | "Section": "subject", 352 | "Item": "values_organizational_unit", 353 | "Value": "", 354 | "OID": "2.5.4.11" 355 | }, 356 | { 357 | "Section": "subject", 358 | "Item": "values_distinguished_name_qualifier", 359 | "Value": "", 360 | "OID": "2.5.4.46" 361 | }, 362 | { 363 | "Section": "subject", 364 | "Item": "rdn_country", 365 | "Value": "0", 366 | "OID": "2.5.4.6" 367 | }, 368 | { 369 | "Section": "subject", 370 | "Item": "rdn_organization", 371 | "Value": "0", 372 | "OID": "2.5.4.10" 373 | }, 374 | { 375 | "Section": "subject", 376 | "Item": "rdn_organizational_unit", 377 | "Value": "2", 378 | "OID": "2.5.4.11" 379 | }, 380 | { 381 | "Section": "subject", 382 | "Item": "rdn_distinguished_name_qualifier", 383 | "Value": "0", 384 | "OID": "2.5.4.46" 385 | }, 386 | { 387 | "Section": "subject", 388 | "Item": "rdn_state_or_province_name", 389 | "Value": "0", 390 | "OID": "2.5.4.8" 391 | }, 392 | { 393 | "Section": "subject", 394 | "Item": "rdn_common_name", 395 | "Value": "2", 396 | "OID": "2.5.4.3" 397 | }, 398 | { 399 | "Section": "subject", 400 | "Item": "rdn_serial_number", 401 | "Value": "0", 402 | "OID": "2.5.4.5" 403 | }, 404 | { 405 | "Section": "subject", 406 | "Item": "rdn_locality", 407 | "Value": "0", 408 | "OID": "2.5.4.7" 409 | }, 410 | { 411 | "Section": "subject", 412 | "Item": "rdn_title", 413 | "Value": "0", 414 | "OID": "2.5.4.12" 415 | }, 416 | { 417 | "Section": "subject", 418 | "Item": "rdn_surname", 419 | "Value": "0", 420 | "OID": "2.5.4.4" 421 | }, 422 | { 423 | "Section": "subject", 424 | "Item": "rdn_given_name", 425 | "Value": "0", 426 | "OID": "2.5.4.42" 427 | }, 428 | { 429 | "Section": "subject", 430 | "Item": "rdn_initials", 431 | "Value": "0", 432 | "OID": "2.5.4.43" 433 | }, 434 | { 435 | "Section": "subject", 436 | "Item": "rdn_pseudonym", 437 | "Value": "0", 438 | "OID": "2.5.4.65" 439 | }, 440 | { 441 | "Section": "subject", 442 | "Item": "rdn_generation_qualifier", 443 | "Value": "0", 444 | "OID": "2.5.4.44" 445 | }, 446 | { 447 | "Section": "subject", 448 | "Item": "rdn_street_address", 449 | "Value": "0", 450 | "OID": "2.5.4.9" 451 | }, 452 | { 453 | "Section": "subject", 454 | "Item": "rdn_business_category", 455 | "Value": "0", 456 | "OID": "2.5.4.15" 457 | }, 458 | { 459 | "Section": "subject", 460 | "Item": "rdn_postal_code", 461 | "Value": "0", 462 | "OID": "2.5.4.17" 463 | }, 464 | { 465 | "Section": "subject", 466 | "Item": "rdn_telephone_number", 467 | "Value": "0", 468 | "OID": "2.5.4.20" 469 | }, 470 | { 471 | "Section": "subject", 472 | "Item": "rdn_organization_identifier", 473 | "Value": "0", 474 | "OID": "2.5.4.97" 475 | }, 476 | { 477 | "Section": "subject", 478 | "Item": "rdn_unique_identifier", 479 | "Value": "0", 480 | "OID": "2.5.4.45" 481 | }, 482 | { 483 | "Section": "subject", 484 | "Item": "rdn_userid", 485 | "Value": "0", 486 | "OID": "0.9.2342.19200300.100.1.1" 487 | }, 488 | { 489 | "Section": "subject_public_key_info", 490 | "Item": "alg_rsa", 491 | "Value": "0", 492 | "OID": "1.2.840.113549.1.1.1" 493 | }, 494 | { 495 | "Section": "subject_public_key_info", 496 | "Item": "alg_ec", 497 | "Value": "0", 498 | "OID": "1.2.840.10045.2.1" 499 | }, 500 | { 501 | "Section": "subject_public_key_info", 502 | "Item": "alg_ec_named_curve", 503 | "Value": "1.2.840.10045.3.1.7 1.3.132.0.34", 504 | "OID": "" 505 | }, 506 | { 507 | "Section": "subject_public_key_info", 508 | "Item": "alg_dsa", 509 | "Value": "1", 510 | "OID": "1.2.840.10040.4.1" 511 | }, 512 | { 513 | "Section": "subject_public_key_info", 514 | "Item": "rsa_min_size", 515 | "Value": "2048", 516 | "OID": "" 517 | }, 518 | { 519 | "Section": "subject_public_key_info", 520 | "Item": "rsa_max_size", 521 | "Value": "2048", 522 | "OID": "" 523 | }, 524 | { 525 | "Section": "subject_public_key_info", 526 | "Item": "ec_min_size", 527 | "Value": "0", 528 | "OID": "" 529 | }, 530 | { 531 | "Section": "subject_public_key_info", 532 | "Item": "ec_max_size", 533 | "Value": "0", 534 | "OID": "" 535 | }, 536 | { 537 | "Section": "akid", 538 | "Item": "present", 539 | "Value": "2", 540 | "OID": "2.5.29.35" 541 | }, 542 | { 543 | "Section": "akid", 544 | "Item": "is_critical", 545 | "Value": "1", 546 | "OID": "" 547 | }, 548 | { 549 | "Section": "akid", 550 | "Item": "key_id", 551 | "Value": "2", 552 | "OID": "" 553 | }, 554 | { 555 | "Section": "akid", 556 | "Item": "name_and_serial", 557 | "Value": "1", 558 | "OID": "" 559 | }, 560 | { 561 | "Section": "skid", 562 | "Item": "present", 563 | "Value": "2", 564 | "OID": "2.5.29.14" 565 | }, 566 | { 567 | "Section": "skid", 568 | "Item": "is_critical", 569 | "Value": "1", 570 | "OID": "" 571 | }, 572 | { 573 | "Section": "skid", 574 | "Item": "require_method_one", 575 | "Value": "0", 576 | "OID": "" 577 | }, 578 | { 579 | "Section": "key_usage", 580 | "Item": "present", 581 | "Value": "2", 582 | "OID": "2.5.29.15" 583 | }, 584 | { 585 | "Section": "key_usage", 586 | "Item": "is_critical", 587 | "Value": "2", 588 | "OID": "" 589 | }, 590 | { 591 | "Section": "key_usage", 592 | "Item": "digital_signature", 593 | "Value": "2", 594 | "OID": "" 595 | }, 596 | { 597 | "Section": "key_usage", 598 | "Item": "non_repudiation", 599 | "Value": "2", 600 | "OID": "" 601 | }, 602 | { 603 | "Section": "key_usage", 604 | "Item": "key_encipherment", 605 | "Value": "1", 606 | "OID": "" 607 | }, 608 | { 609 | "Section": "key_usage", 610 | "Item": "data_encipherment", 611 | "Value": "1", 612 | "OID": "" 613 | }, 614 | { 615 | "Section": "key_usage", 616 | "Item": "key_agreement", 617 | "Value": "1", 618 | "OID": "" 619 | }, 620 | { 621 | "Section": "key_usage", 622 | "Item": "key_cert_sign", 623 | "Value": "1", 624 | "OID": "" 625 | }, 626 | { 627 | "Section": "key_usage", 628 | "Item": "crl_sign", 629 | "Value": "1", 630 | "OID": "" 631 | }, 632 | { 633 | "Section": "key_usage", 634 | "Item": "encipher_only", 635 | "Value": "1", 636 | "OID": "" 637 | }, 638 | { 639 | "Section": "key_usage", 640 | "Item": "decipher_only", 641 | "Value": "1", 642 | "OID": "" 643 | }, 644 | { 645 | "Section": "crldp", 646 | "Item": "present", 647 | "Value": "2", 648 | "OID": "2.5.29.31" 649 | }, 650 | { 651 | "Section": "crldp", 652 | "Item": "is_critical", 653 | "Value": "1", 654 | "OID": "" 655 | }, 656 | { 657 | "Section": "crldp", 658 | "Item": "http", 659 | "Value": "2", 660 | "OID": "" 661 | }, 662 | { 663 | "Section": "crldp", 664 | "Item": "ldap", 665 | "Value": "0", 666 | "OID": "" 667 | }, 668 | { 669 | "Section": "crldp", 670 | "Item": "http_before_ldap", 671 | "Value": "0", 672 | "OID": "" 673 | }, 674 | { 675 | "Section": "crldp", 676 | "Item": "directory_name", 677 | "Value": "0", 678 | "OID": "" 679 | }, 680 | { 681 | "Section": "crldp", 682 | "Item": "crl_reasons", 683 | "Value": "1", 684 | "OID": "" 685 | }, 686 | { 687 | "Section": "aia", 688 | "Item": "present", 689 | "Value": "2", 690 | "OID": "1.3.6.1.5.5.7.1.1" 691 | }, 692 | { 693 | "Section": "aia", 694 | "Item": "is_critical", 695 | "Value": "1", 696 | "OID": "" 697 | }, 698 | { 699 | "Section": "aia", 700 | "Item": "ca_issuers_present", 701 | "Value": "2", 702 | "OID": "1.3.6.1.5.5.7.48.2" 703 | }, 704 | { 705 | "Section": "aia", 706 | "Item": "ca_issuers_http", 707 | "Value": "2", 708 | "OID": "" 709 | }, 710 | { 711 | "Section": "aia", 712 | "Item": "ca_issuers_ldap", 713 | "Value": "0", 714 | "OID": "" 715 | }, 716 | { 717 | "Section": "aia", 718 | "Item": "ca_issuers_http_before_ldap", 719 | "Value": "0", 720 | "OID": "" 721 | }, 722 | { 723 | "Section": "aia", 724 | "Item": "ca_issuers_directory_name", 725 | "Value": "0", 726 | "OID": "" 727 | }, 728 | { 729 | "Section": "aia", 730 | "Item": "ca_issuers_https", 731 | "Value": "1", 732 | "OID": "" 733 | }, 734 | { 735 | "Section": "aia", 736 | "Item": "ca_issuers_ldaps", 737 | "Value": "1", 738 | "OID": "" 739 | }, 740 | { 741 | "Section": "aia", 742 | "Item": "ca_issuers_http_p7c", 743 | "Value": "2", 744 | "OID": "" 745 | }, 746 | { 747 | "Section": "aia", 748 | "Item": "ocsp_present", 749 | "Value": "2", 750 | "OID": "1.3.6.1.5.5.7.48.1" 751 | }, 752 | { 753 | "Section": "aia", 754 | "Item": "ocsp_https", 755 | "Value": "0", 756 | "OID": "" 757 | }, 758 | { 759 | "Section": "sia", 760 | "Item": "present", 761 | "Value": "1", 762 | "OID": "1.3.6.1.5.5.7.1.11" 763 | }, 764 | { 765 | "Section": "sia", 766 | "Item": "is_critical", 767 | "Value": "0", 768 | "OID": "" 769 | }, 770 | { 771 | "Section": "sia", 772 | "Item": "ca_repository_present", 773 | "Value": "0", 774 | "OID": "1.3.6.1.5.5.7.48.5" 775 | }, 776 | { 777 | "Section": "sia", 778 | "Item": "ca_repository_http", 779 | "Value": "0", 780 | "OID": "" 781 | }, 782 | { 783 | "Section": "sia", 784 | "Item": "ca_repository_ldap", 785 | "Value": "0", 786 | "OID": "" 787 | }, 788 | { 789 | "Section": "sia", 790 | "Item": "ca_repository_http_before_ldap", 791 | "Value": "0", 792 | "OID": "" 793 | }, 794 | { 795 | "Section": "sia", 796 | "Item": "ca_repository_directory_name", 797 | "Value": "0", 798 | "OID": "" 799 | }, 800 | { 801 | "Section": "sia", 802 | "Item": "ca_repository_https", 803 | "Value": "1", 804 | "OID": "" 805 | }, 806 | { 807 | "Section": "sia", 808 | "Item": "ca_repository_ldaps", 809 | "Value": "1", 810 | "OID": "" 811 | }, 812 | { 813 | "Section": "sia", 814 | "Item": "ca_repository_http_p7c", 815 | "Value": "0", 816 | "OID": "" 817 | }, 818 | { 819 | "Section": "sia", 820 | "Item": "time_stamping_present", 821 | "Value": "0", 822 | "OID": "" 823 | }, 824 | { 825 | "Section": "cert_policies", 826 | "Item": "present", 827 | "Value": "2", 828 | "OID": "2.5.29.32" 829 | }, 830 | { 831 | "Section": "cert_policies", 832 | "Item": "is_critical", 833 | "Value": "1", 834 | "OID": "" 835 | }, 836 | { 837 | "Section": "cert_policies", 838 | "Item": "required_policy_list", 839 | "Value": "", 840 | "OID": "" 841 | }, 842 | { 843 | "Section": "cert_policies", 844 | "Item": "match_mode", 845 | "Value": "any", 846 | "OID": "" 847 | }, 848 | { 849 | "Section": "cert_policies", 850 | "Item": "permit_others", 851 | "Value": "0", 852 | "OID": "" 853 | }, 854 | { 855 | "Section": "policy_mappings", 856 | "Item": "present", 857 | "Value": "1", 858 | "OID": "2.5.29.33" 859 | }, 860 | { 861 | "Section": "policy_mappings", 862 | "Item": "is_critical", 863 | "Value": "0", 864 | "OID": "" 865 | }, 866 | { 867 | "Section": "policy_mappings", 868 | "Item": "permitted", 869 | "Value": "", 870 | "OID": "" 871 | }, 872 | { 873 | "Section": "policy_mappings", 874 | "Item": "excluded", 875 | "Value": "", 876 | "OID": "" 877 | }, 878 | { 879 | "Section": "san", 880 | "Item": "present", 881 | "Value": "0", 882 | "OID": "2.5.29.17" 883 | }, 884 | { 885 | "Section": "san", 886 | "Item": "is_critical", 887 | "Value": "1", 888 | "OID": "" 889 | }, 890 | { 891 | "Section": "san", 892 | "Item": "other_name", 893 | "Value": "0", 894 | "OID": "" 895 | }, 896 | { 897 | "Section": "san", 898 | "Item": "rfc822_name", 899 | "Value": "0", 900 | "OID": "" 901 | }, 902 | { 903 | "Section": "san", 904 | "Item": "dns_name", 905 | "Value": "1", 906 | "OID": "" 907 | }, 908 | { 909 | "Section": "san", 910 | "Item": "x400_address", 911 | "Value": "0", 912 | "OID": "" 913 | }, 914 | { 915 | "Section": "san", 916 | "Item": "directory_name", 917 | "Value": "0", 918 | "OID": "" 919 | }, 920 | { 921 | "Section": "san", 922 | "Item": "edi_party_name", 923 | "Value": "0", 924 | "OID": "" 925 | }, 926 | { 927 | "Section": "san", 928 | "Item": "uniform_resource_identifier", 929 | "Value": "0", 930 | "OID": "" 931 | }, 932 | { 933 | "Section": "san", 934 | "Item": "ip_address", 935 | "Value": "1", 936 | "OID": "" 937 | }, 938 | { 939 | "Section": "san", 940 | "Item": "registered_id", 941 | "Value": "0", 942 | "OID": "" 943 | }, 944 | { 945 | "Section": "san", 946 | "Item": "other_name_upn", 947 | "Value": "0", 948 | "OID": "1.3.6.1.4.1.311.20.2.3" 949 | }, 950 | { 951 | "Section": "san", 952 | "Item": "other_name_piv_fasc_n", 953 | "Value": "0", 954 | "OID": "2.16.840.1.101.3.6.6" 955 | }, 956 | { 957 | "Section": "san", 958 | "Item": "uniform_resource_identifier_chuid", 959 | "Value": "0", 960 | "OID": "" 961 | }, 962 | { 963 | "Section": "ian", 964 | "Item": "present", 965 | "Value": "0", 966 | "OID": "2.5.29.18" 967 | }, 968 | { 969 | "Section": "ian", 970 | "Item": "is_critical", 971 | "Value": "1", 972 | "OID": "" 973 | }, 974 | { 975 | "Section": "ian", 976 | "Item": "other_name", 977 | "Value": "0", 978 | "OID": "" 979 | }, 980 | { 981 | "Section": "ian", 982 | "Item": "rfc822_name", 983 | "Value": "0", 984 | "OID": "" 985 | }, 986 | { 987 | "Section": "ian", 988 | "Item": "dns_name", 989 | "Value": "0", 990 | "OID": "" 991 | }, 992 | { 993 | "Section": "ian", 994 | "Item": "x400_address", 995 | "Value": "0", 996 | "OID": "" 997 | }, 998 | { 999 | "Section": "ian", 1000 | "Item": "directory_name", 1001 | "Value": "0", 1002 | "OID": "" 1003 | }, 1004 | { 1005 | "Section": "ian", 1006 | "Item": "edi_party_name", 1007 | "Value": "0", 1008 | "OID": "" 1009 | }, 1010 | { 1011 | "Section": "ian", 1012 | "Item": "uniform_resource_identifier", 1013 | "Value": "0", 1014 | "OID": "" 1015 | }, 1016 | { 1017 | "Section": "ian", 1018 | "Item": "ip_address", 1019 | "Value": "0", 1020 | "OID": "" 1021 | }, 1022 | { 1023 | "Section": "ian", 1024 | "Item": "registered_id", 1025 | "Value": "0", 1026 | "OID": "" 1027 | }, 1028 | { 1029 | "Section": "ian", 1030 | "Item": "other_name_upn", 1031 | "Value": "0", 1032 | "OID": "1.3.6.1.4.1.311.20.2.3" 1033 | }, 1034 | { 1035 | "Section": "ian", 1036 | "Item": "other_name_piv_fasc_n", 1037 | "Value": "0", 1038 | "OID": "2.16.840.1.101.3.6.6" 1039 | }, 1040 | { 1041 | "Section": "ian", 1042 | "Item": "uniform_resource_identifier_chuid", 1043 | "Value": "0", 1044 | "OID": "" 1045 | }, 1046 | { 1047 | "Section": "sub_dir_attr", 1048 | "Item": "present", 1049 | "Value": "0", 1050 | "OID": "2.5.29.9" 1051 | }, 1052 | { 1053 | "Section": "sub_dir_attr", 1054 | "Item": "is_critical", 1055 | "Value": "1", 1056 | "OID": "" 1057 | }, 1058 | { 1059 | "Section": "basic_constraints", 1060 | "Item": "present", 1061 | "Value": "0", 1062 | "OID": "2.5.29.19" 1063 | }, 1064 | { 1065 | "Section": "basic_constraints", 1066 | "Item": "is_critical", 1067 | "Value": "0", 1068 | "OID": "" 1069 | }, 1070 | { 1071 | "Section": "basic_constraints", 1072 | "Item": "ca_true", 1073 | "Value": "1", 1074 | "OID": "" 1075 | }, 1076 | { 1077 | "Section": "basic_constraints", 1078 | "Item": "path_length_constraint_req", 1079 | "Value": "0", 1080 | "OID": "" 1081 | }, 1082 | { 1083 | "Section": "basic_constraints", 1084 | "Item": "path_length_constraint_max", 1085 | "Value": "99", 1086 | "OID": "" 1087 | }, 1088 | { 1089 | "Section": "name_constraints", 1090 | "Item": "present", 1091 | "Value": "1", 1092 | "OID": "2.5.29.30" 1093 | }, 1094 | { 1095 | "Section": "name_constraints", 1096 | "Item": "is_critical", 1097 | "Value": "0", 1098 | "OID": "" 1099 | }, 1100 | { 1101 | "Section": "name_constraints", 1102 | "Item": "permitted", 1103 | "Value": "0", 1104 | "OID": "" 1105 | }, 1106 | { 1107 | "Section": "name_constraints", 1108 | "Item": "excluded", 1109 | "Value": "0", 1110 | "OID": "" 1111 | }, 1112 | { 1113 | "Section": "policy_constraints", 1114 | "Item": "present", 1115 | "Value": "1", 1116 | "OID": "2.5.29.36" 1117 | }, 1118 | { 1119 | "Section": "policy_constraints", 1120 | "Item": "is_critical", 1121 | "Value": "0", 1122 | "OID": "" 1123 | }, 1124 | { 1125 | "Section": "policy_constraints", 1126 | "Item": "require_explicit_policy_present", 1127 | "Value": "0", 1128 | "OID": "" 1129 | }, 1130 | { 1131 | "Section": "policy_constraints", 1132 | "Item": "require_explicit_policy_max", 1133 | "Value": "99", 1134 | "OID": "" 1135 | }, 1136 | { 1137 | "Section": "policy_constraints", 1138 | "Item": "inhibit_policy_mapping_present", 1139 | "Value": "0", 1140 | "OID": "" 1141 | }, 1142 | { 1143 | "Section": "policy_constraints", 1144 | "Item": "inhibit_policy_mapping_max", 1145 | "Value": "99", 1146 | "OID": "" 1147 | }, 1148 | { 1149 | "Section": "inhibit_any", 1150 | "Item": "present", 1151 | "Value": "1", 1152 | "OID": "2.5.29.54" 1153 | }, 1154 | { 1155 | "Section": "inhibit_any", 1156 | "Item": "is_critical", 1157 | "Value": "0", 1158 | "OID": "" 1159 | }, 1160 | { 1161 | "Section": "piv_naci", 1162 | "Item": "present", 1163 | "Value": "1", 1164 | "OID": "2.16.840.1.101.3.6.9.1" 1165 | }, 1166 | { 1167 | "Section": "piv_naci", 1168 | "Item": "is_critical", 1169 | "Value": "0", 1170 | "OID": "" 1171 | }, 1172 | { 1173 | "Section": "ocsp_nocheck", 1174 | "Item": "present", 1175 | "Value": "1", 1176 | "OID": "1.3.6.1.5.5.7.48.1.5" 1177 | }, 1178 | { 1179 | "Section": "ocsp_nocheck", 1180 | "Item": "is_critical", 1181 | "Value": "0", 1182 | "OID": "" 1183 | }, 1184 | { 1185 | "Section": "eku", 1186 | "Item": "present", 1187 | "Value": "0", 1188 | "OID": "2.5.29.37" 1189 | }, 1190 | { 1191 | "Section": "eku", 1192 | "Item": "is_critical", 1193 | "Value": "0", 1194 | "OID": "" 1195 | }, 1196 | { 1197 | "Section": "eku", 1198 | "Item": "oid_server_auth", 1199 | "Value": "1", 1200 | "OID": "1.3.6.1.5.5.7.3.1" 1201 | }, 1202 | { 1203 | "Section": "eku", 1204 | "Item": "oid_client_auth", 1205 | "Value": "1", 1206 | "OID": "1.3.6.1.5.5.7.3.2" 1207 | }, 1208 | { 1209 | "Section": "eku", 1210 | "Item": "oid_code_signing", 1211 | "Value": "1", 1212 | "OID": "1.3.6.1.5.5.7.3.3" 1213 | }, 1214 | { 1215 | "Section": "eku", 1216 | "Item": "oid_email_protection", 1217 | "Value": "0", 1218 | "OID": "1.3.6.1.5.5.7.3.4" 1219 | }, 1220 | { 1221 | "Section": "eku", 1222 | "Item": "oid_time_stamping", 1223 | "Value": "1", 1224 | "OID": "1.3.6.1.5.5.7.3.8" 1225 | }, 1226 | { 1227 | "Section": "eku", 1228 | "Item": "oid_ocsp_signing", 1229 | "Value": "1", 1230 | "OID": "1.3.6.1.5.5.7.3.9" 1231 | }, 1232 | { 1233 | "Section": "eku", 1234 | "Item": "oid_any_eku", 1235 | "Value": "0", 1236 | "OID": "2.5.29.37.0" 1237 | }, 1238 | { 1239 | "Section": "eku", 1240 | "Item": "oid_smart_card_logon", 1241 | "Value": "1", 1242 | "OID": "1.3.6.1.4.1.311.20.2.2" 1243 | }, 1244 | { 1245 | "Section": "eku", 1246 | "Item": "oid_ipsec_ike_intermediate", 1247 | "Value": "1", 1248 | "OID": "1.3.6.1.5.5.8.2.2" 1249 | }, 1250 | { 1251 | "Section": "eku", 1252 | "Item": "oid_ipsec_end_system", 1253 | "Value": "1", 1254 | "OID": "1.3.6.1.5.5.7.3.5" 1255 | }, 1256 | { 1257 | "Section": "eku", 1258 | "Item": "oid_ipsec_tunnel_termination", 1259 | "Value": "1", 1260 | "OID": "1.3.6.1.5.5.7.3.6" 1261 | }, 1262 | { 1263 | "Section": "eku", 1264 | "Item": "oid_ipsec_user", 1265 | "Value": "1", 1266 | "OID": "1.3.6.1.5.5.7.3.7" 1267 | }, 1268 | { 1269 | "Section": "eku", 1270 | "Item": "oid_piv_card_auth", 1271 | "Value": "1", 1272 | "OID": "2.16.840.1.101.3.6.8" 1273 | }, 1274 | { 1275 | "Section": "eku", 1276 | "Item": "oid_pivi_content_signing", 1277 | "Value": "1", 1278 | "OID": "2.16.840.1.101.3.8.7" 1279 | }, 1280 | { 1281 | "Section": "eku", 1282 | "Item": "oid_pkinit_KPKdc", 1283 | "Value": "1", 1284 | "OID": "1.3.6.1.5.2.3.5" 1285 | }, 1286 | { 1287 | "Section": "eku", 1288 | "Item": "oid_pkinit_KPClientAuth", 1289 | "Value": "1", 1290 | "OID": "1.3.6.1.5.2.3.4" 1291 | }, 1292 | { 1293 | "Section": "eku", 1294 | "Item": "oid_msft_document_signing", 1295 | "Value": "0", 1296 | "OID": "1.3.6.1.4.1.311.10.3.12" 1297 | }, 1298 | { 1299 | "Section": "eku", 1300 | "Item": "oid_adobe_document_signing", 1301 | "Value": "0", 1302 | "OID": "1.2.840.113583.1.1.5" 1303 | }, 1304 | { 1305 | "Section": "eku", 1306 | "Item": "oid_msft_efs", 1307 | "Value": "1", 1308 | "OID": "1.3.6.1.4.1.311.10.3.4" 1309 | }, 1310 | { 1311 | "Section": "eku", 1312 | "Item": "oid_life_time_signing", 1313 | "Value": "1", 1314 | "OID": "1.3.6.1.4.1.311.10.3.13" 1315 | }, 1316 | { 1317 | "Section": "eku", 1318 | "Item": "other", 1319 | "Value": "0", 1320 | "OID": "" 1321 | }, 1322 | { 1323 | "Section": "pkup", 1324 | "Item": "present", 1325 | "Value": "0", 1326 | "OID": "2.5.29.16" 1327 | }, 1328 | { 1329 | "Section": "pkup", 1330 | "Item": "is_critical", 1331 | "Value": "1", 1332 | "OID": "" 1333 | }, 1334 | { 1335 | "Section": "other_extensions", 1336 | "Item": "other_non_critical_extensions_present", 1337 | "Value": "0", 1338 | "OID": "" 1339 | }, 1340 | { 1341 | "Section": "other_extensions", 1342 | "Item": "other_critical_extensions_present", 1343 | "Value": "1", 1344 | "OID": "" 1345 | } 1346 | ] 1347 | -------------------------------------------------------------------------------- /cpct/fpkilint/strapdown_output.py: -------------------------------------------------------------------------------- 1 | from fpkilint.profile_conformance import * 2 | from fpkilint.text2html import text_to_html 3 | import json 4 | 5 | _header = "\n| **Field** | **Content** | **Analysis** |\n" 6 | _cols = "| :-------- | :-------------------------------------- | :--------------------------------------------------- |\n" 7 | _all_was_good = "OK" 8 | _extension_is_critical = "Critical = TRUE
" 9 | 10 | 11 | def process_add_certificate(cert, profile_file, output_file): 12 | # could make these default params if desired 13 | _add_profile_url = False 14 | _add_profile_string = False 15 | 16 | with open(profile_file) as json_data: 17 | json_profile = json.load(json_data) 18 | 19 | output_rows, other_extensions_rows, profile_info = check_cert_conformance(cert, json_profile) 20 | 21 | output_file.write("\n
\n") 22 | 23 | cert_type = None 24 | profile_string = None 25 | profile_url = None 26 | 27 | if profile_info is not None: 28 | if 'cert_type' in profile_info and len(profile_info['cert_type'].value) > 0: 29 | cert_type = profile_info['cert_type'].value 30 | if _add_profile_string and 'name' in profile_info and len(profile_info['name'].value) > 0: 31 | profile_string = profile_info['name'].value 32 | if 'version' in profile_info and len(profile_info['version'].value) > 0: 33 | profile_string += " v" + profile_info['version'].value 34 | if 'date' in profile_info and len(profile_info['date'].value) > 0: 35 | profile_string += " " + profile_info['date'].value 36 | if _add_profile_url and 'more_info_url' in profile_info and len(profile_info['more_info_url'].value) > 0: 37 | profile_url = profile_info['more_info_url'].value 38 | 39 | if cert_type is not None: 40 | output_file.write("\n## {}".format(cert_type)) 41 | 42 | if profile_string is not None: 43 | output_file.write("\n##### {}".format(profile_string)) 44 | 45 | if profile_url is not None: 46 | output_file.write("\n{}".format(profile_url, profile_url)) 47 | 48 | output_file.write("\n### {}\n".format(get_short_name_from_cert(cert))) 49 | output_file.write(_header) 50 | output_file.write(_cols) 51 | 52 | for i, (key, r) in enumerate(other_extensions_rows.items()): 53 | output_rows[key] = r 54 | 55 | for i, (key, r) in enumerate(output_rows.items()): 56 | 57 | # Field 58 | output_file.write("| **{}** ".format(r.row_name)) 59 | 60 | # Content 61 | output_file.write("| ") 62 | if r.extension_is_critical: 63 | output_file.write(_extension_is_critical) 64 | output_file.write(text_to_html(r.content, lint_cert_indent, lint_cert_newline)) 65 | 66 | # Analysis 67 | if r.analysis == "": 68 | output_file.write(" | {} |\n".format(_all_was_good)) 69 | else: 70 | output_file.write(" | {} |\n".format(text_to_html(r.analysis, lint_cert_indent, lint_cert_newline))) 71 | 72 | # amelia 73 | # bootstrap 74 | # bootstrap-responsive 75 | # cerulean 76 | # cyborg 77 | # journal 78 | # readable 79 | # simplex 80 | # slate 81 | # spacelab 82 | # spruce 83 | # superhero 84 | # united 85 | 86 | _strap_start = "\n\n{}\n" 87 | _strap_end = "\n\n\n\n" 88 | 89 | def process_one_certificate(cert, profile_file, output_file_name, document_title): 90 | 91 | with open(output_file_name, 'w') as output_file: 92 | output_file.write(_strap_start.format(document_title)) 93 | process_add_certificate(cert, profile_file, output_file) 94 | output_file.write(_strap_end) 95 | 96 | 97 | # example input list 98 | # filename, profile 99 | # piv_test_certs = [ 100 | # ["testcerts/piv/cardauth.cer", 'PIV_Card_Authentication'], 101 | # ["testcerts/piv/content_signing.cer", 'PIV_Content_Signer'], 102 | # ["testcerts/piv/pivauth.cer", "PIV_Identity"], 103 | # ] 104 | 105 | 106 | def process_certificate_list(list_of_certs, output_file_name, doc_title): 107 | # strap_start = "\n\n{}\n" 108 | # strap_end = "\n\n\n\n" 109 | 110 | with open(output_file_name, 'w') as output_file: 111 | output_file.write(_strap_start.format(doc_title)) 112 | 113 | for file_name, profile in list_of_certs: 114 | print(file_name) 115 | if profile == "": 116 | profile = "template" 117 | with open(file_name, 'rb') as cert_file: 118 | encoded = cert_file.read() 119 | cert = parse_certificate(encoded) 120 | if cert is None: 121 | print('Failed to parse {}'.format(file_name)) 122 | else: 123 | # output_file.write("\n
" + file_name + "
\n") 124 | # output_file.write(binary_to_hex_string(cert.sha1)) 125 | process_add_certificate(cert, profile, output_file) 126 | 127 | output_file.write(_strap_end) 128 | 129 | -------------------------------------------------------------------------------- /cpct/fpkilint/text2html.py: -------------------------------------------------------------------------------- 1 | import re 2 | import textwrap 3 | # from fpkilint.profile_conformance import * 4 | 5 | url_regex = re.compile(r"(?:http|ftp|ldap)s?://[A-Za-z0-9\-._~:/?#[\]@!$&'()*+,;%=]+(?": ">", 16 | "<": "<", 17 | } 18 | 19 | markdown_escape_table = { 20 | "`": "'", # "`", 21 | "'": "'", 22 | "|": "|", 23 | "*": "*", 24 | } 25 | 26 | printable_characters_to_break = [':', '.', '=', '+', ')', '\\'] 27 | 28 | 29 | def escape_text(text, escape_table): 30 | return "".join(escape_table.get(c, c) for c in text) 31 | 32 | 33 | def text_to_html(text_string, text_indent=None, text_new_line=None): 34 | 35 | if not text_indent: 36 | text_indent = ' ' 37 | if not text_new_line: 38 | text_new_line = '\n' 39 | 40 | html_new_line = '
' 41 | html_indent = '    ' 42 | 43 | text_string = text_string.replace("\r", "") 44 | 45 | uris_to_replace = [] 46 | for uri_match in url_regex.finditer(text_string): 47 | if uri_match.group(0).strip() not in uris_to_replace: 48 | uris_to_replace.append(uri_match.group(0).strip()) 49 | 50 | for n, uri in enumerate(uris_to_replace): 51 | text_string = text_string.replace(uri, '\r' + str(n) + '\r') 52 | 53 | text_string = escape_text(text_string, html_escape_table) 54 | 55 | # this could match urls so it must in this spot 56 | printable_strings_to_break = big_printable_string_sans_space_regex.findall(text_string) 57 | for printable_str in printable_strings_to_break: 58 | for c in printable_characters_to_break: 59 | new_str = printable_str.replace(c, c + '') 60 | text_string = text_string.replace(printable_str, new_str) 61 | 62 | hex_strings = long_hex_string.findall(text_string) 63 | for hex_string in hex_strings: 64 | new_hex_string = ''.join(textwrap.wrap(hex_string, 8)) 65 | text_string = text_string.replace(hex_string, new_hex_string) 66 | 67 | for n, uri in enumerate(uris_to_replace): 68 | display_uri = uri 69 | display_uri = display_uri.replace("/", "/") 70 | display_uri = display_uri.replace(",", ",") 71 | display_uri = display_uri.replace("%20", " ") 72 | display_uri = "{}".format(uri, display_uri) 73 | text_string = text_string.replace('\r' + str(n) + '\r', display_uri) 74 | 75 | strings_to_bold = bold_regex.findall(text_string) 76 | for string_to_bold in strings_to_bold: 77 | text_string = text_string.replace(string_to_bold, "" + string_to_bold[2:-2] + "") 78 | 79 | oids_to_break = oid_regex.findall(text_string) 80 | for oid in oids_to_break: 81 | if len(oid) > 35: 82 | new_oid = oid[:34] 83 | new_oid += oid[34:].replace('.', '.') 84 | text_string = text_string.replace(oid, new_oid) 85 | 86 | # this was original location of this code.. 87 | # hex_strings = long_hex_string.findall(text_string) 88 | # for hex_string in hex_strings: 89 | # new_hex_string = ''.join(textwrap.wrap(hex_string, 8)) 90 | # text_string = text_string.replace(hex_string, new_hex_string) 91 | 92 | text_string = escape_text(text_string, markdown_escape_table) 93 | text_string = text_string.replace(text_indent, html_indent) 94 | text_string = text_string.replace(text_new_line, html_new_line) 95 | 96 | return text_string 97 | -------------------------------------------------------------------------------- /cpct/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cpct.settings") 7 | try: 8 | from django.core.management import execute_from_command_line 9 | except ImportError as exc: 10 | raise ImportError( 11 | "Couldn't import Django. Are you sure it's installed and " 12 | "available on your PYTHONPATH environment variable? Did you " 13 | "forget to activate a virtual environment?" 14 | ) from exc 15 | execute_from_command_line(sys.argv) 16 | -------------------------------------------------------------------------------- /cpct/manifest.yml: -------------------------------------------------------------------------------- 1 | --- 2 | applications: 3 | - name: cpct 4 | stack: cflinuxfs3 5 | instances: 1 6 | memory: 128M 7 | command: null -------------------------------------------------------------------------------- /cpct/profiles/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/profiles/__init__.py -------------------------------------------------------------------------------- /cpct/profiles/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /cpct/profiles/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ProfilesConfig(AppConfig): 5 | name = 'profiles' 6 | -------------------------------------------------------------------------------- /cpct/profiles/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | 4 | class UploadFileForm(forms.Form): 5 | file = forms.FileField() 6 | profile = forms.CharField() 7 | type = forms.CharField() 8 | version = forms.CharField() 9 | -------------------------------------------------------------------------------- /cpct/profiles/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/profiles/migrations/__init__.py -------------------------------------------------------------------------------- /cpct/profiles/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /cpct/profiles/profiles.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_variables": { 3 | "placeholder": "Some Generic Info If Needed" 4 | }, 5 | "profiles": [ 6 | { 7 | "name": "Common Policy SSP Program", 8 | "versions": [ 9 | { 10 | "version": "2.2", 11 | "date": "8/01/2023", 12 | "cert_types": [ 13 | { 14 | "cert_type": "Self-Signed (Root)", 15 | "template": "common-ssp/2.2/ssp-01-self-signed.json" 16 | }, 17 | { 18 | "cert_type": "Self-Issued CA", 19 | "template": "common-ssp/2.2/ssp-02-self-issued-ca.json" 20 | }, 21 | { 22 | "cert_type": "Cross Certificate", 23 | "template": "common-ssp/2.2/ssp-03-cross-certificate.json" 24 | }, 25 | { 26 | "cert_type": "Intermediate CA", 27 | "template": "common-ssp/2.2/ssp-04-intermediate-ca.json" 28 | }, 29 | { 30 | "cert_type": "PIV Content Signing", 31 | "template": "common-ssp/2.2/ssp-05-piv-content-signing.json" 32 | }, 33 | { 34 | "cert_type": "PIV Authentication", 35 | "template": "common-ssp/2.2/ssp-06-piv-auth.json" 36 | }, 37 | { 38 | "cert_type": "PIV Card Authentication", 39 | "template": "common-ssp/2.2/ssp-07-piv-card-auth.json" 40 | }, 41 | { 42 | "cert_type": "Signature", 43 | "template": "common-ssp/2.2/ssp-08-ee-signature.json" 44 | }, 45 | { 46 | "cert_type": "Key Management", 47 | "template": "common-ssp/2.2/ssp-09-key-management.json" 48 | }, 49 | { 50 | "cert_type": "Derived PIV Auth", 51 | "template": "common-ssp/2.2/ssp-10-derived-piv-auth.json" 52 | }, 53 | { 54 | "cert_type": "Authentication", 55 | "template": "common-ssp/2.2/ssp-11-auth.json" 56 | }, 57 | { 58 | "cert_type": "Device", 59 | "template": "common-ssp/2.2/ssp-12-device.json" 60 | }, 61 | { 62 | "cert_type": "Delegated OCSP Responder", 63 | "template": "common-ssp/2.2/ssp-13-delegated-ocsp.json" 64 | }, 65 | { 66 | "cert_type": "Common PIV-I Content Signing", 67 | "template": "common-ssp/2.2/ssp-15-pivi-content-signing.json" 68 | }, 69 | { 70 | "cert_type": "Common PIV-I Authentication", 71 | "template": "common-ssp/2.2/ssp-16-pivi-authentication.json" 72 | }, 73 | { 74 | "cert_type": "Common PIV-I Card Auth", 75 | "template": "common-ssp/2.2/ssp-17-pivi-card-auth.json" 76 | } 77 | ] 78 | }, 79 | { 80 | "version": "2.1", 81 | "date": "9/16/2022", 82 | "cert_types": [ 83 | { 84 | "cert_type": "Self-Signed (Root)", 85 | "template": "common-ssp/2.1/ssp-01-self-signed.json" 86 | }, 87 | { 88 | "cert_type": "Self-Issued CA", 89 | "template": "common-ssp/2.1/ssp-02-self-issued-ca.json" 90 | }, 91 | { 92 | "cert_type": "Cross Certificate", 93 | "template": "common-ssp/2.1/ssp-03-cross-certificate.json" 94 | }, 95 | { 96 | "cert_type": "Intermediate CA", 97 | "template": "common-ssp/2.1/ssp-04-intermediate-ca.json" 98 | }, 99 | { 100 | "cert_type": "PIV Content Signing", 101 | "template": "common-ssp/2.1/ssp-05-piv-content-signing.json" 102 | }, 103 | { 104 | "cert_type": "PIV Authentication", 105 | "template": "common-ssp/2.1/ssp-06-piv-auth.json" 106 | }, 107 | { 108 | "cert_type": "PIV Card Authentication", 109 | "template": "common-ssp/2.1/ssp-07-piv-card-auth.json" 110 | }, 111 | { 112 | "cert_type": "Signature", 113 | "template": "common-ssp/2.1/ssp-08-ee-signature.json" 114 | }, 115 | { 116 | "cert_type": "Key Management", 117 | "template": "common-ssp/2.1/ssp-09-key-management.json" 118 | }, 119 | { 120 | "cert_type": "Derived PIV Auth", 121 | "template": "common-ssp/2.1/ssp-10-derived-piv-auth.json" 122 | }, 123 | { 124 | "cert_type": "Authentication", 125 | "template": "common-ssp/2.1/ssp-11-auth.json" 126 | }, 127 | { 128 | "cert_type": "Device", 129 | "template": "common-ssp/2.1/ssp-12-device.json" 130 | }, 131 | { 132 | "cert_type": "Delegated OCSP Responder", 133 | "template": "common-ssp/2.1/ssp-13-delegated-ocsp.json" 134 | }, 135 | { 136 | "cert_type": "Common PIV-I Content Signing", 137 | "template": "common-ssp/2.1/ssp-15-pivi-content-signing.json" 138 | }, 139 | { 140 | "cert_type": "Common PIV-I Authentication", 141 | "template": "common-ssp/2.1/ssp-16-pivi-authentication.json" 142 | }, 143 | { 144 | "cert_type": "Common PIV-I Card Auth", 145 | "template": "common-ssp/2.1/ssp-17-pivi-card-auth.json" 146 | } 147 | ] 148 | }, 149 | { 150 | "version": "2.0", 151 | "date": "9/1/2020", 152 | "cert_types": [ 153 | { 154 | "cert_type": "Self-Signed (Root)", 155 | "template": "common-ssp/2.0/ssp-01-self-signed.json" 156 | }, 157 | { 158 | "cert_type": "Self-Issued CA", 159 | "template": "common-ssp/2.0/ssp-02-self-issued-ca.json" 160 | }, 161 | { 162 | "cert_type": "Cross Certificate", 163 | "template": "common-ssp/2.0/ssp-03-cross-certificate.json" 164 | }, 165 | { 166 | "cert_type": "Intermediate CA", 167 | "template": "common-ssp/2.0/ssp-04-intermediate-ca.json" 168 | }, 169 | { 170 | "cert_type": "PIV Content Signing", 171 | "template": "common-ssp/2.0/ssp-05-piv-content-signing.json" 172 | }, 173 | { 174 | "cert_type": "PIV Authentication", 175 | "template": "common-ssp/2.0/ssp-06-piv-auth.json" 176 | }, 177 | { 178 | "cert_type": "PIV Card Authentication", 179 | "template": "common-ssp/2.0/ssp-07-piv-card-auth.json" 180 | }, 181 | { 182 | "cert_type": "Signature", 183 | "template": "common-ssp/2.0/ssp-08-ee-signature.json" 184 | }, 185 | { 186 | "cert_type": "Key Management", 187 | "template": "common-ssp/2.0/ssp-09-key-management.json" 188 | }, 189 | { 190 | "cert_type": "Derived PIV Auth", 191 | "template": "common-ssp/2.0/ssp-10-derived-piv-auth.json" 192 | }, 193 | { 194 | "cert_type": "Authentication", 195 | "template": "common-ssp/2.0/ssp-11-auth.json" 196 | }, 197 | { 198 | "cert_type": "Device", 199 | "template": "common-ssp/2.0/ssp-12-device.json" 200 | }, 201 | { 202 | "cert_type": "Delegated OCSP Responder", 203 | "template": "common-ssp/2.0/ssp-13-delegated-ocsp.json" 204 | }, 205 | { 206 | "cert_type": "Common PIV-I Content Signing", 207 | "template": "common-ssp/2.0/ssp-15-pivi-content-signing.json" 208 | }, 209 | { 210 | "cert_type": "Common PIV-I Authentication", 211 | "template": "common-ssp/2.0/ssp-16-pivi-authentication.json" 212 | }, 213 | { 214 | "cert_type": "Common PIV-I Card Auth", 215 | "template": "common-ssp/2.0/ssp-17-pivi-card-auth.json" 216 | } 217 | ] 218 | }, 219 | { 220 | "version": "1.9", 221 | "date": "5/9/2018", 222 | "cert_types": [ 223 | { 224 | "cert_type": "Self Signed (Root)", 225 | "template": "common-ssp/1.9/ssp-01-self-signed.json" 226 | }, 227 | { 228 | "cert_type": "Self Issued CA", 229 | "template": "common-ssp/1.9/ssp-02-self-issued-ca.json" 230 | }, 231 | { 232 | "cert_type": "Cross Certificate", 233 | "template": "common-ssp/1.9/ssp-03-cross-certificate.json" 234 | }, 235 | { 236 | "cert_type": "End Entity Signature", 237 | "template": "common-ssp/1.9/ssp-05-ee-signature.json" 238 | }, 239 | { 240 | "cert_type": "Key Management", 241 | "template": "common-ssp/1.9/ssp-06-key-management.json" 242 | }, 243 | { 244 | "cert_type": "Device", 245 | "template": "common-ssp/1.9/ssp-07-device.json" 246 | }, 247 | { 248 | "cert_type": "PIV Card Auth", 249 | "template": "common-ssp/1.9/ssp-08-piv-card-auth.json" 250 | }, 251 | { 252 | "cert_type": "PIV Authentication", 253 | "template": "common-ssp/1.9/ssp-09-piv-auth.json" 254 | }, 255 | { 256 | "cert_type": "PIV Content Signing", 257 | "template": "common-ssp/1.9/ssp-10-piv-content-signing.json" 258 | }, 259 | { 260 | "cert_type": "Derived PIV Auth", 261 | "template": "common-ssp/1.9/ssp-11-derived-piv-auth.json" 262 | }, 263 | { 264 | "cert_type": "Delegated OCSP", 265 | "template": "common-ssp/1.9/ssp-12-delegated-ocsp.json" 266 | } 267 | ] 268 | }, 269 | { 270 | "version": "1.8", 271 | "date": "7/17/2017", 272 | "cert_types": [ 273 | { 274 | "cert_type": "Self Signed (Root)", 275 | "template": "common-ssp/1.8/ssp-01-self-signed.json" 276 | }, 277 | { 278 | "cert_type": "Self Issued CA", 279 | "template": "common-ssp/1.8/ssp-02-self-issued-ca.json" 280 | }, 281 | { 282 | "cert_type": "Cross Certificate", 283 | "template": "common-ssp/1.8/ssp-03-cross-certificate.json" 284 | }, 285 | { 286 | "cert_type": "End Entity Signature", 287 | "template": "common-ssp/1.8/ssp-05-ee-signature.json" 288 | }, 289 | { 290 | "cert_type": "Key Management", 291 | "template": "common-ssp/1.8/ssp-06-key-management.json" 292 | }, 293 | { 294 | "cert_type": "Device", 295 | "template": "common-ssp/1.8/ssp-07-device.json" 296 | }, 297 | { 298 | "cert_type": "PIV Card Auth", 299 | "template": "common-ssp/1.8/ssp-08-piv-card-auth.json" 300 | }, 301 | { 302 | "cert_type": "PIV Authentication", 303 | "template": "common-ssp/1.8/ssp-09-piv-auth.json" 304 | }, 305 | { 306 | "cert_type": "PIV Content Signing", 307 | "template": "common-ssp/1.8/ssp-10-piv-content-signing.json" 308 | }, 309 | { 310 | "cert_type": "Derived PIV Auth", 311 | "template": "common-ssp/1.8/ssp-11-derived-piv-auth.json" 312 | }, 313 | { 314 | "cert_type": "Delegated OCSP", 315 | "template": "common-ssp/1.8/ssp-12-delegated-ocsp.json" 316 | } 317 | ] 318 | } 319 | ] 320 | }, 321 | { 322 | "name": "Federal PKI / Federal Bridge", 323 | "versions": [ 324 | { 325 | "version": "2.0", 326 | "date": "08/01/2023", 327 | "cert_types": [ 328 | { 329 | "cert_type": "Self Signed CA", 330 | "template": "fbca/2.0/1-self-signed-ca.json" 331 | }, 332 | { 333 | "cert_type": "CA Key Rollover", 334 | "template": "fbca/2.0/2-key-roll-over-ca.json" 335 | }, 336 | { 337 | "cert_type": "Cross Certificate", 338 | "template": "fbca/2.0/3-cross-certificate.json" 339 | }, 340 | { 341 | "cert_type": "End Entity Signature", 342 | "template": "fbca/2.0/5-ee-signature.json" 343 | }, 344 | { 345 | "cert_type": "Key Management", 346 | "template": "fbca/2.0/6-ee-key-management.json" 347 | }, 348 | { 349 | "cert_type": "Authentication", 350 | "template": "fbca/2.0/pivi-05-authentication.json" 351 | }, 352 | { 353 | "cert_type": "Card Authentication", 354 | "template": "fbca/2.0/pivi-04-card-auth.json" 355 | }, 356 | { 357 | "cert_type": "Content Signing", 358 | "template": "fbca/2.0/pivi-08-content-signing.json" 359 | }, 360 | { 361 | "cert_type": "Delegated OCSP", 362 | "template": "fbca/2.0/pivi-09-delegated-ocsp.json" 363 | } 364 | ] 365 | }, 366 | { 367 | "version": "1.9", 368 | "date": "5/10/2018", 369 | "cert_types": [ 370 | { 371 | "cert_type": "Self Signed CA", 372 | "template": "fbca/1.9/1-self-signed-ca.json" 373 | }, 374 | { 375 | "cert_type": "CA Key Rollover", 376 | "template": "fbca/1.9/2-key-roll-over-ca.json" 377 | }, 378 | { 379 | "cert_type": "Cross Certificate", 380 | "template": "fbca/1.9/3-cross-certificate.json" 381 | }, 382 | { 383 | "cert_type": "End Entity Signature", 384 | "template": "fbca/1.9/5-ee-signature.json" 385 | }, 386 | { 387 | "cert_type": "Key Management", 388 | "template": "fbca/1.9/6-ee-key-management.json" 389 | } 390 | ] 391 | }, 392 | { 393 | "version": "1.8", 394 | "date": "7/17/2017", 395 | "cert_types": [ 396 | { 397 | "cert_type": "Self Signed CA", 398 | "template": "fbca/1.8/1-self-signed-ca.json" 399 | }, 400 | { 401 | "cert_type": "CA Key Rollover", 402 | "template": "fbca/1.8/2-key-roll-over-ca.json" 403 | }, 404 | { 405 | "cert_type": "Cross Certificate", 406 | "template": "fbca/1.8/3-cross-certificate.json" 407 | }, 408 | { 409 | "cert_type": "End Entity Signature", 410 | "template": "fbca/1.8/5-ee-signature.json" 411 | }, 412 | { 413 | "cert_type": "Key Management", 414 | "template": "fbca/1.8/6-ee-key-management.json" 415 | } 416 | ] 417 | } 418 | ] 419 | }, 420 | { 421 | "name": "PIV Interoperable (PIV-I)", 422 | "versions": [ 423 | { 424 | "version": "1.3", 425 | "date": "5/10/2018", 426 | "cert_types": [ 427 | { 428 | "cert_type": "Self Signed", 429 | "template": "pivi/1.3/pivi-01-self-signed.json" 430 | }, 431 | { 432 | "cert_type": "Cross Certificate", 433 | "template": "pivi/1.3/pivi-02-cross-certificate.json" 434 | }, 435 | { 436 | "cert_type": "Card Authentication", 437 | "template": "pivi/1.3/pivi-04-card-auth.json" 438 | }, 439 | { 440 | "cert_type": "Authentication", 441 | "template": "pivi/1.3/pivi-05-authentication.json" 442 | }, 443 | { 444 | "cert_type": "Signature", 445 | "template": "pivi/1.3/pivi-06-signature.json" 446 | }, 447 | { 448 | "cert_type": "Key Management", 449 | "template": "pivi/1.3/pivi-07-key-management.json" 450 | }, 451 | { 452 | "cert_type": "Content Signing", 453 | "template": "pivi/1.3/pivi-08-content-signing.json" 454 | }, 455 | { 456 | "cert_type": "Delegated OCSP", 457 | "template": "pivi/1.3/pivi-09-delegated-ocsp.json" 458 | } 459 | ] 460 | }, 461 | { 462 | "version": "1.2", 463 | "date": "7/17/2017", 464 | "cert_types": [ 465 | { 466 | "cert_type": "Self Signed", 467 | "template": "pivi/1.2/pivi-01-self-signed.json" 468 | }, 469 | { 470 | "cert_type": "Cross Certificate", 471 | "template": "pivi/1.2/pivi-02-cross-certificate.json" 472 | }, 473 | { 474 | "cert_type": "Card Authentication", 475 | "template": "pivi/1.2/pivi-04-card-auth.json" 476 | }, 477 | { 478 | "cert_type": "Authentication", 479 | "template": "pivi/1.2/pivi-05-authentication.json" 480 | }, 481 | { 482 | "cert_type": "Signature", 483 | "template": "pivi/1.2/pivi-06-signature.json" 484 | }, 485 | { 486 | "cert_type": "Key Management", 487 | "template": "pivi/1.2/pivi-07-key-management.json" 488 | }, 489 | { 490 | "cert_type": "Content Signing", 491 | "template": "pivi/1.2/pivi-08-content-signing.json" 492 | }, 493 | { 494 | "cert_type": "Delegated OCSP", 495 | "template": "pivi/1.2/pivi-09-delegated-ocsp.json" 496 | } 497 | ] 498 | } 499 | ] 500 | } 501 | ] 502 | } -------------------------------------------------------------------------------- /cpct/profiles/static/GSAStar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/profiles/static/GSAStar.jpg -------------------------------------------------------------------------------- /cpct/profiles/static/check-circle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpct/profiles/static/cio-logo-gif.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/profiles/static/cio-logo-gif.gif -------------------------------------------------------------------------------- /cpct/profiles/static/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/profiles/static/help.png -------------------------------------------------------------------------------- /cpct/profiles/static/idm_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/profiles/static/idm_logo.png -------------------------------------------------------------------------------- /cpct/profiles/static/style.css: -------------------------------------------------------------------------------- 1 | body{background-color:#13315C;padding:0;margin:0;font-family: benton-sans,"Helvetica Neue",helvetica,arial,sans-serif;} 2 | #header{height:8px;background-color:#13315c;width:100%;color:white;font:8pt verdana;} 3 | #header2{height:15px;background: linear-gradient(to right, #024D86, #8ECDEA);width:100%;border-top:1px solid #0b2545;border-bottom:0px solid #0b2545;} 4 | #header3{min-height:60px;background-color:#8da9c4;width:100%;border-top:2px solid #ddd;} 5 | .header4 { 6 | background: linear-gradient(to right, #024D86, #8ECDEA); 7 | content: ''; 8 | width: 100%; 9 | position:relative; 10 | top:0px; 11 | height: 4px; 12 | } 13 | #main-form{border:1px solid #0b2545;background-color:#eef4ed;margin-left:auto;margin-right:auto;width:800px;border-radius:5px;padding:10px;} 14 | a{color:#00528F;} 15 | .ok-result{margin-left:auto;margin-right:auto;} 16 | .footer a{ 17 | color:white; 18 | } 19 | .row{margin:0;padding:0;} 20 | #result td{font:1em 'Courier New';} 21 | .callout{width:100%;padding:15px;margin:0;font:1em Verdana;border-bottom:2px solid white;} 22 | .callout-success{background: linear-gradient(to right, #008000, #00A65A);color:white;} 23 | .callout-danger{background: linear-gradient(to right, #C23321, #DD4B39);color:white;} 24 | #top-bar{ 25 | -moz-border-radius: 0px; 26 | -webkit-border-radius: 10px 10px 0px 0px; 27 | border-radius: 10px 10px 0px 0px; 28 | background-color:white; 29 | font-weight:normal !important; 30 | 31 | } 32 | #top-bar a{ 33 | } 34 | #result-table_wrapper{ 35 | margin-top:5px;padding:0; 36 | } 37 | table.dataTable span.highlight { 38 | background-color: #FFFF88; 39 | border-radius: 0.28571429rem; 40 | } 41 | 42 | table.dataTable span.column_highlight { 43 | background-color: #ffcc99; 44 | border-radius: 0.28571429rem; 45 | } 46 | .dt-buttons{ 47 | margin-left:10px; 48 | } 49 | .dont-break-out { 50 | 51 | /* These are technically the same, but use both */ 52 | overflow-wrap: break-word; 53 | word-wrap: break-word; 54 | 55 | -ms-word-break: break-all; 56 | /* This is the dangerous one in WebKit, as it breaks things wherever */ 57 | word-break: break-all; 58 | /* Instead use this non-standard one: */ 59 | word-break: break-word; 60 | 61 | /* Adds a hyphen where the word breaks, if supported (No Blink) */ 62 | -ms-hyphens: auto; 63 | -moz-hyphens: auto; 64 | -webkit-hyphens: auto; 65 | hyphens: auto; 66 | 67 | } 68 | #result-table_info{padding-left:10px;} 69 | .help-tip{ 70 | width: 20px; 71 | height: 20px; 72 | font-size: 14px; 73 | line-height: 36px; 74 | cursor: pointer; 75 | font-weight: bold; 76 | color:#bbb;padding:3px; 77 | } 78 | .btn-secondary{ 79 | background:#eee; 80 | color:#666 81 | } 82 | #main-padding{ 83 | padding-left:10px;padding-right:10px; 84 | } 85 | #result{ 86 | margin-top:50px; 87 | } 88 | #goback{ 89 | display:none; 90 | } 91 | #result-table_filter{ 92 | max-width:240px;float:right; 93 | } 94 | #result-table_filter input{ 95 | max-width:160px;margin-right:2px; 96 | } 97 | .dt-buttons{ 98 | float:left; 99 | max-width:150px; 100 | color:#ddd; 101 | margin-top:-3px; 102 | } 103 | @media screen and (max-width: 800px) { 104 | #main-padding{ 105 | margin:0;padding:0; 106 | } 107 | .col-md-12{ 108 | margin:0;padding:0; 109 | } 110 | #result{ 111 | margin-top:30px; 112 | overflow-x:scroll; 113 | } 114 | #result-table{ 115 | min-width:800px; 116 | } 117 | #menu{ 118 | display:none; 119 | } 120 | #goback{ 121 | display:""; 122 | } 123 | } -------------------------------------------------------------------------------- /cpct/profiles/templates/contact-us.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% load static %} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 |
127 | 128 | Certificate Profile Conformance Tool 129 | 130 |
131 | 132 | 133 |
134 | 135 |
136 |
137 |
138 | 156 |
157 |
158 | 159 |
160 | 161 |
162 |
163 | 164 | 165 |
166 |
167 |
168 |
169 | 170 |
171 | 172 | 173 | 174 | 175 |

Questions, Feedback, Suggestions?

176 |

You can connect with us on GitHub or by email.

177 | 178 | 179 |

GitHub

180 | 183 | 184 |

Email

185 | 188 |

189 |

Federal PKI Certificate Policies and Certificate Profiles

190 | 191 | 194 | 195 | 196 |
197 |
198 |
199 |
200 | 201 |
202 | 203 |
204 |
205 |
206 |
207 | Contact Us | Source Code | Privacy Policy | Help 208 |
209 |
210 |
211 |
212 | 213 | 218 | 219 | 220 |
221 | 222 | 223 | 224 | 225 | -------------------------------------------------------------------------------- /cpct/profiles/templates/help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% load static %} 5 | 6 | 7 | 8 | 9 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 |
118 | 119 | Certificate Profile Conformance Tool 120 | 121 |
122 | 123 | 124 |
125 | 126 |
127 |
128 |
129 | 147 |
148 |
149 | 150 |
151 | 152 |
153 |
154 | 155 | 156 |
157 |
158 |
159 |
160 | 161 |
162 | 163 | 164 | 165 |
166 |

What is the Certificate Profile Conformance Tool (CPCT)?

167 | 168 |

CPCT instantly analyzes certificates for conformance to a specific profile document and certificate profile. Results show pass or fail status for the certificate content and a brief explanation for failures. You can also download the test report as an .xls or .pdf.

169 | 170 | 177 | 178 |
179 |

Who Needs CPCT?

180 | 181 |

If you need to analyze Federal PKI certificates for conformance to certificate profiles, then CPCT can help you. The following organizations will find CPCT especially useful:

182 |
    183 |
  • Agencies and organizations that submit FPKI Annual Review Packages
    Test your certificates and take corrective actions before submitting certificate samples.
  • 184 |
  • Certificate Issuers
    Use CPCT to analyze certificates as part of a Quality Assurance process.
  • 185 |
186 | 187 |
188 |

How Does This Work?

189 | 190 |
In-depth experience with Federal PKI certificates and certificate profiles is recommended.
191 | 192 |

The key steps are:

193 | 194 |
    195 |
  • You select the Profile Document, Document Version, and Certificate Profile related to a certificate and then upload the certificate.
  • 196 | 197 |
  • You receive the certificate's test results.
  • 198 | 199 |
  • You can choose to download a test report in Microsoft Excel or Adobe PDF formats.
  • 200 |
201 | 202 |
203 |

Usage Details

204 | 205 |

1. Certificate Profile Selection

206 | Specify the certificate profile you want to test using the drop-list selections. 207 | 208 |
    209 |
  • Profile Document - Select the relevant FPKI Profile Document 210 |
    • Common Policy SSP Program1
    • Federal PKI/Federal Bridge2
    • PIV Interoperable (PIV-I).3
    211 |
  • Document Version - The most recent version available is automatically selected when you select the Profile Document. 212 |
  • Certificate Profile - Select the type of certificate you will test. For example, PIV Authentication.
  • 213 |
214 | 215 |

2. Upload a Certificate

216 | 217 |
    218 |
  1. Upload a certificate (.crt, .pem, .cer, or .der) using either of these options:
219 |
    220 |
  • Drag-and-drop your certificate to anywhere on the CPCT main screen. The Test Results display for the uploaded certificate.
    221 |
  • Click the Upload Certificate button and browse to the certificate. Click it, and then click Open. The Test Results display for the uploaded certificate.
  • 222 |
223 | 224 |

3. Review Certificate Test Results

225 | 226 | 227 |

The status banner will be green (certificate conforms) or red (doesn't conform) and will give a test summary:

228 | 229 |
    230 |
  • Tested [n] fields: No Problems detected 231 |
  • Tested [n] fields: [m] problems detected
  • 232 |
233 | 234 |

The Test Results columns provide the following:

235 |
    236 |
  • Field - Types of fields and extensions in the certificate. 237 |
  • Content - Field and extension content. 238 |
  • Analysis - Displays a checkmark for "PASS" or state "FAIL" (with explanation) for each field and extension.
  • 239 |
240 | 241 |

4. Download a Test Report

242 | 243 |
    244 |
  • To download a Test Report, click the XLS or PDF button below the status banner.
  • 245 |
246 | 247 |
248 |

Troubleshooting

249 | 250 |

Certificate Failures

251 | 252 |
    253 |
  • Please check to ensure that the right Profile Document, Document Version, and Certificate Profile have been selected. 254 |
  • If you have questions about why a certificate failed, or you believe the analysis could be an error please contact us. 255 |
  • 256 |
257 | 258 |

Application Error Messages

259 | 260 |
    261 |
  • You can't upload files of this type. The permitted file extensions are: .crt, .cer, .pem, and .der.
  • 262 |
263 | 264 |

What If I Can't Resolve an Issue?

265 | 266 |
    267 |
  • GitHub - Create an issue in the CPCT Repository and attach the certificate. (You will need a GitHub account to do this: Join GitHub.) 268 |
  • Email us - fpki@gsa.gov and attach your certificate. (Please rename your certificate with .txt file extension.)
  • 269 |
270 | 271 |
272 |

Feature Request

273 | 274 |
    275 |
  • If you would like to suggest a new CPCT feature, create a GitHub issue in the CPCT Repository.
  • 276 |
277 | 278 |
279 |
280 |
1. X.509 Certificate and Certificate Revocation List (CRL) Extensions Profile for the Shared Service Providers (SSP) Program Policy.
281 |
2. Federal Public Key Infrastructure (PKI) X.509 Certificate and CRL Extensions Profile.
282 |
3. X.509 Certificate and Certificate Revocation List (CRL) Extensions Profile for Personal Identity Verification Interoperable (PIV-I) Cards.
283 |
284 | 285 | 286 |
287 |
288 |
289 |
290 | 291 |
292 | 293 |
294 |
295 |
296 |
297 | Contact Us | Source Code | Privacy Policy | Help 298 |
299 |
300 |
301 |
302 | 303 | 308 | 309 | 310 |
311 | 312 | 313 | 314 | 315 | -------------------------------------------------------------------------------- /cpct/profiles/templates/privacy-policy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% load static %} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 |
127 | 128 | Certificate Profile Conformance Tool 129 | 130 |
131 | 132 | 133 |
134 | 135 |
136 |
137 |
138 | 156 |
157 |
158 | 159 |
160 | 161 |
162 |
163 | 164 | 165 |
166 |
167 |
168 |
169 | 170 |
171 | 172 | 173 | 174 | 175 | 176 |

GSA IDManagement.gov Privacy Policy

177 | 178 |

The GSA IDManagement.gov website automatically collects some basic system information to help measure site performance and volume of visitors. This information is also used to help GSA develop the site, analyze patterns of usage, address problem areas, and make the site more useful for you.

179 | 180 |

For detailed information, please see IDManagement.gov's Privacy Policy.

181 | 182 |

Certificate Profile Conformance Tool (CPCT) - Additional Privacy Policy

183 | 184 |

No authentication is required to use CPCT and the information that you provide is protected:

185 |
    186 |
  • No uploaded certificates are saved.
  • 187 |
  • No certificate test results are saved.
  • 188 |
189 | 190 |

Questions or Comments?

191 | 192 |

If you have a privacy-related question or comment, please email us at fpki@gsa.gov

193 | 194 | 195 | 196 | 197 | 198 | 199 |
200 |
201 |
202 |
203 | 204 |
205 | 206 |
207 |
208 |
209 |
210 | Contact Us | Source Code | Privacy Policy | Help 211 |
212 |
213 |
214 |
215 | 216 | 221 | 222 | 223 |
224 | 225 | 226 | 227 | 228 | -------------------------------------------------------------------------------- /cpct/profiles/templates/result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 14 | 18 | 19 |
4 |
5 |

{{ short_name }}

6 | Policy: {{ string }}
7 | {{ url }}
8 | Profile: {{ type }} 9 |
10 |
15 |
16 |
17 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | {% for r in rows %} 31 | 32 | 33 | 34 | 35 | {% if r.analysis %} 36 | 37 | {% else %} 38 | 41 | {% endif %} 42 | 43 | 44 | {% endfor %} 45 | 46 |
FieldContentAnalysis
{{ r.name }}{{ r.content|safe }}{{ r.analysis|safe }} 39 | 40 |
47 | -------------------------------------------------------------------------------- /cpct/profiles/templates/upload.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% load static %} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 |
16 | {% csrf_token %} 17 | 18 | 19 | 38 | 39 | Certificate Profile Conformance Tool 40 | 41 |
42 | 43 | 44 |
45 | 46 |
47 |
48 |
49 | 101 |
102 |
103 | 104 |
105 | 106 |
107 |
108 | 109 | 110 | 121 | 122 |
123 |
124 |
125 | 128 |
129 |
130 |
131 | 132 | 137 | 138 |
139 |
140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 361 | 362 | 363 | -------------------------------------------------------------------------------- /cpct/profiles/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /cpct/profiles/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect 2 | from fpkilint.html_output import * 3 | from django.http import HttpResponse, JsonResponse, HttpResponseRedirect 4 | from .forms import UploadFileForm 5 | import json 6 | import os 7 | module_dir = os.path.dirname(__file__) # get current directory 8 | 9 | 10 | def dashboard(request): 11 | file_path = os.path.join(module_dir, 'profiles.json') 12 | with open(file_path) as f: 13 | profiles = f.read() 14 | 15 | form = UploadFileForm() 16 | 17 | return render(request, 'upload.html', {'form': form, 'profiles': profiles}) 18 | 19 | 20 | def upload_file(request): 21 | file_path = os.path.join(module_dir, 'profiles.json') 22 | with open(file_path) as f: 23 | profiles = f.read() 24 | 25 | if request.method == 'POST': 26 | form = UploadFileForm(request.POST, request.FILES) 27 | if form.is_valid(): 28 | file = request.FILES['file'] 29 | try: 30 | cert = parse_certificate(file.read()) 31 | except: 32 | return HttpResponse( 33 | "
File could not be parsed
") 34 | 35 | profile = int(form.cleaned_data['profile']) 36 | type = int(form.cleaned_data['type']) 37 | version = int(form.cleaned_data['version']) 38 | data = json.loads(profiles) 39 | 40 | try: 41 | template = data['profiles'][profile]['versions'][version]['cert_types'][type]['template'] 42 | except: 43 | return HttpResponse("
Invalid Template
") 44 | 45 | # rows, type, string, url, short_name = analyze_certificate(cert, template) 46 | 47 | try: 48 | rows, type, string, url, short_name = analyze_certificate(cert, template) 49 | except: 50 | return HttpResponse( 51 | "
Unrecoverable Error
") 52 | 53 | return render(request, 'result.html', {'rows': rows, 'type': type, 'string': string, 'url': url, 54 | 'short_name': short_name}) 55 | else: 56 | return HttpResponse("
You must select a profile.
") 57 | else: 58 | return HttpResponse("
Invalid Request (not POST)
") 59 | 60 | 61 | def help(request): 62 | return render(request, 'help.html') 63 | 64 | def privacy(request): 65 | return render(request, 'privacy-policy.html') 66 | 67 | def contact(request): 68 | return render(request, 'contact-us.html') 69 | -------------------------------------------------------------------------------- /cpct/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==4.2.18 2 | pytz==2020.1 3 | whitenoise==5.2.0 4 | gunicorn==22.0.0 5 | asn1crypto==1.4.0 6 | setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability 7 | -------------------------------------------------------------------------------- /cpct/runtime.txt: -------------------------------------------------------------------------------- 1 | python-3.9.9 2 | -------------------------------------------------------------------------------- /cpct/staticfiles/GSAStar.554ed8897b06.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/staticfiles/GSAStar.554ed8897b06.jpg -------------------------------------------------------------------------------- /cpct/staticfiles/GSAStar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/staticfiles/GSAStar.jpg -------------------------------------------------------------------------------- /cpct/staticfiles/check-circle.d8739c607554.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpct/staticfiles/check-circle.d8739c607554.svg.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/staticfiles/check-circle.d8739c607554.svg.gz -------------------------------------------------------------------------------- /cpct/staticfiles/check-circle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpct/staticfiles/check-circle.svg.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/staticfiles/check-circle.svg.gz -------------------------------------------------------------------------------- /cpct/staticfiles/cio-logo-gif.5df75addbfd6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/staticfiles/cio-logo-gif.5df75addbfd6.gif -------------------------------------------------------------------------------- /cpct/staticfiles/cio-logo-gif.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/staticfiles/cio-logo-gif.gif -------------------------------------------------------------------------------- /cpct/staticfiles/dropzone.ca03e492beaa.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/staticfiles/dropzone.ca03e492beaa.js.gz -------------------------------------------------------------------------------- /cpct/staticfiles/dropzone.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/staticfiles/dropzone.js.gz -------------------------------------------------------------------------------- /cpct/staticfiles/help.fffff73b616d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/staticfiles/help.fffff73b616d.png -------------------------------------------------------------------------------- /cpct/staticfiles/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/staticfiles/help.png -------------------------------------------------------------------------------- /cpct/staticfiles/idm_logo.3d0213b576f4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/staticfiles/idm_logo.3d0213b576f4.png -------------------------------------------------------------------------------- /cpct/staticfiles/idm_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/cpct/staticfiles/idm_logo.png -------------------------------------------------------------------------------- /cpct/staticfiles/staticfiles.json: -------------------------------------------------------------------------------- 1 | {"paths": {"check-circle.svg": "check-circle.d8739c607554.svg", "cio-logo-gif.gif": "cio-logo-gif.5df75addbfd6.gif", "dropzone.js": "dropzone.ca03e492beaa.js", "GSAStar.jpg": "GSAStar.554ed8897b06.jpg", "help.png": "help.fffff73b616d.png", "idm_logo.png": "idm_logo.3d0213b576f4.png"}, "version": "1.0"} -------------------------------------------------------------------------------- /cpct/staticfiles/strapdown.css: -------------------------------------------------------------------------------- 1 | 2 | /******************************************************************* 3 | 4 | This chunk is to fix Bootstrap so that the Markdown output looks good 5 | 6 | *******************************************************************/ 7 | 8 | body { 9 | padding-top: 60px; 10 | padding-bottom: 40px; 11 | font-size: 15px; 12 | line-height: 150%; 13 | } 14 | 15 | xmp, textarea { 16 | display: none; 17 | } 18 | 19 | h1,h2,h3,h4 { 20 | margin: 15px 0; 21 | } 22 | 23 | pre { 24 | margin: 20px 0; 25 | } 26 | 27 | img { 28 | margin: 10px 0; 29 | } 30 | 31 | .navbar { 32 | z-index: 1; 33 | } 34 | 35 | .table { 36 | width: auto; 37 | } 38 | 39 | /******************************************************************* 40 | 41 | This chunk is for Google's Code Prettify: 42 | http://google-code-prettify.googlecode.com 43 | 44 | *******************************************************************/ 45 | 46 | 47 | /* Pretty printing styles. Used with prettify.js. */ 48 | 49 | /* SPAN elements with the classes below are added by prettyprint. */ 50 | .pln { color: #000 } /* plain text */ 51 | 52 | @media screen { 53 | .str { color: #080 } /* string content */ 54 | .kwd { color: #008 } /* a keyword */ 55 | .com { color: #800 } /* a comment */ 56 | .typ { color: #606 } /* a type name */ 57 | .lit { color: #066 } /* a literal value */ 58 | /* punctuation, lisp open bracket, lisp close bracket */ 59 | .pun, .opn, .clo { color: #660 } 60 | .tag { color: #008 } /* a markup tag name */ 61 | .atn { color: #606 } /* a markup attribute name */ 62 | .atv { color: #080 } /* a markup attribute value */ 63 | .dec, .var { color: #606 } /* a declaration; a variable name */ 64 | .fun { color: red } /* a function name */ 65 | } 66 | 67 | /* Use higher contrast and text-weight for printable form. */ 68 | @media print, projection { 69 | .str { color: #060 } 70 | .kwd { color: #006; font-weight: bold } 71 | .com { color: #600; font-style: italic } 72 | .typ { color: #404; font-weight: bold } 73 | .lit { color: #044 } 74 | .pun, .opn, .clo { color: #440 } 75 | .tag { color: #006; font-weight: bold } 76 | .atn { color: #404 } 77 | .atv { color: #060 } 78 | } 79 | 80 | /* Put a border around prettyprinted code snippets. */ 81 | pre.prettyprint { padding: 2px; border: 1px solid #888 } 82 | 83 | /* Specify class=linenums on a pre to get line numbering */ 84 | ol.linenums { margin-top: 0; margin-bottom: 0 } /* IE indents via margin-left */ 85 | li.L0, 86 | li.L1, 87 | li.L2, 88 | li.L3, 89 | li.L5, 90 | li.L6, 91 | li.L7, 92 | li.L8 { list-style-type: none } 93 | /* Alternate shading for lines */ 94 | li.L1, 95 | li.L3, 96 | li.L5, 97 | li.L7, 98 | li.L9 { background: #eee } 99 | 100 | -------------------------------------------------------------------------------- /docs/SysDiag.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/docs/SysDiag.pptx -------------------------------------------------------------------------------- /docs/Workflow.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/docs/Workflow.pdf -------------------------------------------------------------------------------- /docs/cpct_contact_us.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Contact Us 4 | collection: docs 5 | permalink: docs/contactus/ 6 | --- 7 | 8 | 9 | 10 |

Questions, Feedback, Suggestions?

11 | 12 | 15 | 16 |

Contact us:

17 | 18 | 22 | 23 |

We’ll respond as quickly as possible.

24 | 25 |

Thank you!

26 | 27 |

Where Can I Find the Latest FPKI Certificate Policies, Profiles, and Change Proposals?

28 | 29 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /docs/cpct_privacy_policy.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Privacy Policy 4 | collection: docs 5 | permalink: docs/privacy/ 6 | --- 7 | 8 | 9 | 10 |

GSA IDManagement.gov Privacy Policy

11 | 12 |

The GSA IDManagement.gov website automatically collects some basic system information to help measure site performance and volume of visitors. This information is also used to help GSA develop the site, analyze patterns of usage, address problem areas, and make the site more useful for you.

13 | 14 |

For detailed information, please see IDManagement.gov's Privacy Policy.

15 | 16 |

Certificate Profile Conformance Tool (CPCT) - Additional Privacy Policy

17 | 18 |

When you use CPCT, the information that you provide or generate is protected:

19 | 20 |
  • No uploaded certificates are saved. 21 |
  • No certificate test results are saved. 22 |
  • Your identity information is not saved.
  • 23 | 24 | 25 |

    Questions or Comments?

    26 | 27 |

    If you have a privacy-related question or comment, please email us at fpki@gsa.gov.

    28 | 29 |

    We’ll respond to your email as quickly as possible.

    30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/cpct_user_help.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Certificate Profile Conformance Tool (CPCT) Help 4 | collection: docs 5 | permalink: docs/userguide/ 6 | --- 7 | 8 | 9 |

    What is the Certificate Profile Conformance Tool (CPCT)?

    10 | 11 |

    CPCT is a friendly tool that instantly analyzes certificates for conformance to a specific profile document and certificate profile. It not only displays a certificate's test results but also the reason(s) for any nonconformance. What's more, you can download a Test Report (.xls or .pdf) to submit as part of a Federal PKI Annual Review package or retain for your organization's needs.

    12 | 13 | 21 | 22 |

    Who Needs CPCT?

    23 | 24 |

    If you need to analyze Federal PKI certificates for conformance to certificate profiles, then CPCT can help you. The following organizations will find CPCT especially useful:

    25 | 30 | 31 |

    Operating System Requirements

    32 | 33 | 38 | 39 |

    How Does This Work?

    40 | 41 |

    Note:  In-depth experience with Federal PKI certificates and certificate profiles is recommended.

    42 | 43 |

    The key steps are:

    44 | 45 | 52 | 53 |

    Detailed Steps

    54 | 55 | 56 |

    1. Select Profile Documents

    57 | 58 |
      59 |
    1. Navigate to CPCT. 60 | 61 |
    2. From the 3 drop-downs, pick:
    62 | 67 | 68 |

    2. Upload a Certificate

    69 | 70 |
      71 |
    1. Upload a certificate (.ctr, .pem, .cer, or .der file) using either of these options:
    72 | 76 | 77 |

    3. Review Certificate Test Results

    78 |

    Note:  The Test Results screen includes the CPCT drop-downs so you can easily upload more certificates.

    79 | 80 |

    The status banner will be green (certificate conforms) or red (doesn't conform) and will give a test summary:

    81 | 82 | 86 | 87 |

    The Test Results columns provide the following:

    88 | 93 | 94 |

    4. Download a Test Report

    95 | 96 | 99 | 100 |

    Troubleshooting

    101 | 102 |

    Certificate Failures

    103 | 104 | 109 | 110 |

    Application Error Messages

    111 | 112 | 115 | 116 |

    What If I Can't Resolve an Issue?

    117 | 118 | 122 | 123 |

    We will respond as soon as possible.

    124 | 125 |

    Feature Request

    126 | 127 | 130 | 131 |

    ____________

    132 |

    1. X.509 Certificate and Certificate Revocation List (CRL) Extensions Profile for the Shared Service Providers (SSP) Program Policy.
    133 | 2. Federal Public Key Infrastructure (PKI) X.509 Certificate and CRL Extensions Profile.
    134 | 3. X.509 Certificate and Certificate Revocation List (CRL) Extensions Profile for Personal Identity Verification Interoperable (PIV-I) Cards.

    135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /docs/cpcthelp.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Certificate Profile Conformance Tool (CPCT) Help 4 | collection: docs 5 | permalink: docs/userguide/ 6 | --- 7 | 8 | 9 |

    What is the Certificate Profile Conformance Tool (CPCT)?

    10 | 11 |

    CPCT is a friendly tool that instantly analyzes certificates for conformance to a specific profile document and certificate profile. It not only displays a certificate's test results but also the reason(s) for any nonconformance. What's more, you can download a Test Report (.xls or .pdf) to submit as part of a Federal PKI Annual Review package or retain for your organization's needs.

    12 | 13 | 21 | 22 |

    Who Needs CPCT?

    23 | 24 |

    If you need to analyze Federal PKI certificates for conformance to certificate profiles, then CPCT can help you. The following organizations will find CPCT especially useful:

    25 | 30 | 31 |

    Operating System Requirements

    32 | 33 | 38 | 39 |

    How Does This Work?

    40 | 41 |

    Note:  In-depth experience with Federal PKI certificates and certificate profiles is recommended.

    42 | 43 |

    The key steps are:

    44 | 45 | 52 | 53 |

    Detailed Steps

    54 | 55 | 56 |

    1. Select Profile Documents

    57 | 58 |
      59 |
    1. Navigate to CPCT. 60 | 61 |
    2. From the 3 drop-downs, pick:
    62 | 67 | 68 |

    2. Upload a Certificate

    69 | 70 |
      71 |
    1. Upload a certificate (.ctr, .pem, .cer, or .der file) using either of these options:
    72 | 76 | 77 |

    3. Review Certificate Test Results

    78 |

    Note:  The Test Results screen includes the CPCT drop-downs so you can easily upload more certificates.

    79 | 80 |

    The status banner will be green (certificate conforms) or red (doesn't conform) and will give a test summary:

    81 | 82 | 86 | 87 |

    The Test Results columns provide the following:

    88 | 93 | 94 |

    4. Download a Test Report

    95 | 96 | 99 | 100 |

    Troubleshooting

    101 | 102 |

    Certificate Failures

    103 | 104 | 109 | 110 |

    Application Error Messages

    111 | 112 | 115 | 116 |

    What If I Can't Resolve an Issue?

    117 | 118 | 122 | 123 |

    We will respond as soon as possible.

    124 | 125 |

    Feature Request

    126 | 127 | 130 | 131 |

    ____________

    132 |

    1. X.509 Certificate and Certificate Revocation List (CRL) Extensions Profile for the Shared Service Providers (SSP) Program Policy.
    133 | 2. Federal Public Key Infrastructure (PKI) X.509 Certificate and CRL Extensions Profile.
    134 | 3. X.509 Certificate and Certificate Revocation List (CRL) Extensions Profile for Personal Identity Verification Interoperable (PIV-I) Cards.

    135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /docs/profile-config.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/docs/profile-config.xlsx -------------------------------------------------------------------------------- /docs/sample.md: -------------------------------------------------------------------------------- 1 | ### Below is actual tool output reformatted for this page 2 | 3 | | **Field** | **Content** | **Analysis** | 4 | | :-------- | :------------------------------- | :------------------------------------------------------ | 5 | | Version | v3 | PASS | 6 | | Serial Number | 5B 25 58 A5
    (4 octets) | PASS | 7 | | Signature Algorithm | sha256-rsa (1.2.840.113549.1.1.11) | PASS | 8 | | Issuer DN | OU (2.5.4.11) = (Printable) Entrust Managed Services SSP CA,
    OU (2.5.4.11) = (Printable) Certification Authorities,
    O (2.5.4.10) = (Printable) Entrust,
    C (2.5.4.6) = (Printable) US | PASS | 9 | | Validity Period | Not Before: 2018-11-06 15:42:17+00:00
          [utc_time] 181106154217Z

    Not After: 2021-11-04 16:09:59+00:00
          [utc_time] 211104160959Z

    Validity period of 1094 days, 0:27:42
    Expires in 994 days, 0:43:14 | PASS | 10 | | Subject DN | User ID (0.9.2342.19200300.100.1.1) = (Printable) 47001003572881,
    CN (2.5.4.3) = (Printable) JOHN RYAN (Affiliate),
    OU (2.5.4.11) = (Printable) General Services Administration,
    O (2.5.4.10) = (Printable) U.S. Government,
    C (2.5.4.6) = (Printable) US | PASS | 11 | | Subject Public Key | RSA-2048 (1.2.840.113549.1.1.1)

    30 82 01 0A 02 82 01 01 00 A2 01 56 E3 51 52 74 DB A7 C8 F7 DA 6D B7 FD 0D 0A 7B DE B4 C0 8A D3 71 40 0B 7A 5F 06 F3 3B DE CF C7 80 9E 1D 8C 8C 2B C2 C5 95 39 1D A3 3A F5 B7 0F 75 89 0B E1 2C 39 A2 46 16 AE 69 FD 14 B0 D6 FA AA 2B BF 55 66 B8 CF 1D EE 5A E8 D0 97 FE B8 F9 AE 43 7C 0D 7F C2 54 5B B1 3E 22 71 C0 A8 86 94 5F 92 E3 2E DA EC 1B 72 DC 6C 17 79 50 43 02 3E 25 B3 29 69 E7 C6 BA 56 94 FA 17 85 8D E4 EC 8F F7 FC CD 02 08 8A 55 17 DD D4 C5 C4 36 90 CE 3D CC 1C FC 9B B5 AA F6 91 7D 23 C1 AE 22 5F 61 1C A7 48 52 83 CA 5D C2 B8 7C 1F F7 E7 CF 73 29 D1 12 CD 09 5A DE E1 E7 03 61 88 02 4F E4 85 2C 59 F5 8D CD 4B 3B 9E 93 19 CA F3 DA A0 05 00 F5 AC 02 89 D0 CA 91 CD A9 85 68 5E 33 CC EE F7 3A 53 5F B4 3B D2 63 EF FD 59 9B CC 2D D9 1C 21 C6 E3 9D 63 DF BA BA F5 58 0B 7E 19 C3 5D AB D3 02 03 01 00 01 | PASS | 12 | | Key Usage | Critical = TRUE
    digitalSignature (0) | PASS | 13 | | Extended Key Usage | Client Authentication (1.3.6.1.5.5.7.3.2)
    Microsoft Smart Card Logon (1.3.6.1.4.1.311.20.2.2)
    Any Extended Key Usage (2.5.29.37.0) | PASS | 14 | | Subject Key Identifier | Key ID: 6FC5CBBE574013F7C60596AC59C54F79BC0F3E55 | PASS | 15 | | Authority Key Identifier | Key ID: 55B46C333FE3601AA7FFC3EDB4F7E404DA29D063 | PASS | 16 | | Subject Alternate Name | Other Name: UPN: 0000000000@GSA.GOV
    Other Name: FASCN:
    D1 38 10 D8 21 09 2D CC D4 53 45 A1 68 5A 01 0E 6B C4 4C 59 81 38 10 D7 FA
    URI: (UUID) urn:uuid:7b878890-1001-014a-a8a3-53b5e15d43d1 | PASS | 17 | | CRL Distribution Points | [1] Distribution Point
          Full Name
                URI: http://sspweb.managed.entrust.com/CRLs/EMSSSPCA2.crl
                URI: ldap://sspdir.managed.entrust.com/cn=WinCombined2,ou=Entrust Managed Services SSP CA,ou=Certification Authorities,o=Entrust,c=US?certificateRevocationList;binary
    [2] Distribution Point
          Full Name
                Directory Name:
                      CN = CRL13296,
                      OU = Entrust Managed Services SSP CA,
                      OU = Certification Authorities,
                      O = Entrust,
                      C = US | PASS | 18 | | Authority Information Access | [1] Certification Authority Issuers:
          URI: http://sspweb.managed.entrust.com/AIA/CertsIssuedToEMSSSPCA.p7c
    [2] Certification Authority Issuers:
          URI: ldap://sspdir.managed.entrust.com/ou=Entrust Managed Services SSP CA,ou=Certification Authorities,o=Entrust,c=US?cACertificate;binary,crossCertificatePair;binary
    [3] On-line Certificate Status Protocol:
          URI: http://ocsp.managed.entrust.com/OCSP/EMSSSPCAResponder | PASS | 19 | | Certificate Policies | [1] 2.16.840.1.101.3.2.1.3.13
          (id-fpki-common-authentication) | PASS | 20 | | PIV NACI | BOOLEAN { FALSE } | PASS | 21 | -------------------------------------------------------------------------------- /testdata/README.md: -------------------------------------------------------------------------------- 1 | Test data 2 | -------------------------------------------------------------------------------- /testdata/certs/README.md: -------------------------------------------------------------------------------- 1 | ## Test Certificates 2 | 3 | This directory contains certificates used for testing. Although some certificates found here are legitimate, others are not. No certificates found in this repository should be used for any purpose other than testing. 4 | -------------------------------------------------------------------------------- /testdata/certs/parse_cert_base64.cer: -------------------------------------------------------------------------------- 1 | MIIGkjCCBXqgAwIBAgIUKHPqnR7PYcYFowAuxEkWfNsuHHwwDQYJKoZIhvcNAQEL 2 | BQAwVzELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDENMAsG 3 | A1UECxMERlBLSTEfMB0GA1UEAxMWRmVkZXJhbCBCcmlkZ2UgQ0EgMjAxNjAeFw0x 4 | NjEyMTUxNjI4NDdaFw0xOTEyMTUxNTUxMjJaMGwxCzAJBgNVBAYTAlVTMRYwFAYD 5 | VQQKEw1DZXJ0aVBhdGggTExDMSIwIAYDVQQLExlDZXJ0aWZpY2F0aW9uIEF1dGhv 6 | cml0aWVzMSEwHwYDVQQDExhDZXJ0aVBhdGggQnJpZGdlIENBIC0gRzIwggEiMA0G 7 | CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDS1uJF4kar8AYSXzfbs9dhQPj9g9+D 8 | D8Tre0xl5Y5tqZSdgi872h/P8prDHUlnSQUtTPBZsLzS9cNwOmbs5LCYz4pALvJG 9 | N3XKd5q5JPXgjzkQwMBrX7F8GcrC4rhGg1qWw3Rzmh5yOqllNDejiPoTV+fBIw6S 10 | BgtVkHYaNbRzkz3OR3+f4TqTP9vb/8K+5Mko7Gfu57L5JuazYbiTcz7C7IM1Wief 11 | wVcjqZWctuBSjPGONzI0eKLGZvmtntM54qsOv673I3BmGm2Gs52X0BtRl6Mn9lXm 12 | vggoKYFIZVWn4JMBLPIs5fKyKbwc14hQIBULhiLbqMvdjyWw7ON9HwP3AgMBAAGj 13 | ggM/MIIDOzAPBgNVHRMBAf8EBTADAQH/MIGIBgNVHSAEgYAwfjAMBgpghkgBZQMC 14 | AQMDMAwGCmCGSAFlAwIBAwwwDAYKYIZIAWUDAgEDDjAMBgpghkgBZQMCAQMPMAwG 15 | CmCGSAFlAwIBAyUwDAYKYIZIAWUDAgEDJjAMBgpghkgBZQMCAQMSMAwGCmCGSAFl 16 | AwIBAxMwDAYKYIZIAWUDAgEDFDBTBggrBgEFBQcBAQRHMEUwQwYIKwYBBQUHMAKG 17 | N2h0dHA6Ly9odHRwLmZwa2kuZ292L2JyaWRnZS9jYUNlcnRzSXNzdWVkVG9mYmNh 18 | MjAxNi5wN2MwggFBBgNVHSEEggE4MIIBNDAaBgpghkgBZQMCAQMSBgwrBgEEAYG7 19 | UwEBAQcwGgYKYIZIAWUDAgEDEwYMKwYBBAGBu1MBAQEIMBoGCmCGSAFlAwIBAxQG 20 | DCsGAQQBgbtTAQEBCTAaBgpghkgBZQMCAQMlBgwrBgEEAYG7UwEBARcwGgYKYIZI 21 | AWUDAgEDDAYMKwYBBAGBu1MBAQEDMBoGCmCGSAFlAwIBAwwGDCsGAQQBgbtTAQEB 22 | AjAaBgpghkgBZQMCAQMDBgwrBgEEAYG7UwEBAQEwGgYKYIZIAWUDAgEDDwYMKwYB 23 | BAGBu1MBAQEGMBoGCmCGSAFlAwIBAw8GDCsGAQQBgbtTAQEBBTAaBgpghkgBZQMC 24 | AQMOBgwrBgEEAYG7UwEBAQQwGgYKYIZIAWUDAgEDJgYMKwYBBAGBu1MBAQEYMF4G 25 | CCsGAQUFBwELBFIwUDBOBggrBgEFBQcwBYZCaHR0cDovL2NlcnRpcGF0aC1zaWEu 26 | c3ltYXV0aC5jb20vSXNzdWVkQnktQ2VydGlQYXRoQnJpZGdlQ0EtRzIucDdjMAwG 27 | A1UdJAQFMAOBAQEwCgYDVR02BAMCAQAwDgYDVR0PAQH/BAQDAgEGMB8GA1UdIwQY 28 | MBaAFCOws30WVNQCVnbrOr6pay9DeygWMDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6 29 | Ly9odHRwLmZwa2kuZ292L2JyaWRnZS9mYmNhMjAxNi5jcmwwHQYDVR0OBBYEFNDC 30 | jBM3M3ZKkag84ei3/aKc0d0UMA0GCSqGSIb3DQEBCwUAA4IBAQCnC71Bbx1XnKpj 31 | nV6IjhexQKvAcwpzUAKa+Ypa9UcD2hscKrIXSwCzSaUf2u+DwD2ts9rLNsFWMdvX 32 | l+L22f+eXNHJ/wiXbnJ5+jqb5wbSH+fHPg9mtLUBhX3nYK3CsB8CECgwr1Tzuxkx 33 | l0I85UNw5qFUk52HDqZY/YmV7w/iSVy+KWbt+V2xYu26nDorj1VpkGt60PJlXfix 34 | 1A0rqIsd5RhISGtBMsuTGVNHwJvclmkqnv3mN6zKE+osD9I9B2NfDLj7VuyQmJeh 35 | BOGT0YqaM9sthOOZaMN1AcubkqEAG8rGSw7CRLJGNhTsgkL4wj2O2Q+mXhxOSgQk 36 | KCyEU0C/ 37 | -------------------------------------------------------------------------------- /testdata/certs/parse_cert_binary.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/testdata/certs/parse_cert_binary.cer -------------------------------------------------------------------------------- /testdata/certs/parse_cert_not_cert.p7b: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GSA/fpkilint/f380bc1c902b4dcd2a134eadabdd2ecc5a38e211/testdata/certs/parse_cert_not_cert.p7b -------------------------------------------------------------------------------- /testdata/certs/parse_cert_not_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEA0CtNmDWo9S7UgwzS4i5EGbo0CXY7s+f1ts5DYbnM521C4egc 3 | AzEUhxhJiozhdyW/cfNiWRVyQZSypS/cIu4k7G143sR18PjIREpH3So8OJi2PuE2 4 | MEXcwgjt4RQ7GYqBkjfOoT68VgO66B5l7JFiA4hbQ+GkvJsotoHAVtyWol8Z/6qt 5 | IOVfEcfVisogVLzdoZOegaiFQ4Q0H0HkJWsHFttezqu9C5zZAI/0PqSyPJmp34Zc 6 | TWdwYfo2+KX+a+OtIQAgi7eu+JVG3G0cmqX3mj9RTd4PGvW6gXkmNNRu5YJepDl5 7 | ehb77uF8aHGHT8gkHjJb5Sszz0lMxxe5KrMo4QIDAQABAoIBAAKz/T7zu2zrncDR 8 | 4s8jEKlQ3KoeyemtImisRv223u1GYu7yB6MW+RBEBXhyGd9lMxY0tds4RxKI7sTs 9 | WSxu8TXMuhwSawGlCVyxpjs9+Cg3+23XmM+JqLMwUH5yt82+Ga6fYOSBHwry43Nu 10 | KZ6nyKEJHT5FaNE2JpIwHyJBnQcgtQKoDkxddUnmwcq6f9vcWo/BzrZZBH3KOvi2 11 | A0ialSmKVkGiLht4xx5kieJ00K8h8OG9N7+8+KLgG3RW6Yz0VOzzG9hAHyT3j50e 12 | P+sBC+Ut/0UEi3EbqcENbYpA9F/eQxBsQ48r3SGhBaoleMFnk0pdz22UMFr6MhjH 13 | R+nXp30CgYEA8HThxobrcKoEGtyoN1alnUVHV4cDGKIw/t1tRw93WfM8BAm44qOi 14 | 8uJh3u5dLEOfRjOR1pYVilownAGU+1xLjln4v4Y3ul/ywr3nMsOVy+YOUMnA/iqc 15 | +4XcxO/QLyp4wERhDxBgrabMqYSoBjkiPZBP4k5PeYMfti4qMdStzLsCgYEA3aAf 16 | jSFrcg61FMfqYdCaSHMMqZop1azXCkHV0YtQGWX0P2dC8y2msbk06zMwnlrbs3xl 17 | Lxeq1FP5CTuLLdFb/ec03XQ2b5shSdsuD/fdD6jK41TwtP3aJCUR0saFtujfOReM 18 | nR77GmRP/1xgPvHZIdVzO4C2cgzS7df8qZe69RMCgYACJmlmZwpv5XVH8DUo2YN9 19 | loL+y1xBuiGKBdzWR9MfYMdmmdenXyMz3MZXQfZfUPN5ozhonMrwg8Hvgywb20Vp 20 | rnBE9iRFbFo1V5FbqNgMDLCQFF2/aA4jSZ0hvas04MJXpcTgZ5sVsmoeEeuWsqgV 21 | uNaeBWk8gumjrWH/NBGhxQKBgQCiPjt6zNFkkSG9UdDixJx9l0PY0VP46ewOxT1r 22 | hkogHcQdulGHxo62onf8CuB3vNoDXniQbgoQIF06hg2QgCiRCnZn/FBxiaZn8/2X 23 | kQOTGCVXIPKJ/SB5v2152P1AduAbYoL87xYyLudlcNHAororC6CtGb/2ZC7yEWEV 24 | Ik+qYwKBgF/ms+4D7fj1wG+6zKqMMGkEAQ3wz+l12o5609B12MvpuQkYWxUgQyWI 25 | c+LLkoirW0Ri5uebWeX23md8qOXG/bENpM9EVjHvRvzdReMU8oIomQBoRbbt1kFY 26 | JqWeRNaICDnhn2q9BHxAifSzhwdg/Dd/pClZzLM0M3XzavqiuzFe 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /testdata/certs/parse_cert_pem.cer: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIGkjCCBXqgAwIBAgIUKHPqnR7PYcYFowAuxEkWfNsuHHwwDQYJKoZIhvcNAQEL 3 | BQAwVzELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDENMAsG 4 | A1UECxMERlBLSTEfMB0GA1UEAxMWRmVkZXJhbCBCcmlkZ2UgQ0EgMjAxNjAeFw0x 5 | NjEyMTUxNjI4NDdaFw0xOTEyMTUxNTUxMjJaMGwxCzAJBgNVBAYTAlVTMRYwFAYD 6 | VQQKEw1DZXJ0aVBhdGggTExDMSIwIAYDVQQLExlDZXJ0aWZpY2F0aW9uIEF1dGhv 7 | cml0aWVzMSEwHwYDVQQDExhDZXJ0aVBhdGggQnJpZGdlIENBIC0gRzIwggEiMA0G 8 | CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDS1uJF4kar8AYSXzfbs9dhQPj9g9+D 9 | D8Tre0xl5Y5tqZSdgi872h/P8prDHUlnSQUtTPBZsLzS9cNwOmbs5LCYz4pALvJG 10 | N3XKd5q5JPXgjzkQwMBrX7F8GcrC4rhGg1qWw3Rzmh5yOqllNDejiPoTV+fBIw6S 11 | BgtVkHYaNbRzkz3OR3+f4TqTP9vb/8K+5Mko7Gfu57L5JuazYbiTcz7C7IM1Wief 12 | wVcjqZWctuBSjPGONzI0eKLGZvmtntM54qsOv673I3BmGm2Gs52X0BtRl6Mn9lXm 13 | vggoKYFIZVWn4JMBLPIs5fKyKbwc14hQIBULhiLbqMvdjyWw7ON9HwP3AgMBAAGj 14 | ggM/MIIDOzAPBgNVHRMBAf8EBTADAQH/MIGIBgNVHSAEgYAwfjAMBgpghkgBZQMC 15 | AQMDMAwGCmCGSAFlAwIBAwwwDAYKYIZIAWUDAgEDDjAMBgpghkgBZQMCAQMPMAwG 16 | CmCGSAFlAwIBAyUwDAYKYIZIAWUDAgEDJjAMBgpghkgBZQMCAQMSMAwGCmCGSAFl 17 | AwIBAxMwDAYKYIZIAWUDAgEDFDBTBggrBgEFBQcBAQRHMEUwQwYIKwYBBQUHMAKG 18 | N2h0dHA6Ly9odHRwLmZwa2kuZ292L2JyaWRnZS9jYUNlcnRzSXNzdWVkVG9mYmNh 19 | MjAxNi5wN2MwggFBBgNVHSEEggE4MIIBNDAaBgpghkgBZQMCAQMSBgwrBgEEAYG7 20 | UwEBAQcwGgYKYIZIAWUDAgEDEwYMKwYBBAGBu1MBAQEIMBoGCmCGSAFlAwIBAxQG 21 | DCsGAQQBgbtTAQEBCTAaBgpghkgBZQMCAQMlBgwrBgEEAYG7UwEBARcwGgYKYIZI 22 | AWUDAgEDDAYMKwYBBAGBu1MBAQEDMBoGCmCGSAFlAwIBAwwGDCsGAQQBgbtTAQEB 23 | AjAaBgpghkgBZQMCAQMDBgwrBgEEAYG7UwEBAQEwGgYKYIZIAWUDAgEDDwYMKwYB 24 | BAGBu1MBAQEGMBoGCmCGSAFlAwIBAw8GDCsGAQQBgbtTAQEBBTAaBgpghkgBZQMC 25 | AQMOBgwrBgEEAYG7UwEBAQQwGgYKYIZIAWUDAgEDJgYMKwYBBAGBu1MBAQEYMF4G 26 | CCsGAQUFBwELBFIwUDBOBggrBgEFBQcwBYZCaHR0cDovL2NlcnRpcGF0aC1zaWEu 27 | c3ltYXV0aC5jb20vSXNzdWVkQnktQ2VydGlQYXRoQnJpZGdlQ0EtRzIucDdjMAwG 28 | A1UdJAQFMAOBAQEwCgYDVR02BAMCAQAwDgYDVR0PAQH/BAQDAgEGMB8GA1UdIwQY 29 | MBaAFCOws30WVNQCVnbrOr6pay9DeygWMDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6 30 | Ly9odHRwLmZwa2kuZ292L2JyaWRnZS9mYmNhMjAxNi5jcmwwHQYDVR0OBBYEFNDC 31 | jBM3M3ZKkag84ei3/aKc0d0UMA0GCSqGSIb3DQEBCwUAA4IBAQCnC71Bbx1XnKpj 32 | nV6IjhexQKvAcwpzUAKa+Ypa9UcD2hscKrIXSwCzSaUf2u+DwD2ts9rLNsFWMdvX 33 | l+L22f+eXNHJ/wiXbnJ5+jqb5wbSH+fHPg9mtLUBhX3nYK3CsB8CECgwr1Tzuxkx 34 | l0I85UNw5qFUk52HDqZY/YmV7w/iSVy+KWbt+V2xYu26nDorj1VpkGt60PJlXfix 35 | 1A0rqIsd5RhISGtBMsuTGVNHwJvclmkqnv3mN6zKE+osD9I9B2NfDLj7VuyQmJeh 36 | BOGT0YqaM9sthOOZaMN1AcubkqEAG8rGSw7CRLJGNhTsgkL4wj2O2Q+mXhxOSgQk 37 | KCyEU0C/ 38 | -----END CERTIFICATE----- 39 | -------------------------------------------------------------------------------- /testdata/profiles/README.md: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------