commit 348a475852ac9024878248588b263930266fa4e8
Author: Captain_Trojan <sejakm@students.zcu.cz>
Date:   Wed Mar 10 23:19:41 2021 +0100

    #8226 - deep individual research
    
    Examined both raw openssl's and python-cryptography's utility for our project. Basic certificate functionality implemented and profiled.

diff --git a/doc/README.txt b/doc/README.txt
new file mode 100644
index 0000000..3bc95ad
--- /dev/null
+++ b/doc/README.txt
@@ -0,0 +1,2 @@
+general info (creating CA, CA chain, certificate key usage setup) -> https://gist.github.com/Soarez/9688998
+ocsp (ocsp server), certificate revocation -> https://bhashineen.medium.com/create-your-own-ocsp-server-ffb212df8e63
diff --git a/src/cert/root.key b/src/cert/root.key
new file mode 100644
index 0000000..41c8e43
--- /dev/null
+++ b/src/cert/root.key
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,639D2F92AFFD3C68
+
+ARokGwkac6+e4cozIQjgYhdYvh8SPfpltsFOIo9h5AI4g6WRVJ/ep1xWfz7Bctp6
++bPaxGLedA/GST0D26HlQdJJIXrx0X7FRaGgfCRKzbAed9XWUG/ebBJcRHor9L2I
+tCUxpZM1EoAEYaiIiQ7MnBCuCp+QQ1HhSISE/GAjw6YgzVrEaUZjbmSM5ycNelSp
+zAxde8AVJ2wb7laKNseheuXPtBFMulzhlhVNDxzOmUm5Tm/dVL8Ae+JtREVUWw9X
+egHTqC9c2pVTOGhjSla6P62EoOOLixzyUlKGhlsoiq18G6PfT2DVAv+fdO+H6uey
+4nH6/G7/YXVH9qeokKpTSvE8M8kOjzHeR3sGXUCW9kupjKIz/JbGE2gYliplCaIV
+fh1G4LmgrI5MRqUrIFU5wcClueK2KTPPQeMvNv72Rgsh17rKuQyCvfwCWnvNnR6C
+elhzSXXhLKayrDzsJGkq+TzL8kZJ4XDWAKRbwd3wgUaUCTfrfVblB9JQHS2Vf5P8
+MV8kf2rKsJkNo8w6lOYSTmz2NbS3xiUEtPgX4lLBnEO+tnvUBjwIFHTz0/NmOjn/
+16jjmGcvMEgf+7rObi203dVQ7vacTpk6N3z39sThw75sIJwQ4s4NlGMR+zZPQ1gh
+cQrSbNHMey/JpS4cwR8QLJXXjCrA+ZKXDuZ/ezw8r6r+z7CPKvT7HZrZyMgF2SEn
+0PH6+TaOVOi2I19y8jNpPhowJE0zaJ9QwKuo3+XHxiwe4eITJ9FWe+6E+3zcbIUs
+Ec7GS37QkiP9gmb33FoqNLxstV47LJ5sFVUlsQd8WlgdNbDbj1wxldTK2eHYG3VW
+dLf0SDYg0PqLFNWbjAw8M2A/PQOtkgtc/6nvmiwZXvR4rzZR9wLrUlxOmFuKNfa7
+OgRiQxeRbyuqGRJdZuFhS36+0o6IzpcOy/TbyelmqRvzVK/rAEhT4RTm3Uvgb0Z0
+z8EFSn+evmyS2mqy3hiw8TyjS3cwk/dHzhBfBclMytKCDjBBeISZ4y9YrIwREVdv
+zyiOAhH+e/1XJ7qr7K0NEtkjGUy3K/c1KYNNMnS1t7BgCsTMGbMd+xsvMssdOHRY
+TAheCEotaH8QYSkZaHKZJXmPb29LDAzzJV3XNlG52M8YxYO1k+fCGqW2aUe3qF2I
+9LKjl39o8rQjK4O0KeRXd+vRKvPlJVzn6uL9mS/YtENXJKnqkU8vrxupPIcMkO1m
+lb5veTVBd43aFhCy2BP1sbCHXTa9+3Hf1/4uouwxiw0UWO35SpQvg7tWGOaBxgJI
+Wwzg/gDP7S3dMmwoQZtAeCV0M5xlNt6mSV9m5QbF7c93unP/JFDPExKso7M4uMmQ
+/6aG6RQubuAXKrcZqmTa3zHWTohrGh3OMSWXRxC3060NdJpeBdY8nhM5USLji4cv
+vZ4NpZf+0v1Ka/hD/pSpQGusZp53dMUWkDI0NTeLL1DrxRl400AjR/L4uaB68d9U
+Ahe04OLAv+2eybxsiAFfrc9L9gNk77nMCRq+oD+86eAQanlFtmPPoQl6l2auP5m3
+XBKHVNk3W994mZwQnLFFS3aPK7vaj/e9ozVygsEF/gt9G2rmenopIg==
+-----END RSA PRIVATE KEY-----
diff --git a/src/config.ext b/src/config.ext
new file mode 100644
index 0000000..9f5d59e
--- /dev/null
+++ b/src/config.ext
@@ -0,0 +1,7 @@
+authorityKeyIdentifier=keyid,issuer
+basicConstraints=CA:FALSE
+keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
+subjectAltName = @alt_names
+
+[alt_names]
+DNS.1 = www.alternativename.com.gov.net.biz
\ No newline at end of file
diff --git a/src/crypto.py b/src/crypto.py
new file mode 100644
index 0000000..c7c12da
--- /dev/null
+++ b/src/crypto.py
@@ -0,0 +1,73 @@
+from cryptography import x509
+from cryptography.x509.oid import NameOID
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric import rsa
+import datetime
+from time import time
+
+# Generate our key
+key = rsa.generate_private_key(
+    public_exponent=65537,
+    key_size=2048,
+)
+# Write our key to disk for safe keeping
+with open("cert/key.pem", "wb") as f:
+    f.write(key.private_bytes(
+        encoding=serialization.Encoding.PEM,
+        format=serialization.PrivateFormat.TraditionalOpenSSL,
+        encryption_algorithm=serialization.BestAvailableEncryption(b"passphrase"),
+    ))
+
+# Generate a CSR
+csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
+    # Provide various details about who we are.
+    x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+    x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"California"),
+    x509.NameAttribute(NameOID.LOCALITY_NAME, u"San Francisco"),
+    x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"My Company"),
+    x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
+])).add_extension(
+    x509.SubjectAlternativeName([
+        # Describe what sites we want this certificate for.
+        x509.DNSName(u"mysite.com"),
+        x509.DNSName(u"www.mysite.com"),
+        x509.DNSName(u"subdomain.mysite.com"),
+    ]),
+    critical=False,
+# Sign the CSR with our private key.
+).sign(key, hashes.SHA256())
+# Write our CSR out to disk.
+with open("cert/csr.pem", "wb") as f:
+    f.write(csr.public_bytes(serialization.Encoding.PEM))
+    
+# Various details about who we are. For a self-signed certificate the
+# subject and issuer are always the same.
+subject = issuer = x509.Name([
+    x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
+    x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"California"),
+    x509.NameAttribute(NameOID.LOCALITY_NAME, u"San Francisco"),
+    x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"My Company"),
+    x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
+])
+cert = x509.CertificateBuilder().subject_name(
+    subject
+).issuer_name(
+    issuer
+).public_key(
+    key.public_key()
+).serial_number(
+    x509.random_serial_number()
+).not_valid_before(
+    datetime.datetime.utcnow()
+).not_valid_after(
+    # Our certificate will be valid for 10 days
+    datetime.datetime.utcnow() + datetime.timedelta(days=10)
+).add_extension(
+    x509.SubjectAlternativeName([x509.DNSName(u"localhost")]),
+    critical=False,
+# Sign our certificate with our private key
+).sign(key, hashes.SHA256())
+# Write our certificate out to disk.
+with open("cert/certificate.pem", "wb") as f:
+    f.write(cert.public_bytes(serialization.Encoding.PEM))
diff --git a/src/intermediate_ca_conf.cnf b/src/intermediate_ca_conf.cnf
new file mode 100644
index 0000000..f6d58fc
--- /dev/null
+++ b/src/intermediate_ca_conf.cnf
@@ -0,0 +1,132 @@
+# OpenSSL intermediate CA configuration file.
+# Copy to `/root/ca/intermediate/openssl.cnf`.
+
+[ ca ]
+# `man ca`
+default_ca = CA_default
+
+[ CA_default ]
+# Directory and file locations.
+dir               = /root/ca/intermediate
+certs             = $dir/certs
+crl_dir           = $dir/crl
+new_certs_dir     = $dir/newcerts
+database          = $dir/index.txt
+serial            = $dir/serial
+RANDFILE          = $dir/private/.rand
+
+# The root key and root certificate.
+private_key       = $dir/private/intermediate.key.pem
+certificate       = $dir/certs/intermediate.cert.pem
+
+# For certificate revocation lists.
+crlnumber         = $dir/crlnumber
+crl               = $dir/crl/intermediate.crl.pem
+crl_extensions    = crl_ext
+default_crl_days  = 30
+
+# SHA-1 is deprecated, so use SHA-2 instead.
+default_md        = sha256
+
+name_opt          = ca_default
+cert_opt          = ca_default
+default_days      = 375
+preserve          = no
+policy            = policy_loose
+
+[ policy_strict ]
+# The root CA should only sign intermediate certificates that match.
+# See the POLICY FORMAT section of `man ca`.
+countryName             = match
+stateOrProvinceName     = match
+organizationName        = match
+organizationalUnitName  = optional
+commonName              = supplied
+emailAddress            = optional
+
+[ policy_loose ]
+# Allow the intermediate CA to sign a more diverse range of certificates.
+# See the POLICY FORMAT section of the `ca` man page.
+countryName             = optional
+stateOrProvinceName     = optional
+localityName            = optional
+organizationName        = optional
+organizationalUnitName  = optional
+commonName              = supplied
+emailAddress            = optional
+
+[ req ]
+# Options for the `req` tool (`man req`).
+default_bits        = 2048
+distinguished_name  = req_distinguished_name
+string_mask         = utf8only
+
+# SHA-1 is deprecated, so use SHA-2 instead.
+default_md          = sha256
+
+# Extension to add when the -x509 option is used.
+x509_extensions     = v3_ca
+
+[ req_distinguished_name ]
+# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
+countryName                     = Country Name (2 letter code)
+stateOrProvinceName             = State or Province Name
+localityName                    = Locality Name
+0.organizationName              = Organization Name
+organizationalUnitName          = Organizational Unit Name
+commonName                      = Common Name
+emailAddress                    = Email Address
+
+# Optionally, specify some defaults.
+countryName_default             = GB
+stateOrProvinceName_default     = England
+localityName_default            =
+0.organizationName_default      = Alice Ltd
+organizationalUnitName_default  =
+emailAddress_default            =
+
+[ v3_ca ]
+# Extensions for a typical CA (`man x509v3_config`).
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer
+basicConstraints = critical, CA:true
+keyUsage = critical, digitalSignature, cRLSign, keyCertSign
+
+[ v3_intermediate_ca ]
+# Extensions for a typical intermediate CA (`man x509v3_config`).
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer
+basicConstraints = critical, CA:true, pathlen:0
+keyUsage = critical, digitalSignature, cRLSign, keyCertSign
+
+[ usr_cert ]
+# Extensions for client certificates (`man x509v3_config`).
+basicConstraints = CA:FALSE
+nsCertType = client, email
+nsComment = "OpenSSL Generated Client Certificate"
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid,issuer
+keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
+extendedKeyUsage = clientAuth, emailProtection
+
+[ server_cert ]
+# Extensions for server certificates (`man x509v3_config`).
+basicConstraints = CA:FALSE
+nsCertType = server
+nsComment = "OpenSSL Generated Server Certificate"
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid,issuer:always
+keyUsage = critical, digitalSignature, keyEncipherment
+extendedKeyUsage = serverAuth
+
+[ crl_ext ]
+# Extension for CRLs (`man x509v3_config`).
+authorityKeyIdentifier=keyid:always
+
+[ ocsp ]
+# Extension for OCSP signing certificates (`man ocsp`).
+basicConstraints = CA:FALSE
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid,issuer
+keyUsage = critical, digitalSignature
+extendedKeyUsage = critical, OCSPSigning
\ No newline at end of file
diff --git a/src/openssl.py b/src/openssl.py
new file mode 100644
index 0000000..b7282e8
--- /dev/null
+++ b/src/openssl.py
@@ -0,0 +1,71 @@
+import subprocess
+import os
+from time import time
+
+CONFIG_NAME = "../config"
+
+ROOT_KEY_NAME = "root"
+ROOT_KEY_PASS = "secret_pass"
+ROOT_CERT_NAME = "rootCA"
+
+SOME_CERT_KEY_NAME = "somecert"
+SOME_CERT_KEY_PASS = "another_secret_pass"
+SOME_CERT_NAME = "somecert"
+
+
+def make_private_key(name, passphrase):
+    subprocess.run(["openssl",
+                    "genrsa",               # generate a private key for RSA encryption scheme
+                    "-des3",                # use DES3 for encryption by passphrase
+                    "-out", f"{name}.key",  # output specification
+                    "2048"],                # bits
+
+                   input=bytes(             # input required to interact with openssl's CLI
+                       f'{passphrase}\n'    # openssl queries for passphrase, respond and return
+                       f'{passphrase}\n',   # openssl queries for passphrase verification, respond and return
+                       encoding='utf-8')    # use standard encoding for input stream
+                   )
+
+
+def declare_root_CA(name, key_name, key_passphrase):
+    print("declare root CA")
+    subprocess.run(
+        ["openssl", "req", "-x509", "-new", "-nodes", "-key", key_name + ".key", "-sha256", "-days", "1825", "-out",
+         name + ".crt", "-config", "../root_ca_conf.cnf"], input=bytes(f'{key_passphrase}\nCZ\nPilsen Region\nPilsen\nJSMD\nDepartment of Mysteries\nMd, Js\ninfo@jsmd.gov\n', encoding='utf-8'))
+
+
+def make_certificate_sign_request(name, key_name, key_passphrase):
+    print("make CSR")
+    subprocess.run(
+        ["openssl", "req", "-new", "-key", key_name + ".key", "-out",
+         name + ".csr"], input=bytes(f'{key_passphrase}\nCZ\nPilsen Region\nPilsen\nSome Randoes, a. s.\nBruh\nRando, A\neggsdee@centrum.cz.seznam\n\n\n', encoding='utf-8'))
+
+
+def sign_certificate(name, request_name, ca_certificate, ca_key, ca_pass, config_name):
+    print("sign certificate by CA")
+    subprocess.run(
+        ["openssl", "x509", "-req", "-in", request_name + ".csr", "-CA", ca_certificate + ".crt", "-CAkey", ca_key + ".key",
+         "-CAcreateserial", "-out", name + ".crt", "-days", "123", "-sha256", "-extfile", config_name + ".ext"], input=bytes(ca_pass + "\n", encoding='utf-8'))
+
+
+def setup():
+    make_private_key(ROOT_KEY_NAME, ROOT_KEY_PASS)
+    declare_root_CA(ROOT_CERT_NAME, ROOT_KEY_NAME, ROOT_KEY_PASS)
+
+
+def cert():
+    make_private_key(SOME_CERT_KEY_NAME, SOME_CERT_KEY_PASS)
+    make_certificate_sign_request(SOME_CERT_NAME, SOME_CERT_KEY_NAME, SOME_CERT_KEY_PASS)
+    sign_certificate(SOME_CERT_NAME, SOME_CERT_NAME, ROOT_CERT_NAME, ROOT_KEY_NAME, ROOT_KEY_PASS, CONFIG_NAME)
+
+
+def test():
+    subprocess.run("openssl x509 -text -noout -in rootCA.crt")
+    subprocess.run("openssl rsa -in some_cert.key -check")
+
+
+if __name__ == '__main__':
+    os.chdir("cert")
+    setup()
+    cert()
+    # test()
diff --git a/src/root_ca_conf.cnf b/src/root_ca_conf.cnf
new file mode 100644
index 0000000..8581cda
--- /dev/null
+++ b/src/root_ca_conf.cnf
@@ -0,0 +1,132 @@
+# OpenSSL root CA configuration file.
+# Copy to `/root/ca/openssl.cnf`.
+
+[ ca ]
+# `man ca`
+default_ca = CA_default
+
+[ CA_default ]
+# Directory and file locations.
+dir               = /root/ca
+certs             = $dir/certs
+crl_dir           = $dir/crl
+new_certs_dir     = $dir/newcerts
+database          = $dir/index.txt
+serial            = $dir/serial
+RANDFILE          = $dir/private/.rand
+
+# The root key and root certificate.
+private_key       = $dir/private/ca.key.pem
+certificate       = $dir/certs/ca.cert.pem
+
+# For certificate revocation lists.
+crlnumber         = $dir/crlnumber
+crl               = $dir/crl/ca.crl.pem
+crl_extensions    = crl_ext
+default_crl_days  = 30
+
+# SHA-1 is deprecated, so use SHA-2 instead.
+default_md        = sha256
+
+name_opt          = ca_default
+cert_opt          = ca_default
+default_days      = 375
+preserve          = no
+policy            = policy_strict
+
+[ policy_strict ]
+# The root CA should only sign intermediate certificates that match.
+# See the POLICY FORMAT section of `man ca`.
+countryName             = match
+stateOrProvinceName     = match
+organizationName        = match
+organizationalUnitName  = optional
+commonName              = supplied
+emailAddress            = optional
+
+[ policy_loose ]
+# Allow the intermediate CA to sign a more diverse range of certificates.
+# See the POLICY FORMAT section of the `ca` man page.
+countryName             = optional
+stateOrProvinceName     = optional
+localityName            = optional
+organizationName        = optional
+organizationalUnitName  = optional
+commonName              = supplied
+emailAddress            = optional
+
+[ req ]
+# Options for the `req` tool (`man req`).
+default_bits        = 2048
+distinguished_name  = req_distinguished_name
+string_mask         = utf8only
+
+# SHA-1 is deprecated, so use SHA-2 instead.
+default_md          = sha256
+
+# Extension to add when the -x509 option is used.
+x509_extensions     = v3_ca
+
+[ req_distinguished_name ]
+# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
+countryName                     = Country Name (2 letter code)
+stateOrProvinceName             = State or Province Name
+localityName                    = Locality Name
+0.organizationName              = Organization Name
+organizationalUnitName          = Organizational Unit Name
+commonName                      = Common Name
+emailAddress                    = Email Address
+
+# Optionally, specify some defaults.
+countryName_default             = GB
+stateOrProvinceName_default     = England
+localityName_default            =
+0.organizationName_default      = Alice Ltd
+organizationalUnitName_default  =
+emailAddress_default            =
+
+[ v3_ca ]
+# Extensions for a typical CA (`man x509v3_config`).
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer
+basicConstraints = critical, CA:true
+keyUsage = critical, digitalSignature, cRLSign, keyCertSign
+
+[ v3_intermediate_ca ]
+# Extensions for a typical intermediate CA (`man x509v3_config`).
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer
+basicConstraints = critical, CA:true, pathlen:0
+keyUsage = critical, digitalSignature, cRLSign, keyCertSign
+
+[ usr_cert ]
+# Extensions for client certificates (`man x509v3_config`).
+basicConstraints = CA:FALSE
+nsCertType = client, email
+nsComment = "OpenSSL Generated Client Certificate"
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid,issuer
+keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
+extendedKeyUsage = clientAuth, emailProtection
+
+[ server_cert ]
+# Extensions for server certificates (`man x509v3_config`).
+basicConstraints = CA:FALSE
+nsCertType = server
+nsComment = "OpenSSL Generated Server Certificate"
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid,issuer:always
+keyUsage = critical, digitalSignature, keyEncipherment
+extendedKeyUsage = serverAuth
+
+[ crl_ext ]
+# Extension for CRLs (`man x509v3_config`).
+authorityKeyIdentifier=keyid:always
+
+[ ocsp ]
+# Extension for OCSP signing certificates (`man ocsp`).
+basicConstraints = CA:FALSE
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid,issuer
+keyUsage = critical, digitalSignature
+extendedKeyUsage = critical, OCSPSigning
\ No newline at end of file
