Esempio n. 1
0
 def rsa_sign(self, msg, user_pri_key):
     signer = user_pri_key.signer(
         PSS(mgf=MGF1(SHA512()), salt_length=PSS.MAX_LENGTH), SHA512())
     signer.update(msg)
     signature = signer.finalize()
     sig_length = (len(signature)).to_bytes(4, byteorder='big')
     return sig_length + signature + msg
Esempio n. 2
0
 def validate_machine_authentication(self, authentication_string,
                                     provided_nonce):
     # Ensure the input string is JSON and contains all required fields
     validate_set = ["key_digest", "nonce_digest", "signature"]
     try:
         if type(authentication_string) is bytes:
             authentication_string = authentication_string.decode('utf-8')
         authentication_dict = json.loads(authentication_string)
         for field in validate_set:
             field_value = authentication_dict[field]
             if not type(field_value) == str:
                 print(
                     "[!] Invalid data supplied in authentication string.")
                 raise ValueError
         # Ensure the nonce hash has been computed properly before continuing
         for i in range(0, 10000):
             provided_nonce = self._compute_hash(provided_nonce)
         if not provided_nonce == authentication_dict["nonce_digest"]:
             print(provided_nonce)
             print(authentication_dict["nonce_digest"])
             print(
                 "[!] Nonce digest does not match our digest of provided nonce."
             )
             raise ValueError
         # Check if we have a public key on file for the provided public key digest
         stored_machine_info = self._execute_query(
             "SELECT * FROM authorized_machines "
             "WHERE machine_key_digest=? LIMIT 1",
             (authentication_dict["key_digest"], ))
         if stored_machine_info:
             stored_machine_info = stored_machine_info[0]
         if len(stored_machine_info) == 3:
             # Verify the provided signature with the stored public key.
             public_key = serialization.load_pem_public_key(
                 stored_machine_info[2], default_backend())
             public_key.verify(
                 base64.b64decode(authentication_dict["signature"]),
                 bytes(authentication_dict["nonce_digest"], 'utf-8'),
                 padding.PSS(mgf=padding.MGF1(SHA512()),
                             salt_length=padding.PSS.MAX_LENGTH), SHA512())
             print("[+] Authenticated machine with alias: {0}.".format(
                 stored_machine_info[0]))
             return True
         else:
             raise LookupError(
                 "[!] Invalid data stored for provided public key.")
     except ValueError:
         print(
             "[!] Value error during authentication, invalid JSON may have been supplied."
         )
         return False
     except KeyError:
         print(
             "[!] Not all required fields present in authentication string, machine is not authorized."
         )
         return False
     except InvalidSignature:
         print("[!] Signature mismatch, machine is not authorized.")
         return False
Esempio n. 3
0
 def _sign_ciphertext_digest(self, ciphertext_digest):
     if type(ciphertext_digest) is str:
         ciphertext_digest = bytes(ciphertext_digest, 'utf-8')
     return base64.b64encode(
         self.rsa_private_key.sign(
             ciphertext_digest,
             padding.PSS(mgf=padding.MGF1(SHA512()),
                         salt_length=padding.PSS.MAX_LENGTH),
             SHA512())).decode('utf-8')
Esempio n. 4
0
 def rsa_verify(self, msg, user_pub_key):
     sig_length_bytes = msg[:4]
     sig_length = int.from_bytes(sig_length_bytes, byteorder='big')
     signature = msg[4:4 + sig_length]
     s = msg[4 + sig_length:]
     verifier = user_pub_key.verifier(
         signature, PSS(mgf=MGF1(SHA512()), salt_length=PSS.MAX_LENGTH),
         SHA512())
     verifier.update(s)
     verifier.verify()
     return s
