Skip to content

Commit 7fd179a

Browse files
author
Nolan Rumble
committed
Version 1.07. See CHANGELOG.md
2 parents 1e8b918 + 013c168 commit 7fd179a

File tree

5 files changed

+83
-35
lines changed

5 files changed

+83
-35
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 2023-05-31
2+
## Version 1.07
3+
* Adjusting code to align with better coding practices.
4+
15
# 2023-05-21
26
## Version 1.06
37
* Adjusting code to align with better coding practices.

CryptographySupport/CryptographyFileOperations.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class CryptographyFileOperations:
2121
CLASS_VERSION = 0.01
2222

2323
@staticmethod
24-
def generatePassphrase(__passwordLength: int):
24+
def generatePassphrase(__passwordLength: int) -> str:
2525
"""Generate a random password based on the length supplied."""
2626
# Define the valid letters for the password.
2727
validLetters = "abcdefghijklmnopqrstuvwxyz"

CryptographySupport/CryptographySupport.py

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# Description: Cryptography support
22
# Author: TheScriptGuy
3-
# Last modified: 2023-05-20
4-
# Version: 0.01
3+
# Last modified: 2023-05-31
4+
# Version: 0.02
55

66
from typing import Union
77
from cryptography.hazmat.primitives.asymmetric import rsa, ec
8-
from cryptography.hazmat.primitives import hashes
9-
from cryptography.x509.oid import NameOID
8+
from cryptography.hazmat.primitives import hashes, serialization
9+
from cryptography.x509.oid import NameOID, ExtendedKeyUsageOID
1010
from cryptography import x509
1111

1212

@@ -15,7 +15,7 @@ class CryptographySupport:
1515

1616
PRIVATE_KEY_TYPES = Union[rsa.RSAPrivateKey, ec.EllipticCurvePrivateKey]
1717
PUBLIC_KEY_TYPES = Union[rsa.RSAPublicKey, ec.EllipticCurvePublicKey]
18-
CLASS_VERSION = "0.01"
18+
CLASS_VERSION = "0.02"
1919

2020
@staticmethod
2121
def generate_hash(__hash: str) -> hashes.HashAlgorithm:
@@ -98,6 +98,30 @@ def build_name_attribute(certificateAttributes: dict) -> list:
9898

9999
return name_attribute_list
100100

101+
@staticmethod
102+
def build_extended_key_usage(certificateAttributes: dict) -> list:
103+
"""Build Extended Key Usage list from certificateAttributes."""
104+
attribute_mapping = {
105+
"clientAuth": ExtendedKeyUsageOID.CLIENT_AUTH,
106+
"serverAuth": ExtendedKeyUsageOID.SERVER_AUTH,
107+
"codeSigning": ExtendedKeyUsageOID.CODE_SIGNING,
108+
"emailProtection": ExtendedKeyUsageOID.EMAIL_PROTECTION,
109+
"timeStamping": ExtendedKeyUsageOID.TIME_STAMPING,
110+
"ocspSigning": ExtendedKeyUsageOID.OCSP_SIGNING,
111+
"anyExtendedKeyUsage": ExtendedKeyUsageOID.ANY_EXTENDED_KEY_USAGE
112+
}
113+
114+
attribute_list = []
115+
116+
for value in certificateAttributes['extensions']['extendedKeyUsage']:
117+
if value is None:
118+
continue
119+
elif value in attribute_mapping:
120+
attribute_list.append(attribute_mapping[value])
121+
122+
return attribute_list
123+
124+
101125
def __init__(self):
102126
"""Initialize the class."""
103127
self.initialized = True

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ $ python3 generate-certificate.py -h
2929
usage: generate-certificate.py [-h] [--companyName COMPANYNAME] [--generateRootCA] [--generateClientCertificate] [--generatePKCS12]
3030
[--nonRestrictiveRootCA] [--ecc] [--removeAllCertsAndKeys] [--windowsInstallation]
3131

32-
Certificate Generation v1.06
32+
Certificate Generation v1.07
3333

3434
options:
3535
-h, --help show this help message and exit
@@ -154,7 +154,6 @@ My recommendation is to leave the following fields:
154154

