-
Notifications
You must be signed in to change notification settings - Fork 1
/
server_cert.py
148 lines (129 loc) · 5.16 KB
/
server_cert.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
from cryptography import x509
from cryptography.x509.oid import NameOID, ExtensionOID
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import serialization
from cryptography.x509 import load_pem_x509_certificate
from cryptography.exceptions import InvalidSignature
import datetime
import os
import logging
import sys
logger = logging.getLogger('root')
class ServerCert:
def __init__(self):
self.private_key = None
"""
Generate RSA key pair for certificate
Note: password is hardcoded just for academic purpose
"""
def key_gen(self):
self.private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
if not os.path.exists("server-keys"):
os.mkdir("server-keys")
with open("certs\\certKey.pem" if sys.platform == 'win32'
else "server-keys/certKey.pem", "wb") as f:
f.write(self.private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.BestAvailableEncryption(b'serverSIO'),
))
"""
Generate server self signed certificate
"""
def cert_gen(self):
subject = issuer = x509.Name([
x509.NameAttribute(NameOID.COUNTRY_NAME, u"PT"),
x509.NameAttribute(NameOID.JURISDICTION_LOCALITY_NAME, u"Aveiro"),
x509.NameAttribute(NameOID.LOCALITY_NAME, u"Aveiro"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"SIO"),
x509.NameAttribute(NameOID.COMMON_NAME, u"serverSIO"),
])
if self.private_key is not None:
cert = x509.CertificateBuilder().subject_name(
subject
).issuer_name(
issuer
).public_key(
self.private_key.public_key()
).serial_number(
x509.random_serial_number()
).not_valid_before(
datetime.datetime.utcnow()
).not_valid_after(
datetime.datetime.utcnow() + datetime.timedelta(days=10)
).add_extension(
x509.SubjectAlternativeName([x509.DNSName(u"serversio.io")]),
critical=False,
).add_extension(
x509.BasicConstraints(ca=True, path_length=None)
, critical=True,
).add_extension(
x509.KeyUsage(
digital_signature=True, key_encipherment=True, content_commitment=False,
data_encipherment=False, key_agreement=False, encipher_only=False, decipher_only=False,
key_cert_sign=True, crl_sign=False
),
critical=True
).sign(self.private_key,
hashes.SHA256(),
default_backend())
if not os.path.exists("certs"):
os.mkdir("certs")
with open("certs\\server.pem" if sys.platform == 'win32'
else "certs/server.pem", "wb") as f:
f.write(cert.public_bytes(serialization.Encoding.PEM))
"""
Test validity of server certificate
"""
def is_valid(self, cert):
ca = cert.extensions.get_extension_for_oid(ExtensionOID.BASIC_CONSTRAINTS)
if cert.not_valid_before < datetime.datetime.utcnow() < cert.not_valid_after and ca.value.ca:
try:
cert.public_key().verify(cert.signature, cert.tbs_certificate_bytes, padding.PKCS1v15(),
cert.signature_hash_algorithm)
except InvalidSignature:
return False
return True
else:
return False
def load_cert(self):
with open("certs\\server.pem" if sys.platform == 'win32'
else "certs/server.pem", "rb") as f:
cert = f.read()
return load_pem_x509_certificate(cert, default_backend())
def load_privKey_cert(self):
with open("certs\\server.pem" if sys.platform == 'win32'
else "server-keys/certKey.pem", "rb") as key:
return serialization.load_pem_private_key(
key.read(),
password=b'serverSIO',
backend=default_backend()
)
def main():
"""
Main function that invoke method to create certificate if none exists or
test validity this exists, if validity fails generate a new certificate
"""
s = ServerCert()
if not os.path.exists("certs\\server.pem" if sys.platform == 'win32'
else "certs/server.pem"):
logger.info("No certificate found, Generating")
s.key_gen()
s.cert_gen()
else:
cert = s.load_cert()
if s.is_valid(cert):
logger.info("Certificate still valid")
else:
logger.error("Certificate expired generating a new one")
s.key_gen()
s.cert_gen()
# to test module
# if __name__ == '__main__':
# main()