Esempio n. 5
0
def exchange(config: Config, context: dict, expected_tlv_state: TlvState, encrypted_data: bytes) -> List[dict]:
    """pair_setup M5 and M6"""
    srp = context.get('srp')

    if expected_tlv_state != TlvState.m5 or not srp:
        return _error(TlvState.m6, TlvError.unknown, 'Unexpected pair_setup state')

    hkdf = HKDF(algorithm=SHA512(), length=32, salt=SALT_ENCRYPT, info=INFO_ENCRYPT, backend=default_backend())
    decrypt_key = hkdf.derive(srp.session_key)

    chacha = ChaCha20Poly1305(decrypt_key)

    try:
        data = chacha.decrypt(NONCE_SETUP_M5, encrypted_data, None)
    except InvalidTag:
        return _error(TlvState.m6, TlvError.authentication, 'pair_setup M5: invalid auth tag during chacha decryption')

    try:
        tlv = tlv_parser.decode(data)[0]
    except ValueError:
        return _error(TlvState.m6, TlvError.authentication, 'unable to decode decrypted tlv data')

    hkdf = HKDF(algorithm=SHA512(), length=32, salt=SALT_CONTROLLER, info=INFO_CONTROLLER, backend=default_backend())
    ios_device_x = hkdf.derive(srp.session_key)
    ios_device_info = ios_device_x + tlv[TlvCode.identifier].encode() + tlv[TlvCode.public_key]

    if not _verify_ed25519(key=tlv[TlvCode.public_key], message=ios_device_info, signature=tlv[TlvCode.signature]):
        return _error(TlvState.m6, TlvError.authentication, 'ios_device_info ed25519 signature verification is failed')

    config.add_pairing(tlv[TlvCode.identifier], tlv[TlvCode.public_key], ControllerPermission.admin)  # save pairing

    # M6 response generation
    hkdf = HKDF(algorithm=SHA512(), length=32, salt=SALT_ACCESSORY, info=INFO_ACCESSORY, backend=default_backend())
    accessory_x = hkdf.derive(srp.session_key)

    signing_key = ed25519.SigningKey(config.accessory_ltsk)
    public_key = signing_key.get_verifying_key().to_bytes()
    accessory_info = accessory_x + config.device_id.encode() + public_key
    accessory_signature = signing_key.sign(accessory_info)

    sub_tlv = tlv_parser.encode([{
        TlvCode.identifier: config.device_id,
        TlvCode.public_key: public_key,
        TlvCode.signature: accessory_signature,
    }])

    encrypted_data = chacha.encrypt(NONCE_SETUP_M6, sub_tlv, None)

    config.pair_setup_mode = False
    return [{
        TlvCode.state: TlvState.m6,
        TlvCode.encrypted_data: encrypted_data,
    }]
Esempio n. 6
0
 def _signature_is_valid(self, ciphertext_digest, encoded_signature):
     if type(encoded_signature) is str:
         encoded_signature = bytes(encoded_signature, 'utf-8')
     if type(ciphertext_digest) is str:
         ciphertext_digest = bytes(ciphertext_digest, 'utf-8')
     signature = base64.b64decode(encoded_signature)
     try:
         self.peer_public_key.verify(
             signature, ciphertext_digest,
             padding.PSS(mgf=padding.MGF1(SHA512()),
                         salt_length=padding.PSS.MAX_LENGTH), SHA512())
         return True
     except InvalidSignature:
         return False
Esempio n. 7
0
 def get_machine_authentication_string(self, authentication_nonce):
     nonce_digest = authentication_nonce
     for i in range(0, 10000):
         nonce_digest = self._compute_hash(nonce_digest)
     signature = self.private_key.sign(
         bytes(nonce_digest, 'utf-8'),
         padding.PSS(mgf=padding.MGF1(SHA512()),
                     salt_length=padding.PSS.MAX_LENGTH), SHA512())
     authentication_dict = {
         "key_digest": self.get_public_key_digest().decode('utf-8'),
         "nonce_digest": nonce_digest,
         "signature": base64.b64encode(signature).decode('utf-8')
     }
     return json.dumps(authentication_dict)
Esempio n. 8
0
def verify_start(config: Config, context: dict, ios_device_public_key: bytes) -> List[dict]:
    """pair_verify M1 and M2"""
    curve25519 = X25519PrivateKey.generate()
    accessory_curve25519_public_key: bytes = curve25519.public_key().public_bytes()
    shared_secret: bytes = curve25519.exchange(X25519PublicKey.from_public_bytes(ios_device_public_key))

    accessory_info: bytes = accessory_curve25519_public_key + config.device_id.encode() + ios_device_public_key
    signing_key = ed25519.SigningKey(config.accessory_ltsk)
    accessory_signature = signing_key.sign(accessory_info)

    sub_tlv = tlv_parser.encode([{
        TlvCode.identifier: config.device_id,
        TlvCode.signature: accessory_signature,
    }])

    hkdf = HKDF(algorithm=SHA512(), length=32, salt=SALT_VERIFY, info=INFO_VERIFY, backend=default_backend())
    session_key = hkdf.derive(shared_secret)

    chacha = ChaCha20Poly1305(session_key)
    encrypted_data = chacha.encrypt(NONCE_VERIFY_M2, sub_tlv, None)

    context['session_key'] = session_key
    context['shared_secret'] = shared_secret
    context['accessory_curve25519_public_key'] = accessory_curve25519_public_key
    context['ios_device_curve25519_public_key'] = ios_device_public_key

    return [{
        TlvCode.state: TlvState.m2,
        TlvCode.public_key: accessory_curve25519_public_key,
        TlvCode.encrypted_data: encrypted_data,
    }]