155155
If you'd like to edit how the certificates are generated, you can edit this dict within `def certificateMetaData`:
156156
```python
157-
# Root Certificate Authority information. Edit at your own risk.
158157
certificateInfo["RootCA"] = {
159158
"oid": {
160159
"CN": args.companyName + " Root CA",
@@ -181,7 +180,8 @@ If you'd like to edit how the certificates are generated, you can edit this dict
181180
"digest": "sha512"
182181
},
183182
"extensions": {
184-
"keyUsage": "digitalSignature, nonRepudiation, keyCertSign",
183+
"keyUsage": ["digitalSignature", "nonRepudiation", "keyCertSign"],
184+
"extendedKeyUsage": ["clientAuth"]
185185
}
186186
}
187187

@@ -210,8 +210,8 @@ If you'd like to edit how the certificates are generated, you can edit this dict
210210
"digest": "sha256"
211211
},
212212
"extensions": {
213-
"keyUsage": "digitalSignature, nonRepudiation",
214-
"extendedKeyUsage": "clientAuth"
213+
"keyUsage": ["digitalSignature", "nonRepudiation"],
214+
"extendedKeyUsage": ["clientAuth"]
215215
}
216216
}
217217
```

generate-certificate.py

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Description: Create a Root CA with a client Authentication certificate that's signed by the Root CA.
22
# Author: TheScriptGuy
3-
# Last modified: 2023-05-21
4-
# Version: 1.06
3+
# Last modified: 2023-05-31
4+
# Version: 1.07
55

66
from cryptography import x509
77

@@ -17,7 +17,7 @@
1717
import argparse
1818
import random
1919

20-
scriptVersion = "1.06"
20+
scriptVersion = "1.07"
2121

2222

2323
def certificateMetaData():
@@ -60,7 +60,8 @@ def certificateMetaData():
6060
"digest": "sha512"
6161
},
6262
"extensions": {
63-
"keyUsage": "digitalSignature, nonRepudiation, keyCertSign",
63+
"keyUsage": ["digitalSignature", "nonRepudiation", "keyCertSign"],
64+
"extendedKeyUsage": ["clientAuth"]
6465
}
6566
}
6667

@@ -89,8 +90,8 @@ def certificateMetaData():
8990
"digest": "sha256"
9091
},
9192
"extensions": {
92-
"keyUsage": "digitalSignature, nonRepudiation",
93-
"extendedKeyUsage": "clientAuth"
93+
"keyUsage": ["digitalSignature", "nonRepudiation"],
94+
"extendedKeyUsage": ["clientAuth"]
9495
}
9596
}
9697

