def update_CA(self, s: socket.socket, subject, pubkey): """ Equipments don't know each other and they need to exchange their certificate. The auth by DA failed. :pubkey is the pubkey of the other equipment """ # send our certificate on its public key cert_to_sent = X509Certificate( issuer=self.name, subject=subject, public_key=pubkey, private_key=self.key_pair.private_key(), validity_days=10, ) sendall(s, cert_to_sent.cert_pem()) # received its certificate on our public key cert_received = X509Certificate.load_from_pem(recv_all(s)) if not X509Certificate.verify(cert_received, pubkey): print("update_CA FAILS cause the cert received is not valid") return self.CA.add(AutorityProof(pubkey, cert_received)) print("CA update finished")
def test_chain_0_element(self): """ Should raise an error cause there is no chain """ chain = [] kp = KeyPair() with pytest.raises(ValueError): X509Certificate.verify_chain(kp.public_key(), chain, kp.public_key())
def test_selfsigned_cert(self): kp = KeyPair() cert = X509Certificate( issuer="issuer", subject="subject", public_key=kp.public_key(), private_key=kp.private_key(), validity_days=10, ) X509Certificate.verify(cert, kp.public_key())
def test_cert_to_pem_to_cert(self): kp = KeyPair() cert1 = X509Certificate( issuer="issuer", subject="subject", public_key=kp.public_key(), private_key=kp.private_key(), validity_days=10, ) cert2 = X509Certificate.load_from_pem(cert1.cert_pem()) assert cert1 == cert2
def test_wrong_pubkey(self): pubkey_to_signed = KeyPair().public_key() kp_root = KeyPair() cert = X509Certificate( issuer="issuer", subject="subject", public_key=pubkey_to_signed, private_key=kp_root.private_key(), validity_days=10, ) assert not X509Certificate.verify(cert, pubkey_to_signed)
def test_chain_1_element(self): """" An equipment automaticaly verify a chain with only it inside """ chain = [] kp = KeyPair() cert = X509Certificate( issuer="issuer", subject="subject", public_key=kp.public_key(), private_key=kp.private_key(), validity_days=10, ) chain.append(cert) X509Certificate.verify_chain(kp.public_key(), chain, kp.public_key())
def update_DA(self, s: socket.socket): """ Send in the socket s, all certificates in personal CA and DA """ self.DA.update(self.CA) for autorities in (self.CA, self.DA): # json is better with string, not bytes -> encode() / decode() _set = {} for autority in autorities: k = KeyPair.pubkey_pem(autority.issuer_key).decode() v = autority.cert_from_issuer.cert_pem().decode() _set[k] = v sendall(s, json.dumps(_set).encode()) _received_json = recv_json(s) for (key, value) in _received_json.items(): self.DA.add( AutorityProof( issuer_key=KeyPair.load_pub_from_pem(key.encode()), cert_from_issuer=X509Certificate.load_from_pem( value.encode()), )) print("DA update finished")
def __init__(self, name: str, port: int): self.name = name self.port = port self.CA: Set[AutorityProof] = set() # Certification autorities self.DA: Set[AutorityProof] = set() # Derived autorities self.key_pair = KeyPair() self.certificate = X509Certificate( self.name, self.name, self.key_pair.public_key(), self.key_pair.private_key(), 10, ) print("Is my cert valid ? {} ".format( X509Certificate.verify(self.certificate, self.key_pair.public_key()))) print(self)
def hand_shake(self, s: socket.socket) -> X509Certificate: """ Exchanges selfsigned certificate with another equipment and verifies it """ self.clean_sets() # send selfsigned certificate sendall(s, self.certificate.cert_pem()) # received the other's selfsigned certificate cert_selfsigned_received = X509Certificate.load_from_pem(recv_all(s)) other_cert_pubkey = cert_selfsigned_received.public_key() if not X509Certificate.verify(cert_selfsigned_received, other_cert_pubkey): raise NotValidCertificate( "hand_shake FAILS cause of invalid certificate") return cert_selfsigned_received
def test_certEqcert_names(self): kp = KeyPair() cert1 = X509Certificate( issuer="issuer", subject="subject", public_key=kp.public_key(), private_key=kp.private_key(), validity_days=10, ) cert2 = X509Certificate( issuer="other_issuer", subject="other_subject", public_key=kp.public_key(), private_key=kp.private_key(), validity_days=10, ) with pytest.raises(AssertionError): assert cert1 == cert2 assert cert1 != cert2
def clean_sets(self): """ clean CA and DA sets before any communications with other equipment. Out of date certificates are deleted """ for autority_set in (self.CA, self.DA): autority_set = { autority for autority in autority_set if X509Certificate.verify( autority.cert_from_issuer, autority.issuer_key) }
def test_chain_X_elements(self, cert_count): """ Chain with X valid certificates """ chain = [] kp_root = KeyPair() privkey = kp_root.private_key() for i in range(cert_count): kp_next = KeyPair() pubkey = kp_next.public_key() cert = X509Certificate( issuer="issuer", subject="subject", public_key=kp_next.public_key(), private_key=privkey, validity_days=10, ) privkey = kp_next.private_key() chain.append(cert) X509Certificate.verify_chain(kp_root.public_key(), chain, pubkey)
def is_known_by_DA(self, s: socket.socket, pubkey_other) -> bool: cert_chain = self.create_cert_chain(pubkey_other) set_to_send = [] for cert in cert_chain: d = cert.cert_pem().decode() set_to_send.append(d) sendall(s, json.dumps(set_to_send).encode()) cert_chain_received = recv_json(s) cert_chain_received = [ X509Certificate.load_from_pem(cert.encode()) for cert in cert_chain_received ] print("Cert chain exchanged") if len(cert_chain) != 0: print("I CAN reach the other one, no more question on my side") return True elif len(cert_chain_received) == 0: print("NONE of us can reach the other one with a cert chain") return False elif not X509Certificate.verify_chain( self.key_pair.public_key(), cert_chain_received, pubkey_other): # the other one a cert chain. Is it valid ? print( "I cannot generate a cert chain and the cert chain received is NOT valid" ) return False print( "I cannot generate a cert chain BUT the cert chain received IS valid" ) return True
def test_gen_good_chain_line(self): """ tests weither equipment A can create a chain to B via C B -> C -> A """ equipmentA = Equipment(name="name", port=8888) chain = set() kp_B = KeyPair() kp_C = KeyPair() kp_A = equipmentA.key_pair cert_BC = X509Certificate( issuer="B", subject="C", public_key=kp_C.public_key(), private_key=kp_B.private_key(), validity_days=10, ) cert_CA = X509Certificate( issuer="C", subject="A", public_key=kp_A.public_key(), private_key=kp_C.private_key(), validity_days=10, ) equipmentA.DA.add( AutorityProof(issuer_key=kp_B.public_key(), cert_from_issuer=cert_BC) ) equipmentA.DA.add( AutorityProof(issuer_key=kp_C.public_key(), cert_from_issuer=cert_CA) ) assert equipmentA.create_cert_chain(kp_B.public_key()) == [cert_BC, cert_CA]
def is_in_CA(self, issuer_key) -> bool: """ check if the a issuer_key is a known issuer_key of an AutorityProof is CA and if the associated cert is good """ certs = [ autority.cert_from_issuer for autority in self.CA if autority.issuer_key.public_numbers() == issuer_key.public_numbers() ] if len(certs) == 0: return False else: cert = certs.pop() if not X509Certificate.verify(cert, issuer_key): return False return True
def test_gen_good_chain_dual(self): r""" tests weither equipment A can create a chain to B and then to D B -> C -> A \ / D -> E """ equipmentA = Equipment(name="name", port=8888) chain = set() kp_B = KeyPair() kp_C = KeyPair() kp_A = equipmentA.key_pair kp_D = KeyPair() kp_E = KeyPair() cert_BC = X509Certificate( issuer="B", subject="C", public_key=kp_C.public_key(), private_key=kp_B.private_key(), validity_days=10, ) equipmentA.DA.add(AutorityProof(kp_B.public_key(), cert_BC)) cert_BD = X509Certificate( issuer="B", subject="D", public_key=kp_D.public_key(), private_key=kp_B.private_key(), validity_days=10, ) equipmentA.DA.add(AutorityProof(kp_B.public_key(), cert_BD)) cert_DE = X509Certificate( issuer="D", subject="E", public_key=kp_E.public_key(), private_key=kp_D.private_key(), validity_days=10, ) equipmentA.DA.add(AutorityProof(kp_D.public_key(), cert_DE)) cert_EA = X509Certificate( issuer="E", subject="A", public_key=kp_A.public_key(), private_key=kp_E.private_key(), validity_days=10, ) equipmentA.DA.add(AutorityProof(kp_E.public_key(), cert_EA)) cert_CA = X509Certificate( issuer="C", subject="A", public_key=kp_A.public_key(), private_key=kp_C.private_key(), validity_days=10, ) equipmentA.DA.add(AutorityProof(kp_C.public_key(), cert_CA)) assert equipmentA.create_cert_chain(kp_B.public_key()) == [cert_BC, cert_CA] assert equipmentA.create_cert_chain(kp_D.public_key()) == [cert_DE, cert_EA]
def load(cls, tupl: Tuple[bytes, bytes]) -> "AutorityProof": return cls(KeyPair.load_pub_from_pem(tupl[0]), X509Certificate.load_from_pem(tupl[1]))