Esempio n. 9
0
def sign_message(private_key, data):
    signature = private_key.sign(data, ECDSA(SHA512()))

    public_key = encode_public_key(private_key.public_key())

    header = {"key": b64encode(public_key).decode(), 'sig': b64encode(signature).decode()}
    return b'S' + format_header(header) + data
Esempio n. 10
0
def generate_message_signature(message: Union[str, bytes],
                               private_key: Union[RSAPrivateKey, str]) -> str:
    """Return the BASE64 encoded SHA514 signature of a message.

    Args:
        message (str): The message to sign.
        private_key (str): The private key content used to sign the message.

    Returns:
        str: The BASE64 encoded SHA514 signature of a message.
    """
    # Convert the message string to bytes
    if isinstance(message, str):
        message = message.encode()

    # Convert the private key content to a RSAPrivateKey object
    if isinstance(private_key, str):
        private_key = load_rsa_private_key(private_key)

    # Sign the message using the RSAPrivateKey object
    signature: bytes = private_key.sign(message, PKCS1v15(), SHA512())

    # Return the BASE64 encoded SHA512 signature
    b64_bytes: bytes = base64.b64encode(signature)
    return b64_bytes.decode('ascii')
Esempio n. 11
0
 def _get_ciphertext_digest(ciphertext):
     if type(ciphertext) is str:
         ciphertext = bytes(ciphertext, 'utf-8')
     hash_provider = Hash(SHA512(), default_backend())
     hash_provider.update(ciphertext)
     return base64.b64encode(
         hash_provider.finalize()).decode('utf-8').rstrip("=")
Esempio n. 12
0
def verify_finish(config: Config, context: dict, encrypted_data: bytes) -> List[dict]:
    """pair_verify M3 and M4"""
    session_key = context.get('session_key')
    accessory_curve25519_public_key = context.get('accessory_curve25519_public_key')
    ios_device_curve25519_public_key = context.get('ios_device_curve25519_public_key')

    if not session_key or not accessory_curve25519_public_key or not ios_device_curve25519_public_key:
        return _error(TlvState.m4, TlvError.authentication,
                      'verify_finished call before successful verify_start')

    chacha = ChaCha20Poly1305(session_key)

    try:
        data = chacha.decrypt(NONCE_VERIFY_M3, encrypted_data, None)
    except InvalidTag:
        return _error(TlvState.m4, TlvError.authentication, 'invalid auth tag during chacha decryption')

    try:
        tlv = tlv_parser.decode(data)[0]
    except ValueError:
        return _error(TlvState.m4, TlvError.authentication, 'unable to decode decrypted tlv data')

    ios_device_ltpk = config.get_pairing(tlv[TlvCode.identifier])[1]

    if not ios_device_ltpk:
        return _error(TlvState.m4, TlvError.authentication,
                      'unable to find requested ios device in config file')

    ios_device_info = ios_device_curve25519_public_key + tlv[TlvCode.identifier].encode() + \
        accessory_curve25519_public_key

    if not _verify_ed25519(ios_device_ltpk, message=ios_device_info, signature=tlv[TlvCode.signature]):
        return _error(TlvState.m4, TlvError.authentication,
                      'ios_device_info ed25519 signature verification is failed')

    context['paired'] = True
    context['ios_device_pairing_id'] = tlv[TlvCode.identifier]

    hkdf = HKDF(algorithm=SHA512(), length=32, salt=SALT_CONTROL, info=INFO_CONTROL_WRITE, backend=default_backend())
    context['decrypt_key'] = hkdf.derive(context['shared_secret'])

    hkdf = HKDF(algorithm=SHA512(), length=32, salt=SALT_CONTROL, info=INFO_CONTROL_READ, backend=default_backend())
    context['encrypt_key'] = hkdf.derive(context['shared_secret'])

    return [{
        TlvCode.state: TlvState.m4,
    }]
