A Code Signing Request is created by an entity who wishes to create a digital certificate from a trusted signer. With this, we create a key pair (a public key and a private key). We then send the public key to a trusted issuer, and then sign the request with the private key. The request starts with "-----BEGIN CERTIFICATE REQUEST-----", and is in a form defined by PKCS#10.
Code Signing Request in Python |
Outline
The following shows the process for generating keys and creating the CSR:
The start of the process is the creation of a key pair. This can be achieved using Openssl:
$ openssl genrsa -out ca.key 2048 Loading 'screen' into random state - done Generating RSA private key, 2048 bit long modulus ..............................................+++ .......................................................+++ e is 65537 (0x10001)
In this case we have created 2,048-bit key pairs, and which are contained in the ca.key file:
-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEA7g1oS54PiY/6h2wzN0eY8yzCANa26y6BNBfmK1RKJ9Mc/rXt CofBfunBR5kXhOpQnkmDo9eo4Uu3tPz9qor3zAdaUIOoo8jQw4faQjY35tDTrl9X dBtzkilR6Qnce6VJrLT/t/uL5fIVvxitnRJSd1QEWPoyT5LOvZsw/39qtXv/6v+W wVfTgnWGce99Wpt/PvtYD9u9EfbFUZvbrcl4APokMfbQJfBPwhpX/XKfskKZgt0M 3Km2Ik2kmohKJ5M37KDC8pMoyV2vJ0iZsWAaxPvjaaXkX36XUyL+CbmjtyaQMLXr vNGwxy6OvtYjla/PR1JlPEeKSaCQI/O9/5xnYQIDAQABAoIBAGTsqEAO5hVzRkrt 05TnNPA8FJAYd/qjf8GfNEVAeiQCPDO8259wSNfOsNPzEuaWFNHW5wmqn/3MhTkl … 2GIIwnnAYGlJ2Q/aJAKtR1j58ygW/++n99+l5/2J9Rw3g3Eap5V3QLJ1qchOAvEq WmrLAoGAEpIYa1atB2Atv0FRravY86HmlWHbfFrfs5ZkBAKzCpNqvo7m/ih69U1v 7DV+b0ejF+lW4Jww5q8htdVln9UgUiLQ8O8HJMwOxa4wGB0KM96nIqRJSmX4DB4r r7VsAT6lLlald/plFO/D/evZe4lTWz6C3n/RgttHueDGj8YqckI= -----END RSA PRIVATE KEY-----
Next create a self-signed root CA certificate ca.crt for MegaCorp:
$ openssl req -new -x509 -days 1826 -key ca.key -out ca.crt You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:UK State or Province Name (full name) [Some-State]:None Locality Name (eg, city) []:Edinburgh Organization Name (eg, company) [Internet Widgits Pty Ltd]:MegaCorp Organizational Unit Name (eg, section) []:None Common Name (e.g. server FQDN or YOUR name) []:None Email Address []:none
Next we will create a subordinate CA (My Little Corp), and which will be used for the signing of the certificate. First, generate the key:
$ openssl genrsa -out ia.key 2048 Generating RSA private key, 2048 bit long modulus ............................................................+++ ...............................................................................................................+++ e is 65537 (0x10001)
Next we will request a certificate for our newly created subordinate CA and create a code signing request (CSR):
$ openssl req -new -key ia.key -out ia.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:UK State or Province Name (full name) [Some-State]:None Locality Name (eg, city) []:Edinburgh Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Little Corp Organizational Unit Name (eg, section) []:MLC Common Name (e.g. server FQDN or YOUR name) []:MLC.none Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:Qwerty123 An optional company name []:
The code signing request has the form of:
-----BEGIN CERTIFICATE REQUEST----- MIICyTCCAbECAQAwajELMAkGA1UEBhMCVUsxDTALBgNVBAgTBE5vbmUxEjAQBgNV BAcTCUVkaW5idXJnaDEXMBUGA1UEChMOTXkgTGl0dGxlIENvcnAxDDAKBgNVBAsT A01MQzERMA8GA1UEAxMITUxDLm5vbmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw … k1b4DqOvInWLOs+yuWT7YYtWdr2TNKPpcBqbzCYzrWL6UaUN7LYFpNn4BbqXRgVw iMAnUh9fvLMe7oreYfTaevXT/506Sj9WvQFXTcLtRhs+M30q22/wUK0ZZ8APjpwf rQMegvzXXEIO3xEGrBi5/wXJxsawRLcM3ZSGPu/Ws950oM5Ahn8K8HBdKubQ -----END CERTIFICATE REQUEST-----
We can then create a certificate from the subordinate CA certificate and signed by the root CA.
$ openssl x509 -req -days 730 -in ia.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out ia.crt Signature ok subject=/C=UK/ST=None/L=Edinburgh/O=My Little Corp/OU=MLC/CN=MLC.none Getting CA Private Key
If we want to use this certificate to digitally sign files and verify the signatures, we need to convert it to a PKCS12 file:
$ openssl pkcs12 -export -out ia.p12 -inkey ia.key -in ia.crt -chain -CAfile ca.crt Enter Export Password: Qwerty123 Verifying - Enter Export Password: Qwerty123
The crt format is in encoded in binary. If we want to export to a Base64 format, we can use DER:
$ openssl x509 -inform pem -outform pem -in ca.crt -out ca.cer
and for My Little Corp:
$ openssl x509 -inform pem -outform pem -in ia.crt -out ia.cer
view of the cer file shows that it is in Base64 format:
-----BEGIN CERTIFICATE----- MIIESzCCAzOgAwIBAgIJAJh3rnD4l1QKMA0GCSqGSIb3DQEBBQUAMHYxCzAJBgNV BAYTAlVLMQ0wCwYDVQQIEwROb25lMRIwEAYDVQQHEwlFZGluYnVyZ2gxETAPBgNV BAoTCE1lZ2FDb3JwMQ0wCwYDVQQLEwROb25lMQ0wCwYDVQQDEwROb25lMRMwEQYJ KoZIhvcNAQkBFgRub25lMB4XDTE3MDYyNTEyNTUxM1oXDTIyMDYyNTEyNTUxM1ow … RT5OLx5sHf1+Dr5CrV0WM5zyt3SrF/vyAMVCBZDzonioPi0mSfCtf0CHPNXEow9v jAxNExKpicVWW+eiT7ZdMzIT1u1aYtgO7T9OCsmIqym/zxZzadvA+3jYjzugfq1W iPivmvWHCq5aiAvyzdqlFTt2AE55Ym16T2vVFbr4kDb9j1+Wuo5Gk+B0o/4rq7A= -----END CERTIFICATE-----
The Base64 format is often used to distribute the certificate through an email.
In the above example, we created a self-signed CA, but if we use a root CA, we will receive a CA Certificate Signing Request (CSR) after the key pair has been created, and which is then sent to a CA in order to create a digital identity certificate. This normally this involves passing the public key along with identity information (such as for a related domain name) and a digital signature. If the request is successful, the CA sends back a signed certificate and which has been signed by the private key of the CA. In the CSR given in the previous example:
The following is the code:
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 sys size=512 name="My company" city="Edinburgh" country="US" site="mysite.org" state="Lothian" if (len(sys.argv)>1): size=int(sys.argv[1]) if (len(sys.argv)>2): name=str(sys.argv[2]) print (f"Name: {name}") print (f"Key size: {size}") print () key = rsa.generate_private_key(public_exponent=65537,key_size=size) st = key.private_bytes(encoding=serialization.Encoding.PEM,format=serialization.PrivateFormat.TraditionalOpenSSL,encryption_algorithm=serialization.BestAvailableEncryption(b"passphrase")) csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, country),x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, state),x509.NameAttribute(NameOID.LOCALITY_NAME, city),x509.NameAttribute(NameOID.ORGANIZATION_NAME, name),x509.NameAttribute(NameOID.COMMON_NAME, site),])).add_extension(x509.SubjectAlternativeName([x509.DNSName(site)]),critical=False).sign(key, hashes.SHA256()) csr_string = csr.public_bytes(serialization.Encoding.PEM) print (f"Private key: {st.decode()}") print (csr_string.decode())
A sample run is:
Name: mysite.com Key size: 512 Private key: -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-256-CBC,0FEA35A3E8AE0C6E9B076F2FD81683B8 EjjI5ucobbC8TywFeTDwI7/x7ngLAYdZoL8vqcifXwpabsTrlstGWLsP9bvxC+ww bAYvlUwQwX9UNHyoiDag0q/NxVN09tPZZmcsHdKHMhMhHIFT6kXXGCOyAwHepvuH L5yNfbWbD9cgR9mAO25j5Cnv1ufn2E3M21U/APqbxDadg57Xw8kaW3ynZLbmSK1W xp4wiqMYTR85leNOCqJFy8cETvcPehRK4485gx0aWEe21c9rxNl2QTdrVpX30BEO VQi3mtAJS3yyuJmHTakDew7doyrvpR5rZWYOF10iCvJWV57664kl87QhZfhs6n8w X3mScyt4HzTV5nPYbyOOem3Bpo2eQgPBUckVkScX/ZGFJFLRoezg1wJir8CebewI Aixdp9jEE0w9U7qfL444HXQ1lUAjHlXqhQbOgC0rNhwzqYejA7rH/MXZLSpqcZAu -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE REQUEST----- MIIBPzCB6gIBADBdMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTG90aGlhbjESMBAG A1UEBwwJRWRpbmJ1cmdoMRMwEQYDVQQKDApteXNpdGUuY29tMRMwEQYDVQQDDApt eXNpdGUub3JnMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL7T++sCuBl+AAc89C/A pL+SZrzbnnphxqULDBI/O5iNxws495s50Bg9S+qyDdrkNTvMsbVTvCt+HhfjPJLz OfMCAwEAAaAoMCYGCSqGSIb3DQEJDjEZMBcwFQYDVR0RBA4wDIIKbXlzaXRlLm9y ZzANBgkqhkiG9w0BAQsFAANBABvmnkxKljIzaNRD2bkCFwMrOFr5emMMl5V2a/p5 GX8XDnOrH8NNFrDYDDKH9GHqj12IQuiVbgp4R6dXYvIj92I= -----END CERTIFICATE REQUEST-----