@@ -153,20 +154,43 @@ def printWindowsInstallationInstructions(
153154
print(f"C:\\>certutil -importpfx -f -Enterprise -p {__p12Password} {__certificateInfo['ClientAuthentication']['clientCertificatePKCS12']} NoExport")
154155

155156

156-
def createRootCA(__certificateMetaData: dict) -> None:
157-
"""Create a Root CA with the information from the --companyName argument."""
157+
def create_root_private_keys(__certificateMetaData: dict) -> CryptographySupport.CryptographySupport.PRIVATE_KEY_TYPES:
158+
"""Create a private key."""
158159
# First check to see if the --ecc argument was passed. If passed, generate ECC key.
159160
if args.ecc:
160-
rootCAPrivateKey = ec.generate_private_key(
161+
__private_key = ec.generate_private_key(
161162
curve=CryptographySupport.CryptographySupport.generate_curve(__certificateMetaData["RootCA"]["ecc"]["curve"]),
162163
backend=default_backend()
163164
)
164165
else:
165-
rootCAPrivateKey = rsa.generate_private_key(
166+
__private_key = rsa.generate_private_key(
166167
public_exponent=65537,
167168
key_size=__certificateMetaData["RootCA"]["rsa"]["rsa_bits"],
168169
backend=default_backend()
169170
)
171+
return __private_key
172+
173+
174+
def create_client_private_keys(__certificateMetaData: dict) -> CryptographySupport.CryptographySupport.PRIVATE_KEY_TYPES:
175+
"""Create a private key."""
176+
# First check to see if the --ecc argument was passed. If passed, generate ECC key.
177+
if args.ecc:
178+
__private_key = ec.generate_private_key(
179+
curve=CryptographySupport.CryptographySupport.generate_curve(__certificateMetaData["ClientAuthentication"]["ecc"]["curve"]),
180+
backend=default_backend()
181+
)
182+
else:
183+
__private_key = rsa.generate_private_key(
184+
public_exponent=65537,
185+
key_size=__certificateMetaData["ClientAuthentication"]["rsa"]["rsa_bits"],
186+
backend=default_backend()
187+
)
188+
return __private_key
189+
190+
191+
def createRootCA(__certificateMetaData: dict) -> None:
192+
"""Create a Root CA with the information from the --companyName argument."""
193+
rootCAPrivateKey = create_root_private_keys(__certificateMetaData)
170194

171195
rootCAPublicKey = rootCAPrivateKey.public_key()
172196
rootCACertificateBuilder = x509.CertificateBuilder()
@@ -208,9 +232,12 @@ def createRootCA(__certificateMetaData: dict) -> None:
208232
rootCAKeyUsage, True
209233
)
210234

235+
# Create the ExtendedKeyUsage list
236+
rootCAExtendedKeyUsage = CryptographySupport.CryptographySupport.build_extended_key_usage(__certificateMetaData['RootCA'])
237+
211238
# Add extension for only allowing CA to do Client Authentication
212239
rootCACertificateBuilder = rootCACertificateBuilder.add_extension(
213-
x509.ExtendedKeyUsage([x509.OID_CLIENT_AUTH]), critical=True
240+
x509.ExtendedKeyUsage(rootCAExtendedKeyUsage), critical=True
214241
)
215242

216243
# Apply basic constraints to certificate.
@@ -271,22 +298,12 @@ def create_client_certificate(__certificateMetaData: dict) -> None:
271298
"""Create the client certificate and sign it from the root CA created from createRootCA()"""
272299
check_root_ca_files_exist(__certificateMetaData)
273300

274-
# First check to see if the --ecc argument was passed. If passed, generate ECC key.
275-
if args.ecc:
276-
clientPrivateKey = ec.generate_private_key(
277-
curve=CryptographySupport.CryptographySupport.generate_curve(__certificateMetaData["ClientAuthentication"]["ecc"]["curve"]),
278-
backend=default_backend()
279-
)
280-
else:
281-
clientPrivateKey = rsa.generate_private_key(
282-
public_exponent=65537,
283-
key_size=__certificateMetaData["ClientAuthentication"]["rsa"]["rsa_bits"],
284-
backend=default_backend()
285-
)
301+
clientPrivateKey = create_client_private_keys(__certificateMetaData)
286302

287303
clientPublicKey = clientPrivateKey.public_key()
288304

289305
clientNameAttributes = CryptographySupport.CryptographySupport.build_name_attribute(__certificateMetaData['ClientAuthentication'])
306+
290307
clientCertificateBuilder = x509.CertificateBuilder()
291308
clientCertificateBuilder = clientCertificateBuilder.subject_name(x509.Name(clientNameAttributes))
292309

@@ -305,8 +322,11 @@ def create_client_certificate(__certificateMetaData: dict) -> None:
305322
clientCertificateBuilder = clientCertificateBuilder.add_extension(
306323
x509.BasicConstraints(ca=True, path_length=0), critical=True
307324
)
325+
326+
# Add extended key usage extensions to the certificate
327+
clientCertificateExtendedKeyUsage = CryptographySupport.CryptographySupport.build_extended_key_usage(__certificateMetaData['ClientAuthentication'])
308328
clientCertificateBuilder = clientCertificateBuilder.add_extension(
309-
x509.ExtendedKeyUsage([x509.OID_CLIENT_AUTH]), critical=True
329+
x509.ExtendedKeyUsage(clientCertificateExtendedKeyUsage), critical=True
310330
)
311331

312332
# Load Root CA Key

0 commit comments

Comments
 (0)