Esempio n. 13
0
    def sha512(self, plaintext):
        """ Perform SHA-512 hash """

        digest = Hash(SHA512(), backend=default_backend())
        digest.update(bytes(plaintext.encode('UTF-8')))
        hash = digest.finalize()

        #return binascii.hexlify(bytearray(hash))
        return base64.b16encode(hash).decode()
Esempio n. 14
0
 def __init__(self, data_secret: bytes, data_hash: bytes) -> None:
     digest = Hash(SHA512())
     digest.update(data_secret)
     digest.update(data_hash)
     secret_hash = digest.finalize()
     key = secret_hash[:self._key_size]
     iv = secret_hash[self._key_size:self._key_size + self._iv_size]
     self._data_hash: Final[bytes] = data_hash
     self._cipher: Final[Cipher] = Cipher(AES(key), CBC(iv))
Esempio n. 15
0
 def get_public_key_digest(self):
     pem_public_key = self.get_pem_public_key()
     pem_public_key = [x for x in pem_public_key if len(x) > 0]
     pem_public_key.pop(0)
     pem_public_key.pop(-1)
     key_string = ''.join(pem_public_key)
     hash_provider = Hash(SHA512(), default_backend())
     hash_provider.update(bytes(key_string, 'utf-8'))
     return binascii.hexlify(hash_provider.finalize())
Esempio n. 16
0
    def __call__(self, request):
        hmac = HMAC(self.secret.encode('utf-8'), SHA512(), default_backend())
        hmac.update(request.body.encode('utf-8'))
        signature = hexlify(hmac.finalize())

        request.headers['Key'] = self.key
        request.headers['Sign'] = signature

        return request
Esempio n. 17
0
    def get_hash(algorithm):
        """Return hash algorithm to use for signature"""

        if algorithm == b'rsa-sha2-512':
            return SHA512()
        elif algorithm in (b'rsa-sha2-256', b'rsa2048-sha256'):
            return SHA256()
        else:
            return SHA1()
Esempio n. 18
0
def opdata1_decrypt_master_key(data, key, hmac_key, aes_size=C_AES_SIZE, ignore_hmac=False):
    key_size = KEY_SIZE[aes_size]
    bare_key = opdata1_decrypt_item(data, key, hmac_key, aes_size=aes_size, ignore_hmac=ignore_hmac)
    # XXX: got the following step from jeff@agilebits (as opposed to the
    # docs anywhere)
    digest = Hash(SHA512(), backend=_backend)
    digest.update(bare_key)
    hashed_key = digest.finalize()
    return hashed_key[:key_size], hashed_key[key_size:]
Esempio n. 19
0
    def sign(self, data: Union[str, Dict[Any, Any]]) -> str:
        if isinstance(data, dict):
            data = json.dumps(data, cls=DecimalEncoder)
            payload = sub('[\n\t\r ]', '', data).encode('utf-8')
        else:
            payload = data.encode('utf-8')
        signature = self.private_key.sign(payload, padding.PKCS1v15(),
                                          SHA512())

        return b64encode(signature).decode('utf-8')
Esempio n. 20
0
def derive_keyhash_v2(domain, password, salt, iterations):
    kdf = PBKDF2HMAC(algorithm=SHA512(),
                     length=64,
                     salt=salt,
                     iterations=iterations,
                     backend=_CRYPTO_BACKEND)
    derived_key = kdf.derive((domain + password).encode('utf-8'))
    hf = HMAC(derived_key, SHA256(), backend=_CRYPTO_BACKEND)
    hf.update(domain.encode('utf-8'))
    return hf.finalize()
