Revize 9a55ea8a
Přidáno uživatelem Stanislav Král před téměř 4 roky(ů)
src/services/cryptography.py | ||
---|---|---|
1 | 1 |
import re |
2 | 2 |
import subprocess |
3 | 3 |
import time |
4 |
import random |
|
4 | 5 |
|
5 | 6 |
from src.model.subject import Subject |
6 | 7 |
from src.utils.temporary_file import TemporaryFile |
... | ... | |
24 | 25 |
|
25 | 26 |
CA_EXTENSIONS = "basicConstraints=critical,CA:TRUE" |
26 | 27 |
|
28 |
# upper bound of the range of random serial numbers to be generated |
|
29 |
MAX_SN = 4294967296 |
|
30 |
|
|
27 | 31 |
|
28 | 32 |
class CryptographyService: |
29 | 33 |
|
... | ... | |
102 | 106 |
return self.__run_for_output( |
103 | 107 |
["genrsa", PRIVATE_KEY_ENCRYPTION_METHOD, "-passout", f"pass:{passphrase}", "2048"]).decode() |
104 | 108 |
|
105 |
def create_sscrt(self, subject, key, config="", extensions="", key_pass=None, days=30): |
|
109 |
def create_sscrt(self, subject, key, config="", extensions="", key_pass=None, days=30, sn: int =None):
|
|
106 | 110 |
""" |
107 | 111 |
Creates a root CA |
108 | 112 |
|
... | ... | |
112 | 116 |
:param extensions: name of the section in the configuration representing extensions |
113 | 117 |
:param key_pass: passphrase of the private key |
114 | 118 |
:param days: number of days for which the certificate will be valid |
119 |
:param sn: serial number to be set, when "None" is set a random serial number is generated |
|
115 | 120 |
|
116 | 121 |
:return: string containing the generated certificate in PEM format |
117 | 122 |
""" |
... | ... | |
133 | 138 |
args = ["req", "-x509", "-new", "-subj", subj, "-days", f"{days}", |
134 | 139 |
"-key", "-"] |
135 | 140 |
|
141 |
# serial number passed, use it when generating the certificate, |
|
142 |
# without passing it openssl generates a random one |
|
143 |
if sn is not None: |
|
144 |
args.extend(["-set_serial", str(sn)]) |
|
145 |
|
|
136 | 146 |
if len(config) > 0: |
137 | 147 |
args.extend(["-config", conf_path]) |
138 | 148 |
if len(extensions) > 0: |
... | ... | |
167 | 177 |
|
168 | 178 |
return self.__run_for_output(args, proc_input=bytes(key, encoding="utf-8")).decode() |
169 | 179 |
|
170 |
def __sign_csr(self, csr, issuer_pem, issuer_key, issuer_key_pass=None, extensions="", days=30): |
|
180 |
def __sign_csr(self, csr, issuer_pem, issuer_key, issuer_key_pass=None, extensions="", days=30, sn: int = None):
|
|
171 | 181 |
""" |
172 | 182 |
Signs the given CSR by the given issuer CA |
173 | 183 |
|
... | ... | |
178 | 188 |
format |
179 | 189 |
:param extensions: extensions to be applied when signing the CSR |
180 | 190 |
:param days: number of days for which the certificate will be valid |
191 |
:param sn: serial number to be set, when "None" is set a random serial number is generated |
|
181 | 192 |
:return: string containing the generated and signed certificate in PEM format |
182 | 193 |
""" |
183 | 194 |
|
184 | 195 |
# concatenate CSR, issuer certificate and issuer's key (will be used in the openssl call) |
185 | 196 |
proc_input = csr + issuer_pem + issuer_key |
186 | 197 |
|
198 |
# TODO find a better way to generate a random serial number or let openssl generate a .srl file |
|
199 |
# when serial number is not passed generate a random one |
|
200 |
if sn is None: |
|
201 |
sn = random.randint(0, MAX_SN) |
|
202 |
|
|
187 | 203 |
# prepare openssl parameters... |
188 | 204 |
# CSR, CA and CA's private key will be passed via stdin (that's the meaning of the '-' symbol) |
189 | 205 |
params = ["x509", "-req", "-in", "-", "-CA", "-", "-CAkey", "-", "-CAcreateserial", "-days", str(days)] |
... | ... | |
202 | 218 |
|
203 | 219 |
def create_crt(self, subject, subject_key, issuer_pem, issuer_key, subject_key_pass=None, issuer_key_pass=None, |
204 | 220 |
extensions="", |
205 |
days=30): |
|
221 |
days=30, |
|
222 |
sn: int = None): |
|
206 | 223 |
""" |
207 | 224 |
Creates a certificate by using the given subject, subject's key, issuer and its key. |
208 | 225 |
|
... | ... | |
216 | 233 |
format |
217 | 234 |
:param extensions: extensions to be applied when creating the certificate |
218 | 235 |
:param days: number of days for which the certificate will be valid |
236 |
:param sn: serial number to be set, when "None" is set a random serial number is generated |
|
219 | 237 |
:return: string containing the generated certificate in PEM format |
220 | 238 |
""" |
221 | 239 |
csr = self.__create_csr(subject, subject_key, key_pass=subject_key_pass) |
222 | 240 |
return self.__sign_csr(csr, issuer_pem, issuer_key, issuer_key_pass=issuer_key_pass, extensions=extensions, |
223 |
days=days) |
|
241 |
days=days, sn=sn)
|
|
224 | 242 |
|
225 | 243 |
@staticmethod |
226 | 244 |
def verify_cert(certificate): |
Také k dispozici: Unified diff
Re #8575 - Added a "sn" parameter to some CryptographyService