def decrypt_message(k, encrypted_key, encrypted_message): """ Decrypts a message encrypted by the encrypt_message function First decrypts the AES key and IV using ECC Then decrypts the data using the AES key and IV :param k: Private key k :param encrypted_key: ECC encrypted key (list of of ints) :param encrypted_message: AES encrypted data (bytes :return: Decrypted data (bytes) """ ecies = ecc.ECEIS(ecc.CURVE) r = ecc.AffineCurvePoint(encrypted_key[0], encrypted_key[1], ecc.CURVE) s = ecies.recover(r, ecc.ECPrivateKey(k, ecc.CURVE)) s = str(s).encode('utf-8') key = sha.SHA3_512(s).digest() message_decryptor = Decrypter( mode=AESModeOfOperationCBC(key[:32], iv=key[32:48])) decrypted_message = message_decryptor.feed(encrypted_message) decrypted_message += message_decryptor.feed() return oaep.oaep_unpad(decrypted_message)
def sign_message(k, message): """ Signs a message using an ECDSA signature private key and a message, Computes SHA512 hash of plaintext and then performs ECDSA signature upon it :param k: ECC key k :param message: Message to sign (bytes) :return: Signature (list of ints) """ message_hash = sha.SHA3_512(message).digest() block = get_blocks(message_hash, 1024) return sign_number(k, block[0])
def authenticate_message(kx, ky, plaintext, signature): """ Authenticates a message when given a plaintext and signature Verifies hash with ECDSA public key :param kx: ECC Public key kx :param ky: ECC Public key ky :param plaintext: Decrypted plaintext to verify (bytes) :param signature: The signature (list of ints) :return: Whether the message signature is valid (boolean) """ message_hash = sha.SHA3_512(plaintext).digest() block = get_blocks(message_hash, 1024) return validate_number(kx, ky, signature[0], signature[1], block[0])
def enum_keys(arguments): """ Enumerates all keys residing in the public_keys directory. Prints to stdout a formatted explanation of the key, with: Filename User Name Email Hash Randomart :param arguments: Argparser arguments object :return: None """ key_enum = '' for key_file in os.listdir(PUBLIC_PATH): with open(os.path.join(PUBLIC_PATH, key_file)) as f: key_text = f.read() key = read_public_key(key_text) key_hash = sha.SHA3_512(key_text.encode('utf-8')).hexdigest() key_hash_formatted = ':'.join([ key_hash[:64][i:i + 2] for i in range(0, len(key_hash[:64]), 2) ]).upper() # Only use the first 64 characters of the hash so it fills up less of the board. key_randomart = randomart.RandomArt(hashalg='FinCrypt', room_size=(31, 15)) key_randomart = key_randomart(key_hash) formatted_key = f"{key_file}:\nName: {key['name'].decode('utf-8')}\nEmail: {key['email'].decode('utf-8')}" \ f"\nHash: {key_hash_formatted}\nKeyArt:\n{key_randomart}" key_enum += formatted_key + '\n\n' sys.stdout.write(key_enum.strip())
def encrypt_message(kx, ky, message): """ Encrypts a message using ECC and AES-256 First generates a random AES key and IV with os.urandom() Then encrypts the original message with that key Then encrypts the AES key with the ECC key NOTE: This means that plaintext will not have the same ciphertext when encrypted twice. Keep this in mind if you require reproducibility behavior :param kx: Public key kx (int) :param ky: Public key ky (int) :param message: Message (bytes) :return: Tuple (encrypted key (list of ints), encrypted IV (list of ints), and encrypted message (bytes)) """ ecies = ecc.ECEIS(ecc.CURVE) r, s = ecies.exchange( ecc.ECPublicKey(ecc.AffineCurvePoint(kx, ky, ecc.CURVE))) s = str(s).encode('utf-8') key = sha.SHA3_512(s).digest() message_encryptor = Encrypter( mode=AESModeOfOperationCBC(key[:32], iv=key[32:48])) encrypted_blocks = message_encryptor.feed(oaep.oaep_pad(message)) encrypted_blocks += message_encryptor.feed() encrypted_key = r.x, r.y return encrypted_key, encrypted_blocks