Esempio n. 21
0
    def test_init(self, one_key_of_many):
        key_pem, key_serialized = one_key_of_many

        if isinstance(key_pem, Path):
            private_key_pem_file = key_pem
            private_key_pem = None
        else:
            private_key_pem_file = None
            private_key_pem = key_pem

        login = "******"
        expiration_time = 20
        read_only = True
        global_key = True
        label = f"{__project__} {__version__}"
        authentication_url = "http etc"
        connection_timeout = 30
        token = AccessToken(
            login=login,
            private_key=private_key_pem,
            private_key_file=private_key_pem_file,
            expiration_time=expiration_time,
            read_only=read_only,
            global_key=global_key,
            label=label,
            authentication_url=authentication_url,
            connection_timeout=connection_timeout,
        )
        assert token.login == login
        assert token.time_to_live == expiration_time
        assert token.read_only == read_only
        assert token.global_key == global_key
        assert token.label == label
        assert token.authentication_url == authentication_url
        assert token.connection_timeout == connection_timeout

        payload = (
            "Apparently private keys can't be compared directly when extracted (salts?)."
            "But they MUST create the same signature when signing the same data!"
        )
        assert token.private_key.sign(
            str.encode(payload), PKCS1v15(), SHA512()
        ) == key_serialized.sign(str.encode(payload), PKCS1v15(), SHA512())
Esempio n. 22
0
def decrypt(secret, hash, data, file=False):
    """
    Decrypt per telegram docs at https://core.telegram.org/passport.

    Args:
        secret (:obj:`str` or :obj:`bytes`): The encryption secret, either as bytes or as a
            base64 encoded string.
        hash (:obj:`str` or :obj:`bytes`): The hash, either as bytes or as a
            base64 encoded string.
        data (:obj:`str` or :obj:`bytes`): The data to decrypt, either as bytes or as a
            base64 encoded string.
        file (:obj:`bool`): Force data to be treated as raw data, instead of trying to
            b64decode it.

    Raises:
        :class:`TelegramDecryptionError`: Given hash does not match hash of decrypted data.

    Returns:
        :obj:`bytes`: The decrypted data as bytes.

    """
    # First make sure that if secret, hash, or data was base64 encoded, to decode it into bytes
    try:
        secret = b64decode(secret)
    except (binascii.Error, TypeError):
        pass
    try:
        hash = b64decode(hash)
    except (binascii.Error, TypeError):
        pass
    if not file:
        try:
            data = b64decode(data)
        except (binascii.Error, TypeError):
            pass
    # Make a SHA512 hash of secret + update
    digest = Hash(SHA512(), backend=default_backend())
    digest.update(secret + hash)
    secret_hash_hash = digest.finalize()
    # First 32 chars is our key, next 16 is the initialisation vector
    key, iv = secret_hash_hash[:32], secret_hash_hash[32:32 + 16]
    # Init a AES-CBC cipher and decrypt the data
    cipher = Cipher(AES(key), CBC(iv), backend=default_backend())
    decryptor = cipher.decryptor()
    data = decryptor.update(data) + decryptor.finalize()
    # Calculate SHA256 hash of the decrypted data
    digest = Hash(SHA256(), backend=default_backend())
    digest.update(data)
    data_hash = digest.finalize()
    # If the newly calculated hash did not match the one telegram gave us
    if data_hash != hash:
        # Raise a error that is caught inside telegram.PassportData and transformed into a warning
        raise TelegramDecryptionError("Hashes are not equal! {} != {}".format(data_hash, hash))
    # Return data without padding
    return data[bord(data[0]):]
Esempio n. 23
0
def get_ec2_sig_alg(
        alg_id: COSEAlgorithmIdentifier) -> EllipticCurveSignatureAlgorithm:
    """Turn an "ECDSA" COSE algorithm identifier into a corresponding signature
    algorithm
    """
    if alg_id == COSEAlgorithmIdentifier.ECDSA_SHA_256:
        return ECDSA(SHA256())
    if alg_id == COSEAlgorithmIdentifier.ECDSA_SHA_512:
        return ECDSA(SHA512())

    raise UnsupportedAlgorithm(f"Unrecognized EC2 signature alg {alg_id}")
Esempio n. 24
0
def file_hash(f):
    ctx = SHA512()
    hasher = Hash(ctx, default_backend())
    while True:
        data = f.read(1024)
        if not data:
            break
        hasher.update(data)
    digest = hasher.finalize()
    alg = ECDSA(Prehashed(ctx))
    return digest, alg
Esempio n. 25
0
def get_rsa_pss_sig_alg(alg_id: COSEAlgorithmIdentifier) -> HashAlgorithm:
    """Turn an "RSASSA_PSS" COSE algorithm identifier into a corresponding signature
    algorithm
    """
    if alg_id == COSEAlgorithmIdentifier.RSASSA_PSS_SHA_256:
        return SHA256()
    if alg_id == COSEAlgorithmIdentifier.RSASSA_PSS_SHA_384:
        return SHA384()
    if alg_id == COSEAlgorithmIdentifier.RSASSA_PSS_SHA_512:
        return SHA512()

    raise UnsupportedAlgorithm(f"Unrecognized RSA PSS signature alg {alg_id}")
