Revize 36409852
Přidáno uživatelem Stanislav Král před asi 4 roky(ů)
src/services/cryptography.py | ||
---|---|---|
1 |
import subprocess |
|
2 | 1 |
import re |
2 |
import subprocess |
|
3 |
import time |
|
3 | 4 |
|
4 |
# encryption method to be used when generating private keys |
|
5 | 5 |
from src.model.subject import Subject |
6 | 6 |
from src.utils.temporary_file import TemporaryFile |
7 | 7 |
|
8 |
# encryption method to be used when generating private keys |
|
8 | 9 |
PRIVATE_KEY_ENCRYPTION_METHOD = "-aes256" |
9 | 10 |
|
10 | 11 |
# openssl executable name |
11 | 12 |
OPENSSL_EXECUTABLE = "openssl" |
12 | 13 |
|
14 |
# format of NOT_BEFORE NOT_AFTER date fields |
|
15 |
NOT_AFTER_BEFORE_DATE_FORMAT = "%b %d %H:%M:%S %Y %Z" |
|
16 |
|
|
13 | 17 |
|
14 | 18 |
class CryptographyService: |
15 | 19 |
|
... | ... | |
187 | 191 |
:param issuer_key: string containing the private key of the issuer's certificate in PEM format |
188 | 192 |
:param issuer_pem: string containing the certificate of the issuer that will sign this CSR in PEM format |
189 | 193 |
:param issuer_key: string containing the private key of the issuer's certificate in PEM format |
190 |
:param subject_key_pass: string containing the passphrase of the private key used when creating the certificate in PEM
|
|
191 |
format |
|
194 |
:param subject_key_pass: string containing the passphrase of the private key used when creating the certificate |
|
195 |
in PEM format
|
|
192 | 196 |
:param issuer_key_pass: string containing the passphrase of the private key of the issuer's certificate in PEM |
193 | 197 |
format |
194 | 198 |
:param extensions: extensions to be applied when creating the certificate |
... | ... | |
229 | 233 |
|
230 | 234 |
def parse_cert_pem(self, cert_pem): |
231 | 235 |
""" |
232 |
Parses the given certificate in PEM format and returns the subject of the certificate |
|
236 |
Parses the given certificate in PEM format and returns the subject of the certificate and it's NOT_BEFORE |
|
237 |
and NOT_AFTER field |
|
233 | 238 |
:param cert_pem: a certificated in a PEM format to be parsed |
234 |
:return: a subject stored within the supplied certificate
|
|
239 |
:return: a tuple containing a subject, NOT_BEFORE and NOT_AFTER dates
|
|
235 | 240 |
""" |
236 | 241 |
# run openssl x509 to view certificate content |
237 |
args = ["x509", "-noout", "-text", "-in", "-"] |
|
238 |
result = self.__run_for_output(args, proc_input=bytes(cert_pem, encoding="utf-8")).decode() |
|
242 |
args = ["x509", "-noout", "-subject", "-startdate", "-enddate", "-in", "-"] |
|
239 | 243 |
|
240 |
# find the line containing the subject |
|
241 |
match = re.search(r"Subject:\s(.*)", result) |
|
244 |
cert_info_raw = self.__run_for_output(args, proc_input=bytes(cert_pem, encoding="utf-8")).decode() |
|
245 |
|
|
246 |
# split lines |
|
247 |
results = re.split("\n", cert_info_raw) |
|
248 |
subj_line = results[0] |
|
249 |
not_before_line = results[1] |
|
250 |
not_after_line = results[2] |
|
251 |
|
|
252 |
# attempt to extract subject via regex |
|
253 |
match = re.search(r"subject=(.*)", subj_line) |
|
242 | 254 |
if match is None: |
243 | 255 |
# TODO use logger |
244 |
print(f"Could not find subject to parse: {result}")
|
|
256 |
print(f"Could not find subject to parse: {subj_line}")
|
|
245 | 257 |
return None |
246 | 258 |
else: |
247 |
# find all attributes (key = value |
|
248 |
found = re.findall(r"\s?([^c=\s]+)\s?=\s?([^,\n]+)", match.group()) |
|
259 |
# find all attributes (key = value)
|
|
260 |
found = re.findall(r"\s?([^c=\s]+)\s?=\s?([^,\n]+)", match.group(1))
|
|
249 | 261 |
subj = Subject() |
250 | 262 |
for key, value in found: |
263 |
print(f"{key}:{value}") |
|
251 | 264 |
if key == "C": |
252 | 265 |
subj.country = value |
253 | 266 |
elif key == "ST": |
... | ... | |
262 | 275 |
subj.common_name = value |
263 | 276 |
elif key == "emailAddress": |
264 | 277 |
subj.email_address = value |
265 |
return subj |
|
278 |
|
|
279 |
# extract notBefore and notAfter date fields |
|
280 |
not_before = re.search(r"notBefore=(.*)", not_before_line) |
|
281 |
not_after = re.search(r"notAfter=(.*)", not_after_line) |
|
282 |
|
|
283 |
# if date fields are found parse them into date objects |
|
284 |
if not_before is not None: |
|
285 |
not_before = time.strptime(not_before.group(1), NOT_AFTER_BEFORE_DATE_FORMAT) |
|
286 |
if not_after is not None: |
|
287 |
not_after = time.strptime(not_after.group(1), NOT_AFTER_BEFORE_DATE_FORMAT) |
|
288 |
|
|
289 |
# TODO wrapper class? |
|
290 |
# return it as a tuple |
|
291 |
return subj, not_before, not_after |
|
266 | 292 |
|
267 | 293 |
|
268 | 294 |
class CryptographyException(Exception): |
Také k dispozici: Unified diff
Re #8472 - Improved parse_cert_pem method in such way that it also parses notBefore and notAfter fields now