def dh2(self): """ Executes the second half of the Diffie-Hellman key exchange """ self.write_serial_string(str(Opcodes.ECDH_SHAKE)) pub_arduino = int(self.read_serial_raw(), base=16).to_bytes(32, byteorder="big") self.write_serial(self.keys["public"]) self.symm_key = curve.calculateAgreement(self.keys["private"], pub_arduino)[:16]
def calculateAgreement(publicKey, privateKey): """ :type publicKey: ECPublicKey :type privateKey: ECPrivateKey """ if publicKey.getType() != privateKey.getType(): raise InvalidKeyException("Public and private keys must be of the same type!") if publicKey.getType() == Curve.DJB_TYPE: return _curve.calculateAgreement(privateKey.getPrivateKey(), publicKey.getPublicKey()) else: raise InvalidKeyException("Unknown type: %s" % publicKey.getType())
def calculateAgreement(self, private_key, public_key): return axolotl_curve25519.calculateAgreement(private_key, public_key)
def generateSharedSecret(self, public_key): private_key = self.Curve.private_key shared_secret = axolotl_curve25519.calculateAgreement( private_key, public_key) return shared_secret
def generate_shared_secret(private_key, public_key): shared_secret = curve.calculateAgreement(private_key, public_key) # shared_secret = Box(private_key, public_key).shared_key() return shared_secret
def extract_validated_payload(self, msg): try: if not msg['payload'].startswith("SIG/2"): return super().extract_validated_payload(msg) beat = int(self.beat()) try: hdr, b64sig, payload = msg['payload'].split(' ', 2) sig = base64.b64decode(b64sig) msg['hdr'] = hdr msg['sig'] = sig msg['payload'] = payload signed_payload = msg['payload'] if not super().extract_validated_payload(msg): return None clean_payload = msg['payload'] cmd = msg['payload'].split(" ")[0] except Exception as e: self.logger.warning( "Could not parse curve25519 signature from payload '{}' -- ignored {}" .format(msg['payload'], str(e))) return None if len(sig) != 64: self.logger.error( "Signature wrong length for '{}' - ignored".format( msg['node'])) return None # Process TOFU information if we do not (yet) know the public key # without validating the signature. # seskey = None if cmd == 'announce' or cmd == 'welcome': try: cmd, ip, pubkey, seskey = clean_payload.split(" ") except Exception as e: self.logger.error("Error parsing announce. Ignored. " + str(e)) return None publickey = base64.b64decode(pubkey) if len(publickey) != 32: self.logger.error( "Ignoring malformed signing public key of node {}". format(msg['node'])) return None publickey = ed25519.VerifyingKey(pubkey, encoding="base64") seskey = base64.b64decode(seskey) if len(seskey) != 32: self.logger.error( "Ignoring malformed session public key of node {}". format(msg['node'])) return None if msg['node'] in self.pubkeys: if self.pubkeys[msg['node']] != publickey: self.logger.info( "Ignoring (changed) public key of node {}".format( msg['node'])) return None else: self.logger.debug( "Potentially learned a public key of node {} on first contact - checking signature next." .format(msg['node'])) else: if not msg['node'] in self.pubkeys: self.logger.info( "No public key for node {} -- ignoring.".format( msg['node'])) return None publickey = self.pubkeys[msg['node']] if not self.cnf.privatekey: return None # Note: this is the payload `as of now' -- not the further decoded/stripped of its beat payload. # Because we also (want to) have the signature cover the beat - to prevent replay. # Todo: consider a nonce. try: publickey.verify(b64sig, signed_payload.encode('ASCII'), encoding="base64") self.logger.debug("Good signature on " + signed_payload) except ed25519.BadSignatureError: self.logger.warning("Bad signature for {} - ignored".format( msg['node'])) return None except Exception as e: self.logger.warning( "Invalid signature for {}: {} -- ignored.".format( msg['node'], str(e))) return None if not msg['node'] in self.pubkeys: self.pubkeys[msg['node']] = publickey self.logger.info( "Learned a public key of node {} on first contact.".format( msg['node'])) if (cmd == 'announce' or cmd == 'welcome') and seskey: session_key = curve.calculateAgreement(self.session_priv, seskey) self.sharedkey[msg['node']] = hashlib.sha256( session_key).digest() self.logger.debug( "(Re)calculated shared secret with node {}.".format( msg['node'])) msg['validated'] = 20 except Exception as e: if 1: exc_type, exc_obj, tb = sys.exc_info() f = tb.tb_frame lineno = tb.tb_lineno filename = f.f_code.co_filename linecache.checkcache(filename) line = linecache.getline(filename, lineno, f.f_globals) self.logger.debug('EXCEPTION IN ({}, LINE {} "{}"): {}'.format( filename, lineno, line.strip(), exc_obj)) return msg
print(f"[HUMAN_VERIFICATION_REQUIRED]") hv = HumanVerif(verify['error']['metadata'][11][1], verify['error']['metadata'][11][2]) RetryReq(session, hv) cl.validateProfile(session, 'yinmo') exchangeEncryptionKey = cl.exchangeEncryptionKey(session, b64_public_key.decode(), b64_nonce.decode(), 1) print(f'exchangeEncryptionKey: {exchangeEncryptionKey}') exc_key = base64.b64decode(exchangeEncryptionKey[1]) exc_nonce = base64.b64decode(exchangeEncryptionKey[2]) sign = Curve25519.calculateAgreement(private_key, exc_key) print(f"sign: {sign}") password = '******' master_key = getSHA256Sum(b'master_key', sign, nonce, exc_nonce) aes_key = getSHA256Sum(b'aes_key', master_key) hmac_key = getSHA256Sum(b'hmac_key', master_key) e1 = AES.new(aes_key[:16], AES.MODE_CBC, aes_key[16:32]) doFinal = e1.encrypt(pad(password.encode(), 16)) hmacd = hmac.new(hmac_key, msg=doFinal, digestmod=hashlib.sha256).digest() encPwd = base64.b64encode(doFinal + hmacd).decode() setPwd = cl.setPassword(session, encPwd, 1) print(setPwd)
def extract_validated_payload(self, msg): try: if not msg['payload'].startswith("SIG/2"): return super().extract_validated_payload(msg) beat = int(self.beat()) try: hdr, b64sig, payload = msg['payload'].split(' ',2) sig = base64.b64decode(b64sig) msg['hdr'] = hdr msg['sig'] = sig msg['payload'] = payload signed_payload = msg['payload'] if not super().extract_validated_payload(msg): return None clean_payload = msg['payload'] cmd = msg['payload'].split(" ")[0] except Exception as e: self.logger.warning("Could not parse curve25519 signature from payload '{}' -- ignored {}".format(msg['payload'],str(e))) return None if len(sig) != 64: self.logger.error("Signature wrong length for '{}' - ignored".format(msg['node'])) return None # Process TOFU information if we do not (yet) know the public key # without validating the signature. # seskey = None nonce = None if cmd == 'announce' or cmd == 'welcome': try: # if cmd == 'welcome': cmd, ip, pubkey, seskey, nonce = clean_payload.split(" ") #else: # cmd, ip, pubkey, seskey = clean_payload.split(" ") except Exception as e: self.logger.error("Error parsing announce. Ignored. "+str(e)) return None publickey = base64.b64decode(pubkey) if len(publickey) != 32: self.logger.error("Ignoring malformed signing public key of node {}".format(msg['node'])) return None if publickey == self.cnf.publickey.to_bytes(): self.logger.debug("Ignoring the message - as it is my own (pubkey).") publickey = ed25519.VerifyingKey(pubkey, encoding="base64") seskey = base64.b64decode(seskey) if len(seskey) != 32: self.logger.error("Ignoring malformed session public key of node {}".format(msg['node'])) return None if msg['client'] == self.cnf.node: self.logger.debug("Ignoring the message - as it is my own (name).") if msg['node'] in self.pubkeys: if self.pubkeys[msg['node']] != publickey: self.logger.critical("Ignoring (changed) public key of node {}".format(msg['node'])) return None else: self.logger.debug("Potentially learned a public key of node {} on first contact - checking signature next.".format(msg['node'])) else: if not msg['node'] in self.pubkeys: self.logger.info("No public key for node {} -- ignoring.".format(msg['node'])) return None publickey = self.pubkeys[ msg['node'] ] if not self.cnf.privatekey: return None # Note: this is the payload `as of now' -- not the further decoded/stripped of its beat payload. # Because we also (want to) have the signature cover the beat - to prevent replay. # Todo: consider a nonce. try: publickey.verify(b64sig, signed_payload.encode('ASCII'), encoding="base64") self.logger.debug("Good signature on " + signed_payload) except ed25519.BadSignatureError: self.logger.warning("Bad signature for {} - ignored".format(msg['node'])) return None except Exception as e: self.logger.warning("Invalid signature for {}: {} -- ignored.".format(msg['node'], str(e))) return None if not msg['node'] in self.pubkeys: self.pubkeys[ msg['node'] ] = publickey self.save_pkdb() self.logger.info("Learned a public key of node {} on first contact.".format(msg['node'])) else: if (self.pubkeys[ msg['node'] ] == publickey): self.logger.debug("Already have this very public key recorded for this node {}.".format(msg['node'])) else: self.logger.warning("Does NOT match the key recorded for node {}.".format(msg['node'])) if (cmd == 'announce' or cmd == 'welcome'): if (seskey): session_key = curve.calculateAgreement(self.session_priv, seskey) self.sharedkey[ msg['node'] ] = hashlib.sha256(session_key).digest() if (nonce): self.send_tofu('welcome', msg['node'], nonce) self.logger.debug("(Re)calculated shared secret with node {}.".format(msg['node'])) msg['validated'] = 20 except Exception as e: if 1: exc_type, exc_obj, tb = sys.exc_info() f = tb.tb_frame lineno = tb.tb_lineno filename = f.f_code.co_filename linecache.checkcache(filename) line = linecache.getline(filename, lineno, f.f_globals) self.logger.debug('EXCEPTION IN ({}, LINE {} "{}"): {}'.format(filename, lineno, line.strip(), exc_obj)) return msg
# Key Features - # if backup key = type + 128 # if signature key = type + 64 # if decryption key = type + 32 # if authentication key = type + 16 # For this example it will be a decryption key time.sleep(1.5) print(ok.read_string()) time.sleep(2) print('You should see your OnlyKey blink 3 times') print() message = 'Secret Message' counter = b"\x00\x00\x00\x01" shared_secret = curve.calculateAgreement(alice_private_key, bob_public_key) h = hashlib.sha256() h.update(counter) h.update(shared_secret) h.update(message.encode()) d = h.digest() KEK = d payload = alice_public_key #We are simulating message here, according to refernce below it is a known value to both parties - unsigned char message[256]; # # // Reference - https://www.ietf.org/mail-archive/web/openpgp/current/msg00637.html # // https://fossies.org/linux/misc/gnupg-2.1.17.tar.gz/gnupg-2.1.17/g10/ecdh.c # // gcry_md_write(h, "\x00\x00\x00\x01", 4); /* counter = 1 */
def generateSharedSecret(self, private_key, public_key): return Curve25519.calculateAgreement(bytes(private_key), bytes(public_key))