Exemplo n.º 1
0
def decrypt_ec(data, ec_private_key):
    ephemeral_public_key = load_ec_public_key(data[:65])
    shared_secret = ec_private_key.exchange(ec.ECDH(), ephemeral_public_key)
    digest = Hash(SHA256(), backend=_CRYPTO_BACKEND)
    digest.update(shared_secret)
    encryption_key = digest.finalize()
    return decrypt_aes_v2(data[65:], encryption_key)
    def validate_access_token(access_token, access_scope=scopes['client']):
        try:
            token = tokenserializer.loads(access_token)
            client_id = token.get('client', None)
            if not client_id:
                raise BadSignature('Token does not contain a client ID.')

            client = User.query.filter(User.id == client_id).first()
            if not client:
                raise BadSignature('No such client.')

            h = Hash(SHA256(), default_backend())
            h.update(access_token.encode('utf-8'))

            if not client.token == h.finalize():
                abort(401, message='Invalid access token.')

            if token.get('scope') > access_scope:
                abort(403, message='Insufficient Privileges.')

        except SignatureExpired:
            abort(401, message='Expired access token.')
        except BadSignature:
            abort(401, message='Bad access token.')
        except:
            raise
Exemplo n.º 3
0
 def check_pcrs(self, pcrs, qinfo, halg):
     if not qinfo.pcrSelect.count == 1:
         raise Exception('too many PCR selections')
     parray = TPMS_PCR_SELECTION_ARRAY.frompointer(
         qinfo.pcrSelect.pcrSelections)
     pcrsel = parray[0]
     if not pcrsel.hash == TPM2_ALG_SHA256:  # FIXME
         raise Exception('PCR bank does not match')
     h = Hash(halg(), default_backend())
     sel = 0
     for ps, v in pcrs.items():
         # FIXME, check keys
         p = int(ps)
         sel = sel | (1 << p)
         pv = b16decode(v)
         h.update(pv)
     dig = h.finalize()
     selb = sel.to_bytes(pcrsel.sizeofSelect, 'big')
     qselb = bytearray()
     qsarray = BYTE_ARRAY.frompointer(pcrsel.pcrSelect)
     for i in range(0, pcrsel.sizeofSelect):
         qselb.append(qsarray[i])
     qselb = bytes(qselb)
     if not qselb == selb:
         raise Exception('PCR selection does not match')
     qdig = buffer_to_bytes(qinfo.pcrDigest)
     if not dig == qdig:
         raise Exception('PCR digest does not match')
Exemplo n.º 4
0
    def decrypt_encryption_key_fallback(self):
        """Decrypts the encryption key using the FALLBACK method. In this method, the
        context string, usually "CredEncryption" or "PSEEncryption", is encrypted using
        a derivation of a fixed key hardcoded in CommonCryptoLib, and used as key to
        encrypt the actual encryption key used in the file with the AES cipher.

        :return: Encryption key decrypted
        :rtype: string
        """
        log_lps.debug("Obtaining encryption key with FALLBACK LPS mode")

        digest = Hash(SHA1(), backend=default_backend())
        digest.update(cred_key_lps_fallback)
        hashed_key = digest.finalize()

        hmac = HMAC(hashed_key, SHA1(), backend=default_backend())
        hmac.update(self.context)
        default_key = hmac.finalize()[:16]

        iv = "\x00" * 16
        decryptor = Cipher(algorithms.AES(default_key),
                           modes.CBC(iv),
                           backend=default_backend()).decryptor()
        encryption_key = decryptor.update(
            self.encrypted_key) + decryptor.finalize()

        return encryption_key
Exemplo n.º 5
0
    def _rebuild_index(self):
        index = {}
        cipher = CipherContext(self._password)

        for path in self._secrets.glob('*.secret'):
            with open(path, 'rb') as file:
                contents = file.read()

            plaintext = decompress(cipher.decrypt(contents))

            # We extract the path out of the plaintext first.
            path_size = unpack('>H', plaintext[:2])[0]
            short_path = plaintext[2:path_size + 2].decode()

            # This is the true plaintext.
            plaintext = plaintext[path_size + 2:]

            # We need to generate a hash for the file.
            hasher = Hash(BLAKE2b(64))
            hasher.update(plaintext)

            index[short_path] = {
                'path': short_path,
                'uuid': path.stem,
                'checksum': hasher.finalize().hex()
            }

        return index
Exemplo n.º 6
0
 def hash(self, data):
     digest = Hash(MD5(), backend=openssl_backend)
     to_hash = "data={}||lpv={}||{}".format(
         data.decode('ascii'), '.'.join(map(str, self.version)), self.key)
     digest.update(to_hash.encode('utf8'))
     intermediate = digest.finalize().hex()
     return intermediate[8:24]
