def public_numbers(self): p = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_pqg(self._dh_cdata, p, self._backend._ffi.NULL, g) self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) pub_key = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_key(self._dh_cdata, pub_key, self._backend._ffi.NULL) self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) return dh.DHPublicNumbers( parameter_numbers=dh.DHParameterNumbers( p=self._backend._bn_to_int(p[0]), g=self._backend._bn_to_int(g[0]) ), y=self._backend._bn_to_int(pub_key[0]) )
def post_dissection(self, m): """ First we update the client DHParams. Then, we try to update the server DHParams generated during Server*DHParams building, with the shared secret. Finally, we derive the session keys and update the context. """ s = self.tls_session if s.client_kx_ffdh_params: y = pkcs_os2ip(self.dh_Yc) param_numbers = s.client_kx_ffdh_params.parameter_numbers() public_numbers = dh.DHPublicNumbers(y, param_numbers) s.client_kx_pubkey = public_numbers.public_key(default_backend()) if s.server_kx_privkey and s.client_kx_pubkey: ZZ = s.server_kx_privkey.exchange(s.client_kx_pubkey) s.pre_master_secret = ZZ s.compute_ms_and_derive_keys()
def test_dh_serialization_with_q_unsupported(self, backend, vector): parameters = dh.DHParameterNumbers(int(vector["p"], 16), int(vector["g"], 16), int(vector["q"], 16)) public = dh.DHPublicNumbers(int(vector["ystatcavs"], 16), parameters) private = dh.DHPrivateNumbers(int(vector["xstatcavs"], 16), public) private_key = private.private_key(backend) public_key = private_key.public_key() with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION): private_key.private_bytes(serialization.Encoding.PEM, serialization.PrivateFormat.PKCS8, serialization.NoEncryption()) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION): public_key.public_bytes( serialization.Encoding.PEM, serialization.PublicFormat.SubjectPublicKeyInfo) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_SERIALIZATION): parameters.parameters(backend).parameter_bytes( serialization.Encoding.PEM, serialization.ParameterFormat.PKCS3)
def test_convert_to_numbers(self, backend): parameters = backend.generate_dh_private_key_and_parameters(2, 512) private = parameters.private_numbers() p = private.public_numbers.parameter_numbers.p g = private.public_numbers.parameter_numbers.g params = dh.DHParameterNumbers(p, g) public = dh.DHPublicNumbers(1, params) private = dh.DHPrivateNumbers(2, public) deserialized_params = params.parameters(backend) deserialized_public = public.public_key(backend) deserialized_private = private.private_key(backend) assert isinstance(deserialized_params, dh.DHParametersWithSerialization) assert isinstance(deserialized_public, dh.DHPublicKeyWithSerialization) assert isinstance(deserialized_private, dh.DHPrivateKeyWithSerialization)
def register_pubkey(self): if self.group in _tls_named_ffdh_groups: params = _ffdh_groups[_tls_named_ffdh_groups[self.group]][0] pn = params.parameter_numbers() public_numbers = dh.DHPublicNumbers(self.key_exchange, pn) self.pubkey = public_numbers.public_key(default_backend()) elif self.group in _tls_named_curves: if _tls_named_curves[self.group] == "x25519": if conf.crypto_valid_advanced: import_point = x25519.X25519PublicKey.from_public_bytes self.pubkey = import_point(self.key_exchange) elif _tls_named_curves[self.group] != "x448": curve = ec._CURVE_TYPES[_tls_named_curves[self.group]]() try: # cryptography >= 2.5 import_point = ec.EllipticCurvePublicKey.from_encoded_point # noqa: E501 self.pubkey = import_point(curve, self.key_exchange) except AttributeError: import_point = ec.EllipticCurvePublicNumbers.from_encoded_point # noqa: E501 pub_num = import_point( curve, self.key_exchange).public_numbers() # noqa: E501 self.pubkey = pub_num.public_key(default_backend())
def public_numbers(self) -> dh.DHPublicNumbers: p = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") q = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_pqg(self._dh_cdata, p, q, g) self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) if q[0] == self._backend._ffi.NULL: q_val = None else: q_val = self._backend._bn_to_int(q[0]) pub_key = self._backend._ffi.new("BIGNUM **") self._backend._lib.DH_get0_key(self._dh_cdata, pub_key, self._backend._ffi.NULL) self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) return dh.DHPublicNumbers( parameter_numbers=dh.DHParameterNumbers( p=self._backend._bn_to_int(p[0]), g=self._backend._bn_to_int(g[0]), q=q_val, ), y=self._backend._bn_to_int(pub_key[0]), )
def test_symmetric_key_padding(self, backend): """ This test has specific parameters that produce a symmetric key In length 63 bytes instead 64. We make sure here that we add padding to the key. """ p = int("11859949538425015739337467917303613431031019140213666" "129025407300654026585086345323066284800963463204246390" "256567934582260424238844463330887962689642467123") g = 2 y = int("32155788395534640648739966373159697798396966919821525" "72238852825117261342483718574508213761865276905503199" "969908098203345481366464874759377454476688391248") x = int("409364065449673443397833358558926598469347813468816037" "268451847116982490733450463194921405069999008617231539" "7147035896687401350877308899732826446337707128") parameters = dh.DHParameterNumbers(p, g) public = dh.DHPublicNumbers(y, parameters) private = dh.DHPrivateNumbers(x, public) key = private.private_key(backend) symkey = key.exchange(public.public_key(backend)) assert len(symkey) == 512 // 8 assert symkey[:1] == b"\x00"
def create_dh_public_key(public_key_num: int): pn = dh.DHParameterNumbers(p, g) public_numbers = dh.DHPublicNumbers(public_key_num, pn) public_key = public_numbers.public_key(default_backend()) return public_key
def decomposePeerKey(self,pubBobKey,pn): # Through Alice's public key creates object that allows you to compute the shared key peer_public_numbers = dh.DHPublicNumbers(pubBobKey, pn) peer_public_keyBob = peer_public_numbers.public_key(default_backend()) return peer_public_keyBob
from cryptography.hazmat.primitives.asymmetric import dh from cryptography.utils import int_from_bytes backend = default_backend() p = int("11859949538425015739337467917303613431031019140213666" "12902540730065402658508634532306628480096346320424639" "0256567934582260424238844463330887962689642467123") g = 2 y = int("32155788395534640648739966373159697798396966919821525" "72238852825117261342483718574508213761865276905503199" "969908098203345481366464874759377454476688391248") x = int("409364065449673443397833358558926598469347813468816037" "268451847116982490733450463194921405069999008617231539" "7147035896687401350877308899732826446337707128") params = dh.DHParameterNumbers(p, g) public = dh.DHPublicNumbers(y, params) private = dh.DHPrivateNumbers(x, public) key = private.private_key(backend) shared_key = key.exchange(public.public_key(backend)) # check shared key shared_key = int_from_bytes(shared_key, 'big') shared_key_manual = pow(y, x, p) # y^x mod p assert shared_key == shared_key_manual
def process(self, msg): """ Processa uma mensagem (`bytestring`) enviada pelo CLIENTE. Retorna a mensagem a transmitir como resposta (`None` para finalizar ligação) """ self.msg_cnt += 1 if (msg[:1] == b'P'): P = 99494096650139337106186933977618513974146274831566768179581759037259788798151499814653951492724365471316253651463342255785311748602922458795201382445323499931625451272600173180136123245441204133515800495917242011863558721723303661523372572477211620144038809673692512025566673746993593384600667047373692203583 G = 44157404837960328768872680677686802650999163226766694797650810379076416463147265401084491113667624054557335394761604876882446924929840681990106974314935015501571333024773172440352475358750668213444607353872754650805031912866692119819377041901642732455911509867728218394542745330014071040326856846990119719675 global pn global private_key global derived_key pn = dh.DHParameterNumbers(P, G) parameters = pn.parameters(default_backend()) #chave privada do server #parameters = dh.generate_parameters(generator=2, key_size=2048, backend=default_backend()) private_key = parameters.generate_private_key() #gerar chave publica public_key = private_key.public_key() public_key_server = public_key.public_numbers().y res = 'P' + str(G) + str(P) + str(public_key_server) ress = res.encode() msg = ress return msg elif (msg[:1] == b'S'): public_key_cliente = int(msg[1:].decode()) #CALCULAR exchange peerPublicNumbers = dh.DHPublicNumbers(public_key_cliente, pn) peer_key = peerPublicNumbers.public_key(default_backend()) shared_key = private_key.exchange(peer_key) # Perform key derivation. derived_key = HKDF(algorithm=hashes.SHA512(), length=24, salt=None, info=b'handshake data', backend=default_backend()).derive(shared_key) msg2s = '1' msg2 = str(msg2s).encode() return msg2 elif (msg[:1] == b'C'): iv_cl = msg[1:17] mac_cli = msg[17:49] texto = msg[49:] cipher = Cipher(algorithms.AES(derived_key), modes.CTR(iv_cl), backend=backend) decryptor = cipher.decryptor() txt = decryptor.update(texto) #print("txt") #print(txt) #txt=txt.decode() #h=hmac.HMAC(key,hashes.SHA256(),backend=default_backend()) #h.update(texto) #h.copy().verify(mac_cli) print('%d : %r' % (self.id, txt)) #if(h.copy().verify(mac_cli)): # print("mensagem recebida correta") # print('Recebi (%d): %r' % (self.msg_cnt , msg)) #else: # printf("mensagem recebida está errada") # print('%d : %r' % (self.id,t)) #new = txt.upper().encode() iv_s = os.urandom(16) cipher = Cipher(algorithms.AES(derived_key), modes.CTR(iv_s), backend=backend) encryptor = cipher.encryptor() ct = encryptor.update(txt) + encryptor.finalize() #################################### #HMAC h = hmac.HMAC(key_mac, hashes.SHA256(), backend=default_backend()) h.update(ct) mac_serv = h.finalize() carater = b'2' new_msg = carater + iv_s + mac_serv + ct ######################## return new_msg if len(new_msg) > 0 else None
def df_public_from_bytes(public_bytes): y = int.from_bytes(public_bytes, byteorder='big') peer_public_numbers = dh.DHPublicNumbers( y, _DH_PARAMETERS.parameter_numbers()) return peer_public_numbers.public_key(default_backend())
def on_message(client, userdata, msg): global name global mode global asymmetric_mode global symmetric_mode global b_public_key global b_public_key_ecdh global a_shared_key global f_key global a_key global h global hmac_key print(msg.topic + " -> " + str(msg.payload.decode())) # Connection message if (msg.topic == "connection"): print("Connection message.") # Initialize some variables name = str(msg.payload.decode()).split(":")[0] mode = str(msg.payload.decode()).split(":")[1] asymmetric_mode = int(str(msg.payload.decode()).split(":")[2]) symmetric_mode = int(str(msg.payload.decode()).split(":")[3]) # Save the variables for each device names.append(name) modes.append(mode) asymmetric_modes.append(asymmetric_mode) symmetric_modes.append(symmetric_mode) # Key exchange if (asymmetric_mode == 0): client.publish(name + "/to", "param:" + str(params_pem, 'ascii')) client.publish(name + "/to", "public:" + str(a_public_key.public_numbers().y)) else: client.publish( name + "/to", "public:" + a_public_key_ecdh.public_bytes( encoding=Encoding.PEM, format=PublicFormat.SubjectPublicKeyInfo).decode()) client.subscribe(name + "/from") print("Public key sent to device.") # Show the information on web page data = { "type": "conexion_dispositivo", "payload": msg.payload.decode() } server.send_message_to_all(json.dumps(data)) # Message from a device that has already connected else: # Topic = <Device name>/from name = str(msg.topic).split("/")[0] if (msg.topic == (name + "/from")): # Receive device public key if (str(msg.payload.decode()).split(":")[0] == "public"): # If we know its old public key, we upload it try: public_keys.pop(names.index(name)) shared_keys.pop(names.index(name)) fernet_keys.pop(names.index(name)) aead_keys.pop(names.index(name)) print("Public key uploaded from device.") # If we don't know its public key, we save it except IndexError: # If the device has 'output' or nothing if (int(mode) > 0): # HMAC key will be introduced on web page data = {"type": "hmac", "name": name, "mode": mode} # If the device has just 'input' else: # HMAC key will be introduced on device hmac_key = str(os.urandom(2).hex()) data = { "type": "hmac", "name": name, "mode": mode, "hmac_key": hmac_key } # Show the correspondent information on web page server.send_message_to_all(json.dumps(data)) print("New public key from device.") # DH key exchange if (asymmetric_modes[names.index(name)] == 0): b_public_key_number = int( str(msg.payload.decode()).split(":")[1]) peer_public_numbers = dh.DHPublicNumbers( b_public_key_number, parameters.parameter_numbers()) b_public_key = peer_public_numbers.public_key( default_backend()) public_keys.insert(names.index(name), b_public_key) a_shared_key = a_private_key.exchange(b_public_key) # ECDH key exchange else: b_public_key_number = str( msg.payload.decode()).split(":")[1] b_public_key_ecdh = load_pem_public_key( b_public_key_number.encode()) a_shared_key = a_private_key_ecdh.exchange( ec.ECDH(), b_public_key_ecdh) print("Shared key calculated.") # Save the shared key shared_keys.insert(names.index(name), a_shared_key) # We fix the shared key for Fernet using HASH and save it derived_key_fernet = HKDF( algorithm=hashes.SHA256(), length=32, salt=None, info=b'handshake data').derive(a_shared_key) key_fernet = base64.urlsafe_b64encode(derived_key_fernet) f_key = Fernet(key_fernet) fernet_keys.insert(names.index(name), f_key) # We fix the shared key for AEAD using HASH and save it derived_key_aead = HKDF( algorithm=hashes.SHA256(), length=24, salt=None, info=b'handshake data').derive(a_shared_key) key_aead = base64.urlsafe_b64encode(derived_key_aead) a_key = aead.AESGCM(key_aead) aead_keys.insert(names.index(name), a_key) # Receive HMAC from device elif (str(msg.payload.decode()).split(":")[0] == "hmac"): # Save received HMAC print("HMAC recibida del dispositivo.") h = str(msg.payload.decode()).split(":")[1] # If the device has just 'input' if (int(mode) == 0): # DH or ECDH if (asymmetric_mode == 0): h2 = hmac.new( bytes(hmac_key, 'ascii'), bytes(str(b_public_key.public_numbers().y), 'ascii'), hashlib.sha256) else: h2 = hmac.new( bytes(hmac_key, 'ascii'), b_public_key_ecdh.public_bytes( encoding=Encoding.PEM, format=PublicFormat.SubjectPublicKeyInfo), hashlib.sha256) # Compare HMAC if (hmac.compare_digest(h, h2.hexdigest())): hmacs.append(True) data = { "type": "datos_dispositivos", "name": name, "mode": mode } # Device will be added on web page if HMAC is correct server.send_message_to_all(json.dumps(data)) print("HMAC de " + name + " coincide. Añadiendo dispositivo...") else: hmacs.append(False) # Unsubscribe client.unsubscribe(name + "/from") print("HMAC de " + name + " no coincide. Dispositivo expulsado.") # Receive message from device elif (str(msg.payload.decode()).split(": ")[0] == "message"): message = str(msg.payload.decode()).split(": ")[1] # Fernet or AEAD if (symmetric_modes[names.index(name)] == 0): message = fernet_keys[names.index(name)].decrypt( message.encode()) else: message = aead_keys[names.index(name)].decrypt( b"12345678", message.encode('latin-1'), None) print("Message from " + name + ": " + message.decode()) # Show the correspondent information on web page data = { "type": "message", "name": name, "payload": message.decode() } # model data server.send_message_to_all(json.dumps(data))
def decrypt_pk_dh(data, diffieHellmanExchange): try: rep = SPNEGO_PKINIT_AS_REP.load(bytes.fromhex(data)).native except: krb_message = KerberosResponse.load(bytes.fromhex(data)) raise KerberosError(krb_message) relevantPadata = None for padata in rep['Kerberos']['padata']: if padata['padata-type'] == 17: relevantPadata = PA_PK_AS_REP.load(padata['padata-value']).native break if not relevantPadata: raise Exception('No PAdata found with type 17') keyinfo = SignedData.load( relevantPadata['dhSignedData']).native['encap_content_info'] if keyinfo['content_type'] != '1.3.6.1.5.2.3.2': raise Exception('Keyinfo content type unexpected value') authdata = KDCDHKeyInfo.load(keyinfo['content']).native pubkey = int( ''.join(['1'] + [str(x) for x in authdata['subjectPublicKey']]), 2) pubkey = int.from_bytes(core.BitString( authdata['subjectPublicKey']).dump()[7:], 'big', signed=False) shared_key = diffieHellmanExchange.exchange(pubkey) server_nonce = relevantPadata['serverDHNonce'] fullKey = shared_key + diffieHellmanExchange.dh_nonce + server_nonce etype = rep['Kerberos']['enc-part']['etype'] cipher = _enctype_table[etype] if etype == Enctype.AES256: t_key = truncate(fullKey, 32) elif etype == Enctype.AES128: t_key = truncate(fullKey, 16) elif etype == Enctype.RC4: raise NotImplementedError( 'RC4 key truncation documentation missing. it is different from AES' ) key = Key(cipher.enctype, t_key) enc_data = rep['Kerberos']['enc-part']['cipher'] dec_data = cipher.decrypt(key, 3, enc_data) encasrep = EncASRepPart.load(dec_data).native cipher = _enctype_table[int(encasrep['key']['keytype'])] session_key = Key(cipher.enctype, encasrep['key']['keyvalue']) return session_key, cipher, rep # remove Octet String manualy padata = str(rep['padata'][0]['padata-value']).encode('hex') parsedPadata = decode(padata.decode('hex'), asn1Spec=AS_REP_Padata())[0] decoded = parsedPadata['DHRepInfo']['dhSignedData'] kdcSignedDataResponse = decode(decoded, asn1Spec=SignedData())[0] kdcDHKeyInfo = str(kdcSignedDataResponse['encapContentInfo'] ['id-pkinit-authData-value']).encode('hex') d = decode(kdcDHKeyInfo.decode('hex'), asn1Spec=KDCDHKeyInfo())[0] dcPublicKey = int(encode(d['subjectPublicKey']).encode('hex')[20:], 16) dcPublicNumbers = dh.DHPublicNumbers(dcPublicKey, diffieHellmanExchange[2]) backend = default_backend() dcPublicKey = backend.load_dh_public_numbers(dcPublicNumbers) shared_key = diffieHellmanExchange[1].exchange(dcPublicKey) sharedHexKey = shared_key.encode('hex') clientDHNonce = '6B328FA66EEBDFD3D69ED34E5007776AB30832A2ED1DCB1699781BFE0BEDF87A' serverDHNonce = encode( parsedPadata['DHRepInfo']['encKeyPack']).encode('hex')[8:] fullKey = sharedHexKey + clientDHNonce + serverDHNonce etype = rep['enc-part']['etype'] cipher = _enctype_table[etype] if etype == Enctype.AES256: truncateKey = truncate(fullKey, 32) key = Key(cipher.enctype, truncateKey) elif etype == Enctype.AES128: truncateKey = truncate(fullKey, 16) key = Key(cipher.enctype, truncateKey) elif etype == Enctype.RC4: truncateKey = truncate(fullKey, 16) key = Key(cipher.enctype, truncateKey) cipherText = rep['enc-part']['cipher'].asOctets() plainText = cipher.decrypt(key, 3, cipherText) encASRepPart = decode(plainText, asn1Spec=EncASRepPart())[0] cipher = _enctype_table[int(encASRepPart['key']['keytype'])] session_key = Key(cipher.enctype, encASRepPart['key']['keyvalue'].asOctets()) return session_key, cipher, rep
def registration(first_msg_obj, conn): # Check structure of first_msg_obj expected = ["reg"] real = sorted(list(first_msg_obj.keys())) if expected != real: print("Invalid message structure") put_message(conn, '{"error": "Invalid message structure"}') return parted_obj = first_msg_obj["reg"] # Check structure of parted_obj expected = ["iv", "part1", "part2"] real = sorted(list(parted_obj.keys())) if expected != real: print("Invalid message structure") put_message(conn, '{"error": "Invalid message structure"}') return # Decrypt part1 globalized.debug("about to decrypt part1") part1_b64 = parted_obj["part1"] tup, error = part1_parts(part1_b64) if error: put_message(conn, error) return ts, username, secret_key, secret_key_b64 = tup ts_int = None try: ts_int = int(ts) except ValueError: print("timestamp is not int") put_message(conn, '{"error": "timestamp is not int"}') return globalized.debug("about to check time and username") now = int(time.time()) if not (now - 2 * 60 < ts_int < now + 1 * 60): print("timestamp out of acceptable range") put_message(conn, '{"error": "timestamp out of acceptable range"}') return user = model.get_user(username) if user: print("username already exists") put_message(conn, '{"error": "username already exists"}') return # Get iv iv_b64 = parted_obj["iv"] iv, error = iv_from_b64(iv_b64) if error: put_message(conn, error) return # Decrypt part2 globalized.debug("about to decrypt part2") part2_b64 = parted_obj["part2"] tup, error = part2_parts(part2_b64, secret_key, iv) if error: put_message(conn, error) return certificate, signature = tup # Verify signature to_hash = (ts + username + secret_key_b64).encode() pub_key = certificate.public_key() try: pub_key.verify(signature, to_hash, padding.PKCS1v15(), hashes.SHA256()) except InvalidSignature: print("Invalid signature of part1") put_message(conn, '{"error": "Signature of part1 was invalid"}') return DH_parameters = dh.generate_parameters(5, 2048) DH_private = DH_parameters.generate_private_key() DH_public = DH_private.public_key() A = DH_public.public_numbers().y numbers = DH_parameters.parameter_numbers() g = numbers.g N = numbers.p to_sign = (ts + str(g) + str(N) + str(A)).encode() signature = sign_to_b64(to_sign) content_dic = { "ts": ts, "g": str(g), "N": str(N), "A": str(A), "signature": signature } content_bytes = json.dumps(content_dic).encode() iv2 = os.urandom(16) enc_content_b64 = aes_encrypt_to_b64(content_bytes, secret_key, iv2) msg_2_dic = { "content": enc_content_b64, "iv": base64.b64encode(iv2).decode() } msg_2 = json.dumps(msg_2_dic) + "\n" put_message(conn, msg_2) # Receive 3rd message message = None try: message = get_message(conn) except Exception as e: print(f"problem receiving 3rd message: {e}") put_message(conn, '{"error": "invalid 3rd message"}') return globalized.debug("checking parts of 3rd message") parts, error = parts_3rd_message(message, secret_key, pub_key) if error: put_message(conn, error) return B, new_username, new_ts = parts if new_username != username: print("username in 3rd message doesn't match") put_message(conn, '''{"error": "username doesn't match"}''') return if new_ts != ts: print("ts in 3rd message doesn't match") put_message(conn, '''{"error": "ts doesn't match"}''') return peer_public_numbers = dh.DHPublicNumbers(int(B), numbers) peer_public_key = peer_public_numbers.public_key() secret = DH_private.exchange(peer_public_key) # Store username, secret and certificate bytes res = model.add_user(username, secret, certificate.public_bytes(serialization.Encoding.DER)) # Send 4th message globalized.debug("preparing 4th message") resp = "OK" if res else "NO" to_sign = (ts + resp).encode() signature = sign_to_b64(to_sign) content_dic = {"ts": ts, "resp": resp, "signature": signature} content_bytes = json.dumps(content_dic).encode() iv4 = os.urandom(16) enc_content_b64 = aes_encrypt_to_b64(content_bytes, secret_key, iv4) msg_4_dic = { "content": enc_content_b64, "iv": base64.b64encode(iv4).decode() } msg_4 = json.dumps(msg_4_dic) + "\n" put_message(conn, msg_4)
# print(p) # print(g) parameters = pn.parameters(default_backend()) private_key = parameters.generate_private_key() y_2 = private_key.public_key().public_numbers().y # print("Server y", y_2) # print("Client y", y) c.send(easy_bytes(y_2)) pk_len = int.from_bytes(c.recv(1024), byteorder='little') if pk_len != len(easy_bytes(y_2)): print("mismatched data") s.close() exit(-1) peer_public_numbers = dh.DHPublicNumbers(y, pn) peer_public_key = peer_public_numbers.public_key(default_backend()) shared_key = private_key.exchange(peer_public_key) derived_key = HKDF( algorithm=hashes.SHA256(), length=32, salt=None, info=b'handshake data', backend=default_backend() ).derive(shared_key) global_key = derived_key print("MITM Protection:", *random_emoji(int.from_bytes(derived_key, byteorder='little'), UNICODE_VERSION), sep=' ') # g^b
def calc_shared_key(self, y): peer_public_number = dh.DHPublicNumbers(y, self.pn) peer_public_key = peer_public_number.public_key(default_backend()) return self.private_key.exchange(peer_public_key)
def is_power_of_two(x): if x == 1: return True if x % 2 == 1: return False return is_power_of_two(x // 2) if is_power_of_two(x): print( "Hey! Your exponent (private key) is so small I could've guessed it! Try to use a larger secure exponent instead!" ) sys.exit() pn = dh.DHParameterNumbers(p, 2) peer = dh.DHPublicNumbers(x, params.parameter_numbers()).public_key( default_backend()) key = sk.exchange(peer) print( "I have encrypted the flag by XORing it bitwise with our shared secret. Here it is:" ) def xor(a, b): return bytes([x ^ y for x, y in zip(a, b)]) print(int.from_bytes(xor(key, flag.encode().rjust(len(key), b'\0')), "big"))
def compute_secret(self, peer_public_key): peer_public_key_int = int.from_bytes(peer_public_key, 'big') peer_public_numbers = dh.DHPublicNumbers(peer_public_key_int, self._pn) peer_public_key = peer_public_numbers.public_key(self.backend) self.shared_secret = self._private_key.exchange(peer_public_key)
def process(self, msg=b""): """ Processa uma mensagem (`bytestring`) enviada pelo SERVIDOR. Retorna a mensagem a transmitir como resposta (`None` para finalizar ligação) """ #primeiro p e g self.msg_cnt += 1 if msg == b'': msg = mensagemboasvinda(self) return msg while len(msg) > 0: if msg: if (msg[:1] == b'E'): break if (msg[:1] == b'P'): global derived_key_2 global public_key_file_server_serial P = 99494096650139337106186933977618513974146274831566768179581759037259788798151499814653951492724365471316253651463342255785311748602922458795201382445323499931625451272600173180136123245441204133515800495917242011863558721723303661523372572477211620144038809673692512025566673746993593384600667047373692203583 G = 44157404837960328768872680677686802650999163226766694797650810379076416463147265401084491113667624054557335394761604876882446924929840681990106974314935015501571333024773172440352475358750668213444607353872754650805031912866692119819377041901642732455911509867728218394542745330014071040326856846990119719675 #ve qual é a chave publica DH server public_key_server_dh = int(msg[1:].decode()) #dh do cliente pn = dh.DHParameterNumbers(P, G) parameters = pn.parameters(default_backend()) #criar private key dh do cliente private_key_cliente_dh = parameters.generate_private_key() #gerar public key dh do cliente public_key_cliente_dh = private_key_cliente_dh.public_key( ).public_numbers().y #atraves da public key dh cria objeto para calcular chave Partilhada peerPublicNumbers2 = dh.DHPublicNumbers( public_key_server_dh, pn) peer_key2 = peerPublicNumbers2.public_key( default_backend()) #Lê o ficheiro p12 para extrair a sua chave privada filepriv = open("privateKeyCli.pem", "rb") keyprivateclii = filepriv.read() filepriv.close() #fazer serializacao chave privada ficheiro do cliente private_key_file_cliente_serial = serialization.load_pem_private_key( keyprivateclii, password=None, backend=default_backend()) #- Lê chave pública do ficheiro do servidor filepub = open("publicKeySvr.pem", "rb") keypublicread = filepub.read() filepub.close() #fazer serializacao chave publica ficheiro do SERVIDOR public_key_file_server_serial = serialization.load_pem_public_key( keypublicread, backend=default_backend()) clp12 = crypto.load_pkcs12( open("client.p12", 'rb').read(), "xpto") print(clp12) clpem = getCertificado(clp12) keyprivatecli = extractPrivate(clp12) #concatenar chave publica dh server + chave publica dh cliente gxgy = str(public_key_server_dh) + str( public_key_cliente_dh) global gyxx gyxx = gxgy.encode() #assinatura = gxgy + chave privada ficheiro cliente serial signature = keyprivatecli.sign( gyxx, padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH), hashes.SHA256()) public_key_cliente_dh_2 = str( public_key_cliente_dh).encode() #envia assinatura + certificado + chave pública tmp = b'S' + signature + public_key_cliente_dh_2 + clpem shared_key_2 = private_key_cliente_dh.exchange(peer_key2) derived_key_2 = HKDF( algorithm=hashes.SHA512(), length=24, salt=None, info=b'handshake data', backend=default_backend()).derive(shared_key_2) print(signature) print(public_key_cliente_dh_2) print(clpem) return tmp #finito #reopen if (msg[:1] == b'm'): #- Recebe Assinatura print("entra aqui") vsign = msg[1:257] svrpem = msg[257:] print("here\n") print(svrpem) print("svrpem\n") verificacao = verifica(svrpem) if verificacao: pub_svr = extractPublic(svrpem) verifySignature(vsign, pub_svr, gyxx) print('é seguro falarmos') balhelhe = b'4' return balhelhe else: print(signature) print(public_key_cliente_dh) print(clpem) msg = b'S' + signature + clpem if (msg[:1] == b'4'): iv_recebido = msg[1:17] #chave de aes mac_recebido = msg[17:49] new_msg = msg[49:] #imprime mensagem recebida print('Received (%d): %r' % (1, msg)) print('Input message to send (empty to finish)') new_msg_encode = input().encode() iv_servido = os.urandom(16) #encriptar ct = encriptarcliente(keyaes, iv_servido, new_msg_encode) #hmac hmacfin = hmaccliente(keymac, ct) #verificamac(self,msg,hmacfin,mac_recebido) iv_cliente = os.urandom(16) mensagem = b'C' + iv_servido + hmacfin + ct return mensagem if len(mensagem) > 0 else None else: #desencriptar cipher = Cipher(algorithms.AES(keyaes), modes.CTR(iv_recebido), backend=backend) decryptor = cipher.decryptor() #hmac hmacfin = hmacclienteelse(keymac, new_msg) txt = decryptor.update(new_msg) + decryptor.finalize() msg = txt.decode() #verificamac(self,msg,hmacfin,mac_recebido) #Função para verificar o hmac #def verificamac(self,msg,hmacfin,mac_recebido,msgpv=b''): if (hmacfin == mac_recebido): print('Received (%d): %r' % (self.msg_cnt, msg)) print('Input message to send (empty to finish)') new_msg_encode = input().encode() iv_posve = os.urandom(16) ct = encriptarelse(keyaes, iv_posve, new_msg_encode) msgpv = iv_posve + hmacfin + ct print(msgpv) return msgpv if len(msgpv) > 0 else None else: print('deu erro, nao e igual')
def on_message(client, userdata, msg): global parameters global hmac_key global b_public_key_number global a_private_key global a_public_key global a_private_key_ecdh global a_public_key_ecdh global key_fernet global f_key global a_key if (msg.topic == (name + "/to")): # Receive params if (str(msg.payload.decode()).split(":")[0] == "param"): b_pem = str(msg.payload.decode()).split(":")[1] parameters = load_pem_parameters(bytes(b_pem, 'ascii'), backend=default_backend()) # Calculate keys from params a_private_key = parameters.generate_private_key() a_public_key = a_private_key.public_key() client.publish(name + "/from", "public:" + str(a_public_key.public_numbers().y)) # Receive public key elif (str(msg.payload.decode()).split(":")[0] == "public"): print("Public key received from platform.") # DH if (asymmetric_mode == 0): b_public_key_number = int( str(msg.payload.decode()).split(":")[1]) peer_public_numbers = dh.DHPublicNumbers( b_public_key_number, parameters.parameter_numbers()) b_public_key = peer_public_numbers.public_key( default_backend()) # Calculate shared key a_shared_key = a_private_key.exchange(b_public_key) # ECDH else: # Generate private and public key ECDH a_private_key_ecdh = ec.generate_private_key(ec.SECP384R1()) a_public_key_ecdh = a_private_key_ecdh.public_key() b_public_key_number = str(msg.payload.decode()).split(":")[1] b_public_key = load_pem_public_key( b_public_key_number.encode()) client.publish( name + "/from", "public:" + a_public_key_ecdh.public_bytes( encoding=Encoding.PEM, format=PublicFormat.SubjectPublicKeyInfo).decode()) # Calculate shared key a_shared_key = a_private_key_ecdh.exchange( ec.ECDH(), b_public_key) print("Shared key calculated.") # Calculate HMAC def hebra(): global hmac_key # If device has just 'input', write HMAC key here if (mode == 0): hmac_key = str( input( "Introduce la clave que aparece en la plataforma: " )) # If device has 'output' or nothing, write HMAC key on web page else: hmac_key = str(os.urandom(2).hex()) print("HMAC KEY: " + hmac_key) # Calcula HMAC (DH or ECDH) if (asymmetric_mode == 0): h = hmac.new( bytes(hmac_key, 'ascii'), bytes(str(a_public_key.public_numbers().y), 'ascii'), hashlib.sha256) else: h = hmac.new( bytes(hmac_key, 'ascii'), a_public_key_ecdh.public_bytes( encoding=Encoding.PEM, format=PublicFormat.SubjectPublicKeyInfo), hashlib.sha256) # Send to platform HMAC client.publish(name + "/from", "hmac:" + str(h.hexdigest())) if (hmac_key is None): # New thread because 'input' is blocking threading.Thread(target=hebra).start() # Calculate FERNET key using HASH derived_key_fernet = HKDF( algorithm=hashes.SHA256(), length=32, salt=None, info=b'handshake data').derive(a_shared_key) key_fernet = base64.urlsafe_b64encode(derived_key_fernet) f_key = Fernet(key_fernet) # Calculate AEAD key using HASH derived_key_aead = HKDF( algorithm=hashes.SHA256(), length=24, salt=None, info=b'handshake data').derive(a_shared_key) key_aead = base64.urlsafe_b64encode(derived_key_aead) a_key = aead.AESGCM(key_aead)