Esempio n. 26
0
def keygen(key_name: Text,
           passcode: Text,
           return_key: Optional[bool] = None) -> Union[None, Text]:
    """Generates key.

    key_name:   The name with which the key needs to be stored in as an
                environment variable.
    passcode:   The password that you would like to encrypt using salt.
    return_key: If made True, it will return the key an then save it in
                an environment variable.

    Generates key with salt & stores it within an environment variable.

    Caution: This key or password is the master password that would be
    used with the other encrypt and decrypt functions. Hence do not
    forget.
    """
    # You can find the reference code here:
    # https://nitratine.net/blog/post/encryption-and-decryption-in-python/
    from base64 import urlsafe_b64encode
    from os import urandom
    from subprocess import PIPE, Popen
    from cryptography.hazmat.backends import default_backend
    from cryptography.hazmat.primitives.hashes import SHA512
    from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

    try:
        # Converting the input string into bytes.
        password = passcode.encode()
        # Creating a salt for encryption.
        # Using SHA512 hashing algorithm, you can use SHA128 or SHA256
        # as well.
        kdf = PBKDF2HMAC(algorithm=SHA512(),
                         length=32,
                         salt=urandom(128),
                         iterations=100000,
                         backend=default_backend())
        # Generating encrypted and salted key but changing it to str
        # format so that it can be stored in an environment variable.
        # This is a personal preference.
        key = urlsafe_b64encode(kdf.derive(
            password)).decode(encoding=_ENCODING)
        if key_name is None:
            key_name = _KEY_NAME
        Popen(f"setx {key_name} {key}",
              stdout=PIPE,
              shell=True)
        if return_key is True:
            return key
    except Exception as error:
        print('An error occured while performing this operation because of'
              f' {error} in function "{stack()[0][3]}" on line'
              f' {exc_info()[-1].tb_lineno}.')
Esempio n. 27
0
 def compute_key_digest(key_data_array):
     # Clean empty lines
     key_data_array = [x for x in key_data_array if len(x) > 0]
     # Clean BEGIN and END tags
     key_data_array.pop(0)
     key_data_array.pop(-1)
     # Join the base64 string
     key_data = ''.join(key_data_array)
     hash_provider = Hash(SHA512(), default_backend())
     hash_provider.update(bytes(key_data, 'utf-8'))
     digest = binascii.hexlify(hash_provider.finalize()).decode('utf-8')
     return digest
Esempio n. 28
0
 def get_shared_key(self, key_length=32, shared_secret=None):
     if not shared_secret and not self.shared_secret:
         raise ArithmeticError("No shared secret provided.")
     elif shared_secret and not self.shared_secret:
         self.shared_secret = shared_secret
     hash_provider = HMAC(
         hex(self.shared_secret).encode('utf-8'), SHA512(),
         default_backend())
     for i in range(0, 10000):
         hash_provider.update(hex(i).encode('utf-8'))
     shared_digest = base64.b64encode(hash_provider.finalize())
     return shared_digest[:key_length]
Esempio n. 29
0
 def _otp(self):
     """
     Current one time password implementation, time-based "TOTP"
     https://cryptography.io/en/latest/hazmat/primitives/twofactor/
     """
     if not self._otp_enabled or len(self._otp_secret) < 1:
         raise ValueError("2FA/OTP is not enabled for this user")
     key = self._otp_secret.decode('hex')
     return TOTP(key,
                 self.OTP_LENGTH,
                 SHA512(),
                 self.OTP_STEP,
                 backend=default_backend())
Esempio n. 30
0
    def _generate_signature_header(self, payload: Dict) -> Dict:
        """Sign the payload and include it in the headers.

        :param payload: payload (claim) for the request for the access token
        :type payload: Dict
        :return: headers which include the signature of the payload
        :rtype: Dict
        """
        signature = self.private_key.sign(str.encode(payload), PKCS1v15(),
                                          SHA512())
        return {
            "Content-Type": "application/json",
            "Signature": b64encode(signature).decode("ascii"),
        }