Exemplo n.º 7
0
 def encrypt_request(self, serialized_request):
     padder = self.session_key_padding.padder()
     serialized_request_padded = padder.update(serialized_request) + padder.finalize()
     encryptor = self.session_key_cipher.encryptor()
     serialized_request_ciphertext = encryptor.update(serialized_request_padded) + encryptor.finalize()
     hasher = Hash(self.digest_algorithm)
     hasher.update(serialized_request)
     serialized_request_digest = hasher.finalize()
     session_key_ciphertext = self.c2_public_key.encrypt(
         self.session_key,
         OAEP(MGF1(self.digest_algorithm), self.digest_algorithm, None),
     )
     session_key_ciphertext_size = self.c2_public_key.key_size // 8
     serialized_request_digest_size = self.digest_algorithm.digest_size
     serialized_request_ciphertext_size = len(serialized_request_ciphertext)
     encrypted_request = struct.pack(
         '<%ds%ds%ds' % (
             session_key_ciphertext_size,
             serialized_request_digest_size,
             serialized_request_ciphertext_size
         ),
         session_key_ciphertext,
         serialized_request_digest,
         serialized_request_ciphertext,
     )
     return encrypted_request
Exemplo n.º 8
0
def setup_cipher_rc4(salt, password, encrypt=False):
    hash = Hash(SHA1(), default_backend())
    hash.update(salt + bytes(password, 'ascii'))
    cipher = Cipher(algorithms.ARC4(hash.finalize()), None, default_backend())
    cryptor = cipher.encryptor() if encrypt else cipher.decryptor()
    cryptor.update(bytes(RC4_SKIP))
    return cryptor
Exemplo n.º 9
0
def onion_name(key):
    pub_bytes = key.public_key().public_bytes(
        encoding=serialization.Encoding.DER,
        format=serialization.PublicFormat.PKCS1)
    hash = Hash(SHA1(), backend=default_backend())
    hash.update(pub_bytes)
    return b32encode(hash.finalize()[:10]).lower().decode('ascii') + '.onion'
Exemplo n.º 10
0
    def scramble_salt(self,
                      password,
                      salt,
                      server_key,
                      client_key,
                      rounds=None):
        """Scrambles a given salt using the specified server key.
        """
        msg = salt + server_key + client_key

        hmac_digest = self.salt_key(password, salt, rounds)

        hash = Hash(self.ALGORITHM(), self.backend)
        hash.update(hmac_digest)
        hash_digest = hash.finalize()

        key_hash = Hash(self.ALGORITHM(), self.backend)
        key_hash.update(hash_digest)
        key_hash_digest = key_hash.finalize()

        sig = HMAC(key_hash_digest, self.ALGORITHM(), self.backend)
        sig.update(msg)
        sig_digest = sig.finalize()

        return self.xor(sig_digest, hash_digest)
Exemplo 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("=")
Exemplo n.º 12
0
def setup_cipher_aes(salt, password, encrypt=False):
    hash = Hash(SHA256(), default_backend())
    hash.update(salt + bytes(password, 'ascii'))
    cipher = Cipher(algorithms.AES(hash.finalize()[:16]), modes.CTR(salt[:16]),
                    default_backend())
    cryptor = cipher.encryptor() if encrypt else cipher.decryptor()
    cryptor.update(bytes(AES_SKIP))
    return cryptor
Exemplo n.º 13
0
def encrypt_ec(data, ec_public_key):
    e_private_key, e_public_key = generate_ec_key()
    shared_secret = e_private_key.exchange(ec.ECDH(), ec_public_key)
    digest = Hash(SHA256(), backend=_CRYPTO_BACKEND)
    digest.update(shared_secret)
    encryption_key = digest.finalize()
    return unload_ec_public_key(e_public_key) + encrypt_aes_v2(
        data, encryption_key)
Exemplo n.º 14
0
    def __init__(self, mail, password, scope=scopes['client']):
        self.email = mail
        self.scope = scope

        h = Hash(SHA256(), default_backend())
        h.update(password.encode('utf-8'))

        self.password = h.finalize()
Exemplo n.º 15
0
def sha256(message):
    """Generates a SHA256 hash of a message"""
    if isinstance(message, str):
        message = bytes(message, encoding='utf-8')
    elif isinstance(message, bytearray):
        message = bytes(message)
    digest = Hash(SHA256(), backend=default_backend())
    digest.update(message)
    return digest.finalize()
Exemplo n.º 16
0
def get_name(area):
    halg = tpm2_to_crypto_alg(area.nameAlg)
    algp = area.nameAlg.to_bytes(2, 'big')
    pbuf = marshal(area)
    h = Hash(halg(), default_backend())
    h.update(pbuf)
    dig = h.finalize()
    name = algp + dig
    return name
Exemplo n.º 17
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())
Exemplo 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:]
Exemplo n.º 19
0
def sha256(message):
    """Generates a SHA256 hash of a message"""
    if isinstance(message, str):
        message = bytes(message, encoding='utf-8')
    elif isinstance(message, bytearray):
        message = bytes(message)
    digest = Hash(SHA256(), backend=default_backend())
    digest.update(message)
    return digest.finalize()
Exemplo n.º 20
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()
Exemplo n.º 21
0
    def compute_hash(cls, data: bytes) -> bytes:
        h = Hash(algorithm=cls.get_hash_func(), backend=default_backend())
        h.update(data)
        digest = h.finalize()

        if cls.trunc_size:
            digest = digest[:cls.trunc_size]

        return digest
Exemplo n.º 22
0
 def decrypt(self, ciphertext: bytes) -> bytes:
     decryptor = self._cipher.decryptor()  # type: ignore
     assert isinstance(decryptor, CipherContext)
     plaintext = decryptor.update(ciphertext) + decryptor.finalize()
     digest = Hash(SHA256())
     digest.update(plaintext)
     computed_hash = digest.finalize()
     if not bytes_eq(computed_hash, self._data_hash):
         raise RuntimeError('Decryption error')
     return plaintext[plaintext[0]:]
Exemplo n.º 23
0
def double_sha256(bytestr):
    hash1 = Hash(SHA256, DEFAULT_BACKEND)
    hash1.update(bytestr)
    hash1 = hash1.finalize()

    hash2 = Hash(SHA256, DEFAULT_BACKEND)
    hash2.update(hash1)
    hash2 = hash2.finalize()

    return hash2
Exemplo n.º 24
0
def _shorten_hmac_key(key: bytes) -> bytes:
    if len(key) > SHA1_BLOCK_SIZE:
        h = Hash(SHA1(), default_backend())  # nosec
        h.update(key)
        key = h.finalize()
    elif len(key) > HMAC_KEY_SIZE:
        raise NotSupportedError(
            "Key lengths > {} bytes not supported".format(HMAC_KEY_SIZE)
        )
    return key
Exemplo n.º 25
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]):]
Exemplo n.º 26
0
def get_pass(master: str, salt: str, version: Optional[int] = 2) -> str:
    """
    Get derived password from PassHash
    :param master: Master password
    :param salt: Site key (e.g. amazon.com)
    :param version: PassHash version, either 1 or 2 (recommended)
    :return:
    """
    fullpass = ''
    if version not in [1, 2]:
        raise ValueError('Wrong version {}, use either version 1 or 2 '
                         '(you can find them here http://tinyurl.com/y2qlwnxp)')
    if version == 2:
        """In version 2 of PassHash, hash is generated using PBKDF2HMAC-SHA256 using 1000 iterations"""
        pbkdf2_hash = binascii.hexlify(
            PBKDF2HMAC(SHA256, 32, salt.encode(), 1000, default_backend()).derive(master.encode())).decode()
        fullpass = convert(pbkdf2_hash,
                           "0123456789abcdef", "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
    if version == 1:
        """In version 1 of PassHash, hash is generated using SHA1(master + salt)"""
        hashobj = Hash(SHA1(), default_backend())
        hashobj.update(master.encode() + salt.encode())
        fullpass = convert(binascii.hexlify(hashobj.finalize()).decode(), "0123456789abcdef",
                           "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
    passwd = ""
    chars = 0
    i = 0

    while chars < 12:
        j = i % 12
        if chars == 0 and (fullpass[j:j + 1].upper() != fullpass[j:j + 1]):
            passwd += fullpass[j:j + 1]
            chars += 1
        elif chars == 1 and (parse_int(fullpass[j:j + 1]) != -99):
            passwd += fullpass[j:j + 1]
            chars += 1
        elif chars == 2 and (fullpass[j:j + 1].lower() != fullpass[j:j + 1]):
            passwd += fullpass[j:j + 1]
            chars += 1
        elif chars > 2:
            passwd += fullpass[j:j + 1]
            chars += 1
        elif chars == 0 and i >= len(fullpass):
            passwd += 'f'
            chars += 1
        elif chars == 1 and i >= len(fullpass) * 2:
            passwd += '7'
            chars += 1
        elif chars == 2 and i >= len(fullpass) * 3:
            passwd += 'T'
            chars += 1
        i += 1

    return passwd
Exemplo n.º 27
0
    def compute_verify_data(self, basekey, handshake_context):
        hash_len = self.hash.digest_size
        finished_key = self.expand_label(basekey, b"finished", b"", hash_len)

        h = Hash(self.hash, backend=default_backend())
        h.update(handshake_context)
        hash_value = h.finalize()

        hm = HMAC(finished_key, self.hash, default_backend())
        hm.update(hash_value)
        return hm.finalize()
Exemplo n.º 28
0
    def login(email, password):

        user = User.query.filter(User.email == email).first()

        h = Hash(SHA256(), default_backend())
        h.update(password.encode('utf-8'))

        if not user.password == h.finalize():
            return None
        else:
            return user
Exemplo n.º 29
0
    def generate(time: datetime) -> "Challenge":
        assert isinstance(time, datetime)
        ts = int(time.timestamp())
        ts = ts.to_bytes((ts.bit_length() + 7) // 8, 'big')
        rs = os.urandom(Challenge._hash_algo.digest_size)

        h = Hash(Challenge._hash_algo(), backend=default_backend())
        h.update(ts)
        h.update(rs)

        return Challenge(h.finalize())
Exemplo n.º 30
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
Exemplo n.º 31
0
def alternative_evmctl_check(file_path, pubkey):
    # In RHEL7, evmctl is too old, so we won't be able to run the
    #  evmctl check
    ima_sig = bytearray(xattr.getxattr(file_path, 'user.ima'))
    if ima_sig[0] != 3:
        raise Exception("IMA signature has wrong prefix (%s)" % ima_sig[0])
    if ima_sig[1] != 2:
        raise Exception("IMA signature has wrong version (%s)" % ima_sig[1])
    algo_id = ima_sig[2]
    if algo_id == 7:  # SHA224
        hasher = hashlib.sha224()
        crypto_algo = crypto_hashes.SHA224()
    elif algo_id == 4:  # SHA256
        hasher = hashlib.sha256()
        crypto_algo = crypto_hashes.SHA256()
    elif algo_id == 5:  # SHA384
        hasher = hashlib.sha384()
        crypto_algo = crypto_hashes.SHA384()
    elif algo_id == 6:  # SHA512
        hasher = hashlib.sha512()
        crypto_algo = crypto_hashes.SHA512()
    else:
        raise Exception("IMA signature has invalid algo: %d" % algo_id)
    crypto_algo = Prehashed(crypto_algo)
    if sys.version_info.major == 3:
        # X962 is only supported on Cryptography 2.5+
        # We are a bit lazy and just check for py3 instead of checking this more carefully

        # Check the Key ID
        key_id = ima_sig[3:7]
        keybytes = pubkey.public_bytes(
            crypto_serialization.Encoding.X962,
            crypto_serialization.PublicFormat.UncompressedPoint,
        )
        keybytes_digester = Hash(SHA1())
        keybytes_digester.update(keybytes)
        keybytes_digest = keybytes_digester.finalize()
        correct_keyid = keybytes_digest[-4:]
        if correct_keyid != key_id:
            raise Exception("IMA signature has invalid key ID: %s != %s" % (correct_keyid, key_id))
    # Check the signature itself
    (sig_size,) = struct.unpack('>H', ima_sig[7:9])
    sig = ima_sig[9:]
    if len(sig) != sig_size:
        raise Exception("IMA signature size invalid: %d != %d" % (len(sig), sig_size))

    with open(file_path, 'rb') as f:
        hasher.update(f.read())
        file_digest = hasher.digest()
    pubkey.verify(
        bytes(sig),
        bytes(file_digest),
        crypto_ec.ECDSA(crypto_algo),
    )
Exemplo n.º 32
0
    def compute_verify_data(self, basekey, handshake_context):
        hash_len = self.hash.digest_size
        finished_key = self.expand_label(basekey, b"finished", b"", hash_len)

        h = Hash(self.hash, backend=default_backend())
        h.update(handshake_context)
        hash_value = h.finalize()

        hm = HMAC(finished_key, self.hash, default_backend())
        hm.update(hash_value)
        return hm.finalize()
Exemplo n.º 33
0
 def derive(self, key_material):
     if not isinstance(key_material, bytes):
         raise TypeError("key_material must be bytes.")
     h = Hash(self._algorithm(), backend=self._backend)
     h.update(key_material)
     h.update(self._salt)
     derived_key = h.finalize()
     for i in xrange(self._iterations-1):
         h = Hash(self._algorithm(), backend=self._backend)
         h.update(derived_key)
         derived_key = h.finalize()
     return derived_key
Exemplo n.º 34
0
def a_decrypt_item(data, key, aes_size=A_AES_SIZE):
    key_size = KEY_SIZE[aes_size]
    if data[:len(SALT_MARKER)] == SALT_MARKER:
        salt = data[len(SALT_MARKER):len(SALT_MARKER) + SALT_SIZE]
        data = data[len(SALT_MARKER) + SALT_SIZE:]
        pb_gen = pbkdf1.PBKDF1(key, salt)
        nkey = pb_gen.read(key_size)
        iv = pb_gen.read(key_size)
    else:
        digest = Hash(MD5(), backend=_backend)
        digest.update(key)
        nkey = digest.finalize()
        iv = '\x00'*key_size

    aes = Cipher(algorithms.AES(nkey), modes.CBC(iv), backend=_backend)
    decryptor = aes.decryptor()
    return padding.pkcs5_unpad(decryptor.update(data) + decryptor.finalize())
Exemplo n.º 35
0
    def decrypt_encryption_key_fallback(self):
        """Decrypts the encryption key using the FALLBACK method. In this method, the
        context string, usually "CredEncryption" or "PSEEncryption", is encrypted using
        a derivation of a fixed key hardcoded in CommonCryptoLib, and used as key to
        encrypt the actual encryption key used in the file with the AES cipher.

        :return: Encryption key decrypted
        :rtype: string
        """
        log_lps.debug("Obtaining encryption key with FALLBACK LPS mode")

        digest = Hash(SHA1(), backend=default_backend())
        digest.update(cred_key_lps_fallback)
        hashed_key = digest.finalize()

        hmac = HMAC(hashed_key, SHA1(), backend=default_backend())
        hmac.update(self.context)
        default_key = hmac.finalize()[:16]

        iv = "\x00" * 16
        decryptor = Cipher(algorithms.AES(default_key), modes.CBC(iv), backend=default_backend()).decryptor()
        encryption_key = decryptor.update(self.encrypted_key) + decryptor.finalize()

        return encryption_key
Exemplo n.º 36
0
def _generate_property_iv(entity_iv, pk, rk, property_name, isJavaV1):
    '''
    Uses the entity_iv, partition key, and row key to generate and return
    the iv for the specified property.
    '''
    digest = Hash(SHA256(), default_backend())
    if not isJavaV1:
        digest.update(entity_iv +
                      (rk + pk + property_name).encode('utf-8'))
    else:
        digest.update(entity_iv +
                      (pk + rk + property_name).encode('utf-8'))
    propertyIV = digest.finalize()
    return propertyIV[:16]
Exemplo n.º 37
0
 def _get_digest(self, data, digest_algorithm):
     hasher = Hash(algorithm=digest_algorithm, backend=default_backend())
     hasher.update(data)
     return ensure_str(b64encode(hasher.finalize()))
Exemplo n.º 38
0
def sha1(msg):
    sha = Hash(SHA1(), backend=bend)
    sha.update(msg)
    return sha.finalize()
Exemplo n.º 39
0
 def derive_secret(self, secret, label, messages):
     h = Hash(self.hash, backend=default_backend())
     h.update(messages)
     hash_messages = h.finalize()
     hash_len = self.hash.digest_size
     return self.expand_label(secret, label, hash_messages, hash_len)
Exemplo n.º 40
0
class ntor(object):
    def __init__(self, node):
        # 5.1.4. The "ntor" handshake

        # This handshake uses a set of DH handshakes to compute a set of
        # shared keys which the client knows are shared only with a particular
        # server, and the server knows are shared with whomever sent the
        # original handshake (or with nobody at all).  Here we use the
        # "curve25519" group and representation as specified in "Curve25519:
        # new Diffie-Hellman speed records" by D. J. Bernstein.

        # [The ntor handshake was added in Tor 0.2.4.8-alpha.]

        self.node = node

        # In this section, define:
        #   H(x,t) as HMAC_SHA256 with message x and key t.
        #   H_LENGTH  = 32.
        #   ID_LENGTH = 20.
        #   G_LENGTH  = 32
        #   PROTOID   = "ntor-curve25519-sha256-1"
        #   t_mac     = PROTOID | ":mac"
        #   t_key     = PROTOID | ":key_extract"
        #   t_verify  = PROTOID | ":verify"
        #   MULT(a,b) = the multiplication of the curve25519 point 'a' by the
        #               scalar 'b'.
        #   G         = The preferred base point for curve25519 ([9])
        #   KEYGEN()  = The curve25519 key generation algorithm, returning
        #               a private/public keypair.
        #   m_expand  = PROTOID | ":key_expand"

        # H is defined as hmac()
        # MULT is included in the curve25519 library as get_shared_key()
        # KEYGEN() is curve25519.Private()
        self.protoid = 'ntor-curve25519-sha256-1'
        self.t_mac = self.protoid + ':mac'
        self.t_key = self.protoid + ':key_extract'
        self.t_verify = self.protoid + ':verify'
        self.m_expand = self.protoid + ':key_expand'

        # To perform the handshake, the client needs to know an identity key
        # digest for the server, and an ntor onion key (a curve25519 public
        # key) for that server. Call the ntor onion key "B".  The client
        # generates a temporary keypair:
        #     x,X = KEYGEN()
        self.x = curve25519.Private()
        self.X = self.x.get_public()

        self.B = curve25519.Public(b64decode(self.node['ntor-onion-key']))

        # and generates a client-side handshake with contents:
        #   NODEID      Server identity digest  [ID_LENGTH bytes]
        #   KEYID       KEYID(B)                [H_LENGTH bytes]
        #   CLIENT_PK   X                       [G_LENGTH bytes]
        self.handshake  = b64decode(self.node['identity'])
        self.handshake += self.B.serialize()
        self.handshake += self.X.serialize()

    def complete_handshake(self, Y, auth):
        # The server's handshake reply is:
        # SERVER_PK   Y                       [G_LENGTH bytes]
        # AUTH        H(auth_input, t_mac)    [H_LENGTH bytes]

        # The client then checks Y is in G^* [see NOTE below], and computes

        # secret_input = EXP(Y,x) | EXP(B,x) | ID | B | X | Y | PROTOID
        si  = self.x.get_shared_key(curve25519.Public(Y), hash_func)
        si += self.x.get_shared_key(self.B, hash_func)
        si += b64decode(self.node['identity'])
        si += self.B.serialize()
        si += self.X.serialize()
        si += Y
        si += 'ntor-curve25519-sha256-1'

        # KEY_SEED = H(secret_input, t_key)
        # verify = H(secret_input, t_verify)
        key_seed = hmac(self.t_key, si)
        verify = hmac(self.t_verify, si)

        # auth_input = verify | ID | B | Y | X | PROTOID | "Server"
        ai = verify
        ai += b64decode(self.node['identity'])
        ai += self.B.serialize()
        ai += Y
        ai += self.X.serialize()
        ai += self.protoid
        ai += 'Server'

        # The client verifies that AUTH == H(auth_input, t_mac).
        if auth != hmac(self.t_mac, ai):
            raise NtorError('auth input does not match.')

        # Both parties check that none of the EXP() operations produced the
        # point at infinity. [NOTE: This is an adequate replacement for
        # checking Y for group membership, if the group is curve25519.]

        # Both parties now have a shared value for KEY_SEED.  They expand this
        # into the keys needed for the Tor relay protocol, using the KDF
        # described in 5.2.2 and the tag m_expand.

        # 5.2.2. KDF-RFC5869

        # For newer KDF needs, Tor uses the key derivation function HKDF from
        # RFC5869, instantiated with SHA256.  (This is due to a construction
        # from Krawczyk.)  The generated key material is:

        #     K = K_1 | K_2 | K_3 | ...

        #     Where H(x,t) is HMAC_SHA256 with value x and key t
        #       and K_1     = H(m_expand | INT8(1) , KEY_SEED )
        #       and K_(i+1) = H(K_i | m_expand | INT8(i+1) , KEY_SEED )
        #       and m_expand is an arbitrarily chosen value,
        #       and INT8(i) is a octet with the value "i".

        # In RFC5869's vocabulary, this is HKDF-SHA256 with info == m_expand,
        # salt == t_key, and IKM == secret_input.
        keys = hkdf(key_seed, length=72, info=self.m_expand)

        # When used in the ntor handshake, the first HASH_LEN bytes form the
        # forward digest Df; the next HASH_LEN form the backward digest Db; the
        # next KEY_LEN form Kf, the next KEY_LEN form Kb, and the final
        # DIGEST_LEN bytes are taken as a nonce to use in the place of KH in the
        # hidden service protocol.  Excess bytes from K are discarded.
        Df, Db, Kf, Kb = struct.unpack('>20s20s16s16s', keys)

        # we do what we can with what we've got.
        del self.X
        del self.x
        del self.B
        del key_seed
        del keys
        del verify
        del ai
        del auth
        del si
        del Y

        self.send_digest = Hash(SHA1(), backend=bend)
        self.send_digest.update(Df)
        self.recv_digest = Hash(SHA1(), backend=bend)
        self.recv_digest.update(Db)

        self.encrypt = Cipher(AES(Kf), CTR('\x00' * 16), backend=bend).encryptor()
        self.decrypt = Cipher(AES(Kb), CTR('\x00' * 16), backend=bend).decryptor()

    def get_handshake(self):
        return self.handshake
Exemplo n.º 41
0
    def complete_handshake(self, Y, auth):
        # The server's handshake reply is:
        # SERVER_PK   Y                       [G_LENGTH bytes]
        # AUTH        H(auth_input, t_mac)    [H_LENGTH bytes]

        # The client then checks Y is in G^* [see NOTE below], and computes

        # secret_input = EXP(Y,x) | EXP(B,x) | ID | B | X | Y | PROTOID
        si  = self.x.get_shared_key(curve25519.Public(Y), hash_func)
        si += self.x.get_shared_key(self.B, hash_func)
        si += b64decode(self.node['identity'])
        si += self.B.serialize()
        si += self.X.serialize()
        si += Y
        si += 'ntor-curve25519-sha256-1'

        # KEY_SEED = H(secret_input, t_key)
        # verify = H(secret_input, t_verify)
        key_seed = hmac(self.t_key, si)
        verify = hmac(self.t_verify, si)

        # auth_input = verify | ID | B | Y | X | PROTOID | "Server"
        ai = verify
        ai += b64decode(self.node['identity'])
        ai += self.B.serialize()
        ai += Y
        ai += self.X.serialize()
        ai += self.protoid
        ai += 'Server'

        # The client verifies that AUTH == H(auth_input, t_mac).
        if auth != hmac(self.t_mac, ai):
            raise NtorError('auth input does not match.')

        # Both parties check that none of the EXP() operations produced the
        # point at infinity. [NOTE: This is an adequate replacement for
        # checking Y for group membership, if the group is curve25519.]

        # Both parties now have a shared value for KEY_SEED.  They expand this
        # into the keys needed for the Tor relay protocol, using the KDF
        # described in 5.2.2 and the tag m_expand.

        # 5.2.2. KDF-RFC5869

        # For newer KDF needs, Tor uses the key derivation function HKDF from
        # RFC5869, instantiated with SHA256.  (This is due to a construction
        # from Krawczyk.)  The generated key material is:

        #     K = K_1 | K_2 | K_3 | ...

        #     Where H(x,t) is HMAC_SHA256 with value x and key t
        #       and K_1     = H(m_expand | INT8(1) , KEY_SEED )
        #       and K_(i+1) = H(K_i | m_expand | INT8(i+1) , KEY_SEED )
        #       and m_expand is an arbitrarily chosen value,
        #       and INT8(i) is a octet with the value "i".

        # In RFC5869's vocabulary, this is HKDF-SHA256 with info == m_expand,
        # salt == t_key, and IKM == secret_input.
        keys = hkdf(key_seed, length=72, info=self.m_expand)

        # When used in the ntor handshake, the first HASH_LEN bytes form the
        # forward digest Df; the next HASH_LEN form the backward digest Db; the
        # next KEY_LEN form Kf, the next KEY_LEN form Kb, and the final
        # DIGEST_LEN bytes are taken as a nonce to use in the place of KH in the
        # hidden service protocol.  Excess bytes from K are discarded.
        Df, Db, Kf, Kb = struct.unpack('>20s20s16s16s', keys)

        # we do what we can with what we've got.
        del self.X
        del self.x
        del self.B
        del key_seed
        del keys
        del verify
        del ai
        del auth
        del si
        del Y

        self.send_digest = Hash(SHA1(), backend=bend)
        self.send_digest.update(Df)
        self.recv_digest = Hash(SHA1(), backend=bend)
        self.recv_digest.update(Db)

        self.encrypt = Cipher(AES(Kf), CTR('\x00' * 16), backend=bend).encryptor()
        self.decrypt = Cipher(AES(Kb), CTR('\x00' * 16), backend=bend).decryptor()
Exemplo n.º 42
0
def sha1_hash(data):
    sha = Hash(SHA1(), backend)
    sha.update(data)
    return sha.finalize()
Exemplo n.º 43
0
# new Z2 instead of Kz in the KDF
KDF2_input = b'EAP-NOOB' + base64url_decode(Np2_b64) + base64url_decode(Ns2_b64)
KDF2_out = KDF(algorithm=SHA256(), length=288, otherinfo=KDF2_input,
    backend=default_backend()).derive(Kz)
Kms2 = KDF2_out[224:256]
Kmp2 = KDF2_out[256:288]

# Remove trailing '=' from base64 encoded values
Np_b64 = Np_b64.strip('=')
Ns_b64 = Ns_b64.strip('=')
Np2_b64 = Np2_b64.strip('=')
Ns2_b64 = Ns2_b64.strip('=')
Noob_b64 = Noob_b64.strip('=')

## NoobId
NoobId_input = Hash(SHA256(), backend=default_backend())
NoobId_input.update(b'NoobId')
NoobId_input.update(Noob_b64.encode())
NoobId = NoobId_input.finalize()[:16]
NoobId_b64 = base64url_encode(NoobId).decode().strip('=')

## Hoob
Hoob_values = loads('{"Hoob":[]}', object_pairs_hook=OrderedDict)
Hoob_values['Hoob'] = [Dir, Vers, Verp, PeerId, Cryptosuites, Dirs,
    loads(ServerInfo, object_pairs_hook=OrderedDict), Cryptosuitep, Dirp, Realm,
        loads(PeerInfo, object_pairs_hook=OrderedDict), 0, PKs_full, Ns_b64,
            PKp_full, Np_b64, Noob_b64]
Hoob_input = Hash(SHA256(), backend=default_backend())
Hoob_input.update(dumps(Hoob_values['Hoob'], separators=(',', ':')).encode())
Hoob = Hoob_input.finalize()[:16]
Hoob_b64 = base64url_encode(Hoob).decode().strip('=')
Exemplo n.º 44
0
 def digest(inp):
     h = Hash(self._algorithm(), backend=self._backend)
     h.update(inp)
     return h.finalize()
    def test_validate_encryption(self):
        # Arrange 
        entity = self._create_default_entity_for_encryption()
        key_encryption_key = KeyWrapper('key1')
        self.ts.key_encryption_key = key_encryption_key
        self.ts.insert_entity(self.table_name, entity)

        # Act
        self.ts.key_encryption_key = None
        entity = self.ts.get_entity(self.table_name, entity['PartitionKey'], entity['RowKey'])

        # Note the minor discrepancy from the normal decryption process: because the entity was retrieved
        # without being decrypted, the encrypted_properties list is now stored in an EntityProperty object
        # and is already raw bytes.
        encrypted_properties_list = entity['_ClientEncryptionMetadata2'].value
        encryption_data = entity['_ClientEncryptionMetadata1']
        encryption_data = _dict_to_encryption_data(loads(encryption_data))

        content_encryption_key = key_encryption_key.unwrap_key(encryption_data.wrapped_content_key.encrypted_key,
                                                           encryption_data.wrapped_content_key.algorithm)

        digest = Hash(SHA256(), default_backend())
        digest.update(encryption_data.content_encryption_IV +
                        (entity['RowKey'] + entity['PartitionKey'] + '_ClientEncryptionMetadata2').encode('utf-8'))
        metadataIV = digest.finalize()
        metadataIV = metadataIV[:16]

        cipher = _generate_AES_CBC_cipher(content_encryption_key, metadataIV)

        # Decrypt the data.
        decryptor = cipher.decryptor()
        encrypted_properties_list = decryptor.update(encrypted_properties_list) + decryptor.finalize()

        # Unpad the data.
        unpadder = PKCS7(128).unpadder()
        encrypted_properties_list = unpadder.update(encrypted_properties_list) + unpadder.finalize()

        encrypted_properties_list = encrypted_properties_list.decode('utf-8')

        # Strip the square braces from the ends and split string into list.
        encrypted_properties_list = loads(encrypted_properties_list)

        entity_iv, encrypted_properties, content_encryption_key = \
            (encryption_data.content_encryption_IV, encrypted_properties_list, content_encryption_key)

        decrypted_entity = deepcopy(entity)

        for property in encrypted_properties_list:
            value = entity[property]

            digest = Hash(SHA256(), default_backend())
            digest.update(entity_iv +
                            (entity['RowKey'] + entity['PartitionKey'] + property).encode('utf-8'))
            propertyIV = digest.finalize()
            propertyIV = propertyIV[:16]

            cipher = _generate_AES_CBC_cipher(content_encryption_key,
                                              propertyIV)

            # Decrypt the property.
            decryptor = cipher.decryptor()
            decrypted_data = (decryptor.update(value.value) + decryptor.finalize())
        
            # Unpad the data.
            unpadder = PKCS7(128).unpadder()
            decrypted_data = (unpadder.update(decrypted_data) + unpadder.finalize())

            decrypted_data = decrypted_data.decode('utf-8')
        
            decrypted_entity[property] = decrypted_data

        decrypted_entity.pop('_ClientEncryptionMetadata1')
        decrypted_entity.pop('_ClientEncryptionMetadata2')

        
        # Assert
        self.assertEqual(decrypted_entity['sex'], 'male')