Exemplo n.º 1
0
def test_aes_gcm(backend, wycheproof):
    key = binascii.unhexlify(wycheproof.testcase["key"])
    iv = binascii.unhexlify(wycheproof.testcase["iv"])
    aad = binascii.unhexlify(wycheproof.testcase["aad"])
    msg = binascii.unhexlify(wycheproof.testcase["msg"])
    ct = binascii.unhexlify(wycheproof.testcase["ct"])
    tag = binascii.unhexlify(wycheproof.testcase["tag"])
    if wycheproof.valid or wycheproof.acceptable:
        enc = Cipher(algorithms.AES(key), modes.GCM(iv), backend).encryptor()
        enc.authenticate_additional_data(aad)
        computed_ct = enc.update(msg) + enc.finalize()
        computed_tag = enc.tag
        assert computed_ct == ct
        assert computed_tag == tag
        dec = Cipher(
            algorithms.AES(key),
            modes.GCM(iv, tag, min_tag_length=len(tag)),
            backend
        ).decryptor()
        dec.authenticate_additional_data(aad)
        computed_msg = dec.update(ct) + dec.finalize()
        assert computed_msg == msg
    elif len(iv) == 0:
        with pytest.raises(ValueError):
            Cipher(algorithms.AES(key), modes.GCM(iv), backend)
    else:
        dec = Cipher(
            algorithms.AES(key),
            modes.GCM(iv, tag, min_tag_length=len(tag)),
            backend
        ).decryptor()
        dec.authenticate_additional_data(aad)
        dec.update(ct)
        with pytest.raises(InvalidTag):
            dec.finalize()
def main():
    if type(cipher_key) != str or len(cipher_key) != cipher_key_bytelen:
        return "no key", 500

    auth = request.args.get('auth', None)
    if auth is None:
        cleartext = '{"userid":%d,"is_admin":0}' % random.randint(1000000, 2000000)
        iv = os.urandom(cipher_block_bytelen)
        padder = padding.PKCS7(cipher.block_size).padder()
        padded_data = padder.update(cleartext) + padder.finalize()
        encryptor = Cipher(cipher(cipher_key), modes.CBC(iv), backend=backend).encryptor()
        ciphertext = encryptor.update(padded_data) + encryptor.finalize()
        return redirect('/?auth=' + binascii.hexlify(iv + ciphertext))

    try:
        received = binascii.unhexlify(auth)
    except:
        return "hex error", 400
    # print "received"
    # hexdump.hexdump(received)
    # sys.stdout.flush()

    if len(received) < cipher_block_bytelen * 2:
        return "input too short", 400
    iv, ciphertext = received[:cipher_block_bytelen], received[cipher_block_bytelen:]

    decryptor = Cipher(cipher(cipher_key), modes.CBC(iv), backend=backend).decryptor()
    decrypted = decryptor.update(ciphertext) + decryptor.finalize()
    # print "decrypted"
    # hexdump.hexdump(decrypted)
    # sys.stdout.flush()

    unpadder = padding.PKCS7(cipher.block_size).unpadder()
    unpadded = unpadder.update(decrypted)
    try:
        unpadded += unpadder.finalize()
    except ValueError:
        return "padding error", 400
    # print "unpadded"
    # hexdump.hexdump(unpadded)
    # sys.stdout.flush()

    try:
        decoded = unpadded.decode('utf-8')
        parsed = json.loads(decoded)
    except:
        return "parsing error", 400

    if type(parsed) != dict or 'userid' not in parsed or 'is_admin' not in parsed:
        return "parsing error", 400

    if parsed['is_admin']:
        return "Hello user #%d, you are admin!" % parsed['userid']
    else:
        return "Hello user #%d!" % parsed['userid']
Exemplo n.º 3
0
    def encrypt_with_hmac(self, data, data_id, iv):
        if not isinstance(data, bytes):
            raise TypeError("data must be bytes.")

        if not isinstance(data_id, int):
            raise TypeError("data_id must be int.")

        main_parts = (
            struct.pack(config.FORMAT_CHAR, data_id) + data
        )

        # PKCS7 padding
        padded_data = self.add_padding(main_parts, algorithms.AES.block_size)
        # AES with CBC mode
        encryptor = Cipher(algorithms.AES(self.aes_key), modes.CBC(iv), backend=self.backend).encryptor()
        ciphertext = encryptor.update(padded_data) + encryptor.finalize()

        basic_parts = (
            b"\x80" + iv + ciphertext
        )

        h = HMAC(self.mac_key, hashes.SHA256(), backend=self.backend)
        h.update(basic_parts)
        hmac = h.finalize()
        return basic_parts + hmac
Exemplo n.º 4
0
def encrypt_v3(a_key, a_token, a_verbose = False):

    # Get sha-256 of key
    l_key = hashlib.sha256(a_key).hexdigest().decode('hex')

    # Generate iv
    l_iv = os.urandom(G_IV_SIZE_BYTES)  # TODO Make constant...

    # Construct an AES-GCM Cipher object with the given key and a
    # randomly generated IV.
    l_encryptor = Cipher(
        algorithms.AES(l_key),
        modes.GCM(l_iv),
        backend=default_backend()
    ).encryptor()

    # Encrypt the plaintext and get the associated ciphertext.
    # GCM does not require padding.
    l_ciphertext = l_encryptor.update(a_token) + l_encryptor.finalize()

    l_iv_ciphertext = l_iv + l_ciphertext + l_encryptor.tag

    #print 'TAG (len:%d) : %s'%(len(l_encryptor.tag), l_encryptor.tag)

    if a_verbose:
        print('+-------------------------------------------------------------')
        print('| l_iv:            %s'%(l_iv.encode('hex')))
        print('| l_ciphertext:    %s'%(l_ciphertext.encode('hex')))
        print('| l_tag:           %s'%(l_encryptor.tag.encode('hex')))
        print('+-------------------------------------------------------------')
        print('| l_encoded_token: %s'%(l_iv_ciphertext.encode('hex')))
        print('+-------------------------------------------------------------')

    return url_safe_base64_encode(l_iv_ciphertext)
Exemplo n.º 5
0
def decrypt(data: bytes, privkey: datatypes.PrivateKey, shared_mac_data: bytes = b'') -> bytes:
    """Decrypt data with ECIES method using the given private key

    1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) )
    2) verify tag
    3) decrypt

    ecdhAgree(r, recipientPublic) == ecdhAgree(recipientPrivate, R)
    [where R = r*G, and recipientPublic = recipientPrivate*G]

    """
    if data[:1] != b'\x04':
        raise DecryptionError("wrong ecies header")

    #  1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) )
    shared = data[1:1 + PUBKEY_LEN]
    key_material = ecdh_agree(privkey, keys.PublicKey(shared))
    key = kdf(key_material)
    key_enc, key_mac = key[:KEY_LEN // 2], key[KEY_LEN // 2:]
    key_mac = sha256(key_mac).digest()
    tag = data[-KEY_LEN:]

    # 2) Verify tag
    expected_tag = hmac_sha256(key_mac, data[1 + PUBKEY_LEN:- KEY_LEN] + shared_mac_data)
    if not bytes_eq(expected_tag, tag):
        raise DecryptionError("Failed to verify tag")

    # 3) Decrypt
    algo = CIPHER(key_enc)
    blocksize = algo.block_size // 8
    iv = data[1 + PUBKEY_LEN:1 + PUBKEY_LEN + blocksize]
    ciphertext = data[1 + PUBKEY_LEN + blocksize:- KEY_LEN]
    ctx = Cipher(algo, MODE(iv), default_backend()).decryptor()
    return ctx.update(ciphertext) + ctx.finalize()
Exemplo n.º 6
0
def encrypt(data: bytes, pubkey: datatypes.PublicKey, shared_mac_data: bytes = b'') -> bytes:
    """Encrypt data with ECIES method to the given public key

    1) generate r = random value
    2) generate shared-secret = kdf( ecdhAgree(r, P) )
    3) generate R = rG [same op as generating a public key]
    4) 0x04 || R || AsymmetricEncrypt(shared-secret, plaintext) || tag
    """
    # 1) generate r = random value
    ephemeral = generate_privkey()

    # 2) generate shared-secret = kdf( ecdhAgree(r, P) )
    key_material = ecdh_agree(ephemeral, pubkey)
    key = kdf(key_material)
    key_enc, key_mac = key[:KEY_LEN // 2], key[KEY_LEN // 2:]

    key_mac = sha256(key_mac).digest()
    # 3) generate R = rG [same op as generating a public key]
    ephem_pubkey = ephemeral.public_key

    # Encrypt
    algo = CIPHER(key_enc)
    iv = os.urandom(algo.block_size // 8)
    ctx = Cipher(algo, MODE(iv), default_backend()).encryptor()
    ciphertext = ctx.update(data) + ctx.finalize()

    # 4) 0x04 || R || AsymmetricEncrypt(shared-secret, plaintext) || tag
    msg = b'\x04' + ephem_pubkey.to_bytes() + iv + ciphertext

    # the MAC of a message (called the tag) as per SEC 1, 3.5.
    tag = hmac_sha256(key_mac, msg[1 + PUBKEY_LEN:] + force_bytes(shared_mac_data))
    return msg + tag
Exemplo n.º 7
0
    def unwrap(self, key, ek):
        rk = self.get_key(key, 'decrypt')

        # Implement RFC 3394 Key Unwrap - 2.2.3
        # TODO: Use cryptography once issue #1733 is resolved
        iv = 'a6a6a6a6a6a6a6a6'
        Aiv = unhexlify(iv)

        R = [ek[i:i+8] for i in range(0, len(ek), 8)]
        A = R.pop(0)
        n = len(R)
        for j in range(5, -1, -1):
            for i in range(n - 1, -1, -1):
                AtR = _encode_int((_decode_int(A) ^ ((n*j)+i+1)), 64) + R[i]
                d = Cipher(algorithms.AES(rk), modes.ECB(),
                           backend=self.backend).decryptor()
                B = d.update(AtR) + d.finalize()
                A = B[:8]
                R[i] = B[-8:]

        if A != Aiv:
            raise InvalidJWEData('Decryption Failed')

        cek = b''.join(R)
        return cek
Exemplo n.º 8
0
    def decrypt(self, n, ad, ciphertext):
        '''
           Returns plaintext or raises MessageAuthenticationFailure exception
           if fail to authenticate.
        '''

        if len(ciphertext) < 16:
            raise ValueError(
                'Invalid ciphertext length (len={0}), must be >16 bytes.'.format(len(ciphertext))
            )

        n = self._nonce(n)

        decryptor = Cipher(
            algorithms.AES(self.key),
            modes.GCM(n, ciphertext[-16:]),
            backend=default_backend()
        ).decryptor()

        decryptor.authenticate_additional_data(ad)
        try:
            plaintext = decryptor.update(ciphertext[:-16]) + decryptor.finalize()
        except _InvalidTag:
            raise MessageAuthenticationFailure
        except:
            raise

        return plaintext
Exemplo n.º 9
0
    def decrypt(self, data, ttl=None):
        """
        :type data: bytes
        :type ttl: int
        :rtype: bytes
        """
        data = self._signer.unsign(data, ttl)

        iv = data[:16]
        ciphertext = data[16:]
        decryptor = Cipher(
            algorithms.AES(self._encryption_key), modes.CBC(iv),
            self._backend).decryptor()
        plaintext_padded = decryptor.update(ciphertext)
        try:
            plaintext_padded += decryptor.finalize()
        except ValueError:
            raise InvalidToken

        # Remove padding
        unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
        unpadded = unpadder.update(plaintext_padded)
        try:
            unpadded += unpadder.finalize()
        except ValueError:
            raise InvalidToken
        return unpadded
Exemplo n.º 10
0
def _decrypt_aesgcm(key, nonce, ciphertext_tag, associated_data):
    """
    Decrypts a ciphertext with associated data with AES GCM.

    Args:
        key:                encryption key
        nonce:              nonce for encryption
        ciphertext_tag:     ciphertext with appended tag to decrypt
        associated_data:    additional authenticated associated data (the AD in AEAD)

    Returns:
        decrypted plaintext
    """
    if len(ciphertext_tag) < MAC_BYTES:
        raise NoiseError('Truncated ciphertext (length < authentication tag length).')
    algo = algorithms.AES(key)
    assert len(nonce) == 12, 'Expected 96 bit nonce for AES-GCM'
    ciphertext, tag = ciphertext_tag[:-MAC_BYTES], ciphertext_tag[-MAC_BYTES:]
    mode = modes.GCM(nonce, tag)
    decryptor = Cipher(algo, mode, backend).decryptor()
    decryptor.authenticate_additional_data(associated_data)
    try:
        return decryptor.update(ciphertext) + decryptor.finalize()
    except InvalidTag as invalid_tag:
        raise NoiseError('GMAC failure') from invalid_tag
Exemplo n.º 11
0
 def decrypt(self, orig_pkt, assoclen=None):
     """decrypt a MACsec frame for this Secure Association"""
     hdr = copy.deepcopy(orig_pkt)
     del hdr[MACsec].payload
     pktlen = len(orig_pkt)
     if self.send_sci:
         hdrlen = NOSCI_LEN + SCI_LEN
     else:
         hdrlen = NOSCI_LEN
     if assoclen is None or not self.do_encrypt:
         if self.do_encrypt:
             assoclen = hdrlen
         else:
             assoclen = pktlen - self.icvlen
     iv = self.make_iv(hdr)
     assoc, ct, icv = MACsecSA.split_pkt(orig_pkt, assoclen, self.icvlen)
     decryptor = Cipher(
         algorithms.AES(self.key),
         modes.GCM(iv, icv),
         backend=default_backend()
     ).decryptor()
     decryptor.authenticate_additional_data(assoc)
     pt = assoc[hdrlen:assoclen]
     pt += decryptor.update(ct)
     pt += decryptor.finalize()
     hdr[MACsec].type = struct.unpack('!H', pt[0:2])[0]
     hdr[MACsec].payload = Raw(pt[2:])
     return hdr
Exemplo n.º 12
0
    def _decrypt_data(self, data, timestamp, ttl):
        current_time = int(time.time())
        if ttl is not None:
            if timestamp + ttl < current_time:
                raise InvalidToken

            if current_time + _MAX_CLOCK_SKEW < timestamp:
                raise InvalidToken

        h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend)
        h.update(data[:-32])
        try:
            h.verify(data[-32:])
        except InvalidSignature:
            raise InvalidToken

        iv = data[9:25]
        ciphertext = data[25:-32]
        decryptor = Cipher(
            algorithms.AES(self._encryption_key), modes.CBC(iv), self._backend
        ).decryptor()
        plaintext_padded = decryptor.update(ciphertext)
        try:
            plaintext_padded += decryptor.finalize()
        except ValueError:
            raise InvalidToken
        unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()

        unpadded = unpadder.update(plaintext_padded)
        try:
            unpadded += unpadder.finalize()
        except ValueError:
            raise InvalidToken
        return unpadded
Exemplo n.º 13
0
def decrypt(value, key, stash=None):
    """
    Return a decrypted value
    """
    # extract fields using a regex
    res = re.match(r'^ENC\[AES256_GCM,data:(.+),iv:(.+),aad:(.+),tag:(.+)\]$',
                   value)
    # if the value isn't in encrypted form, return it as is
    if res is None:
        return value
    enc_value = b64decode(res.group(1))
    iv = b64decode(res.group(2))
    aad = b64decode(res.group(3))
    tag = b64decode(res.group(4))
    decryptor = Cipher(algorithms.AES(key),
                       modes.GCM(iv, tag),
                       default_backend()
                       ).decryptor()
    decryptor.authenticate_additional_data(aad)
    cleartext = decryptor.update(enc_value) + decryptor.finalize()
    if stash:
        # save the values for later if we need to reencrypt
        stash['iv'] = iv
        stash['aad'] = aad
        stash['cleartext'] = cleartext
    return cleartext
Exemplo n.º 14
0
def decrypt(data, key):
    iv = data[0:16]
    data = data[16:]
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()).decryptor()
    data = cipher.update(data) + cipher.finalize()
    padder = padding.PKCS7(128).unpadder()
    return padder.update(data) + padder.finalize()
Exemplo n.º 15
0
    def decrypt(self, data):
        """
        Decrypts an AESGCM payload.

        Relies on constants:
            :attr:`~crypto.aesgcm.IV_SIZE`

            :attr:`~crypto.aesgcm.TAG_SIZE`

        :param data: The raw data to decrypt
        :type data: bytes
        :returns: Decrypted data
        :rtype: bytes
        """
        iv = data[:IV_SIZE]
        payload = data[IV_SIZE: -TAG_SIZE]
        tag = data[-TAG_SIZE:]

        decryptor = Cipher(
            algorithms.AES(self.key),
            modes.GCM(iv, tag),
            backend=default_backend()
        ).decryptor()

        decryptor.authenticate_additional_data(iv)

        return decryptor.update(payload) + decryptor.finalize()
Exemplo n.º 16
0
    def lookup_origin_text(
        self, secure_text: str,
            valid_length: Optional[int]=None) -> str:
        try:
            encrypted_text_reader = io.BytesIO(base64.b64decode(secure_text))
        except:  # Unable to decode the data.
            return None

        try:
            iv = encrypted_text_reader.read(16)
            length = struct.unpack("l", encrypted_text_reader.read(8))[0]
            ciphertext = encrypted_text_reader.read(length)
            tag = encrypted_text_reader.read(16)
        except:  # Unable to split the data.
            return None

        decryptor = AESCipher(
            aes_algorithms.AES(self._security_secret),
            aes_modes.GCM(iv, tag),
            backend=aes_backend()
        ).decryptor()

        try:
            content = decryptor.update(ciphertext) + decryptor.finalize()
        except:  # Unable to decrypt and/or verify the data.
            return None

        timestamp = struct.unpack("l", content[:8])[0]
        text = content[8:]

        if valid_length and int(time.time()) - timestamp > valid_length:
            return None  # Data Expired.

        return ensure_str(text)
Exemplo n.º 17
0
    def encrypt(self, data):
        """
        .. warning::

            This should really have thread controls in it.
            If two threads are simutaneously encrypting,
            there is a small chance that the IVs would be the same.
            This would be **extremely** bad.

        :param data: The data to encrypt
        :type data: bytes
        :returns: IV + payload + TAG
        :rtype: bytes
        """
        # Grab && increment iv
        iv = self.iv
        self.iv = (int.from_bytes(iv, 'big') + 1).to_bytes(len(iv), 'big')

        # TODO: Do we have to make the encryptor every time?
        # Make the encryptor
        encryptor = Cipher(algorithms.AES(self.key),
                           modes.GCM(iv),
                           backend=default_backend()
                           ).encryptor()

        # Encrypt the data
        encryptor.authenticate_additional_data(iv)
        ciphertext = encryptor.update(data) + encryptor.finalize()

        return iv + ciphertext + encryptor.tag
Exemplo n.º 18
0
 def encrypt(self, orig_pkt, assoclen=None):
     """encrypt a MACsec frame for this Secure Association"""
     hdr = copy.deepcopy(orig_pkt)
     del hdr[MACsec].payload
     del hdr[MACsec].type
     pktlen = len(orig_pkt)
     if self.send_sci:
         hdrlen = NOSCI_LEN + SCI_LEN
     else:
         hdrlen = NOSCI_LEN
     if assoclen is None or not self.do_encrypt:
         if self.do_encrypt:
             assoclen = hdrlen
         else:
             assoclen = pktlen
     iv = self.make_iv(orig_pkt)
     assoc, pt, _ = MACsecSA.split_pkt(orig_pkt, assoclen)
     encryptor = Cipher(
         algorithms.AES(self.key),
         modes.GCM(iv),
         backend=default_backend()
     ).encryptor()
     encryptor.authenticate_additional_data(assoc)
     ct = encryptor.update(pt) + encryptor.finalize()
     hdr[MACsec].payload = Raw(assoc[hdrlen:assoclen] + ct + encryptor.tag)
     return hdr
Exemplo n.º 19
0
def aes_encrypt(passphrase, data):
    enc_salt = os.urandom(32)
    enc_iv = os.urandom(16)

    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA1(),
        length=32,
        salt=enc_salt,
        iterations=1000,
        backend=default_backend(),
    )
    enc_key = kdf.derive(passphrase)

    data += '\x00' * (16 - (len(data) % 16))

    cipher = Cipher(
        algorithms.AES(enc_key),
        modes.CBC(enc_iv),
        backend=default_backend()
    ).encryptor()
    enc_data = cipher.update(data) + cipher.finalize()

    return '\n'.join([
        base64.b64encode(enc_salt),
        base64.b64encode(enc_iv),
        base64.b64encode(enc_data),
    ])
Exemplo n.º 20
0
def aes_key_wrap(wrapping_key, key_to_wrap, backend):
    if len(wrapping_key) not in [16, 24, 32]:
        raise ValueError("The wrapping key must be a valid AES key length")

    if len(key_to_wrap) < 16:
        raise ValueError("The key to wrap must be at least 16 bytes")

    if len(key_to_wrap) % 8 != 0:
        raise ValueError("The key to wrap must be a multiple of 8 bytes")

    # RFC 3394 Key Wrap - 2.2.1 (index method)
    encryptor = Cipher(AES(wrapping_key), ECB(), backend).encryptor()
    a = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6"
    r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)]
    n = len(r)
    for j in range(6):
        for i in range(n):
            # every encryption operation is a discrete 16 byte chunk (because
            # AES has a 128-bit block size) and since we're using ECB it is
            # safe to reuse the encryptor for the entire operation
            b = encryptor.update(a + r[i])
            # pack/unpack are safe as these are always 64-bit chunks
            a = struct.pack(
                ">Q", struct.unpack(">Q", b[:8])[0] ^ ((n * j) + i + 1)
            )
            r[i] = b[-8:]

    assert encryptor.finalize() == b""

    return a + b"".join(r)
Exemplo n.º 21
0
def aes_key_unwrap(wrapping_key, wrapped_key, backend):
    if len(wrapped_key) < 24:
        raise ValueError("Must be at least 24 bytes")

    if len(wrapped_key) % 8 != 0:
        raise ValueError("The wrapped key must be a multiple of 8 bytes")

    if len(wrapping_key) not in [16, 24, 32]:
        raise ValueError("The wrapping key must be a valid AES key length")

    # Implement RFC 3394 Key Unwrap - 2.2.2 (index method)
    decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor()
    aiv = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6"

    r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)]
    a = r.pop(0)
    n = len(r)
    for j in reversed(range(6)):
        for i in reversed(range(n)):
            # pack/unpack are safe as these are always 64-bit chunks
            atr = struct.pack(
                ">Q", struct.unpack(">Q", a)[0] ^ ((n * j) + i + 1)
            ) + r[i]
            # every decryption operation is a discrete 16 byte chunk so
            # it is safe to reuse the decryptor for the entire operation
            b = decryptor.update(atr)
            a = b[:8]
            r[i] = b[-8:]

    assert decryptor.finalize() == b""

    if not bytes_eq(a, aiv):
        raise InvalidUnwrap()

    return b"".join(r)
Exemplo n.º 22
0
    def generate_secure_text(self, origin_text: str) -> str:
        """
        Encrypt and sign the origin text by ``cryptography`` library
        using AES GCM algorithm.

        :arg origin_text: is a string that will be encrypted by the provided
            security secret.
        """

        iv = os.urandom(16)

        content = struct.pack(
            "l", int(time.time())) + ensure_bytes(origin_text)

        encryptor = AESCipher(
            aes_algorithms.AES(ensure_bytes(self.__security_secret)),
            aes_modes.GCM(iv),
            backend=aes_backend()
        ).encryptor()

        ciphertext = encryptor.update(content) + encryptor.finalize()

        final_encrypted_text = iv
        final_encrypted_text += struct.pack("l", len(ciphertext))
        final_encrypted_text += ciphertext
        final_encrypted_text += encryptor.tag

        return ensure_str(base64.b64encode(final_encrypted_text))
Exemplo n.º 23
0
def decrypt_file(cipher_text):
    iv = cipher_text[:IV_LEN]
    decryptor = Cipher(
            algorithms.AES(key),
            modes.GCM(iv, cipher_text[IV_LEN:IV_LEN+TAG_LEN]),
            backend=b.default_backend()).decryptor()
    return decryptor.update(cipher_text[IV_LEN+TAG_LEN:]) + decryptor.finalize()
Exemplo n.º 24
0
 def decrypt(packed_encrypted_data, key, mac_key='', backend=BACKEND):
     """ Decrypts packed encrypted data as returned by encrypt with the same key. 
         If extra data is present, returns plaintext, extra_data. If not,
         returns plaintext. Raises InvalidTag on authentication failure. """
     header, ciphertext, iv, tag, extra_data = load_data(packed_encrypted_data)        
     algorithm, mode, authentication_algorithm = header.split('_', 2)   
     if algorithm.lower() in hashlib.algorithms_guaranteed:
         return cryptographyless.decrypt(packed_encrypted_data, key, mac_key, backend)
         
     mode_args = (iv, tag) if mode in AEAD_MODES else (iv, )
     decryptor = Cipher(getattr(algorithms, algorithm)(key), 
                        getattr(modes, mode)(*mode_args), 
                        backend=BACKEND).decryptor()
     if mode in AEAD_MODES:
         decryptor.authenticate_additional_data(extra_data)
     else:
         if not mac_key:
             raise ValueError("mac_key not supplied for {} mode".format(header))
         if not verify_mac(mac_key, save_data(tag, header + ciphertext + iv + extra_data), authentication_algorithm):
             raise InvalidTag("Failed to authenticate data")
         
     plaintext = decryptor.update(ciphertext) + decryptor.finalize()
     if extra_data:
         return (plaintext, extra_data)     
     else:
         return plaintext
Exemplo n.º 25
0
    def unwrap(self, key, keylen, ek, headers):
        rk = self._get_key(key, 'decrypt')

        # Implement RFC 3394 Key Unwrap - 2.2.3
        # TODO: Use cryptography once issue #1733 is resolved
        iv = 'a6a6a6a6a6a6a6a6'
        aiv = unhexlify(iv)

        r = [ek[i:i + 8] for i in range(0, len(ek), 8)]
        a = r.pop(0)
        n = len(r)
        for j in range(5, -1, -1):
            for i in range(n - 1, -1, -1):
                da = _decode_int(a)
                atr = _encode_int((da ^ ((n * j) + i + 1)), 64) + r[i]
                d = Cipher(algorithms.AES(rk), modes.ECB(),
                           backend=self.backend).decryptor()
                b = d.update(atr) + d.finalize()
                a = b[:8]
                r[i] = b[-8:]

        if a != aiv:
            raise InvalidJWEData('Decryption Failed')

        cek = b''.join(r)
        if len(cek) != keylen:
            raise InvalidJWEKeyLength(keylen, len(cek))
        return cek
def verifyThenDecrypt(cipher, emailTime, key):
	encryptKey = key[16:]
	signKey = key[:16]
	payload = base64.urlsafe_b64decode(cipher)

	#verify timestamp to prevent replay
	try:
		timestamp, = struct.unpack(">Q", payload[1:9])
	except struct.error:
		raise ValueError('Invalid message')
	if timestamp + TTL < emailTime:
		raise Exception('Invalid timestamp: replay attack detected')

	#verify HMAC
	hasher = HMAC(signKey, hashes.SHA256(), backend=default_backend())
	hasher.update(payload[:-32])
	try:
		hasher.verify(payload[-32:])
	except InvalidSignature:
		raise Exception('Invalid HMAC: data modification detected')

	#decrypt cipher text
	iv = payload[9:25]
	ciphertext = payload[25:-32]
	decryptor = Cipher(algorithms.AES(encryptKey), modes.CBC(iv), default_backend()).decryptor()
	paddedPlaintext = decryptor.update(ciphertext)
	paddedPlaintext += decryptor.finalize()
	unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
	plaintext = unpadder.update(paddedPlaintext)
	plaintext += unpadder.finalize()

	return plaintext
Exemplo n.º 27
0
def decrypt(key, associated_data, iv, ciphertext, tag):
    # Construct a Cipher object, with the key, iv, and additionally the
    # GCM tag used for authenticating the message.

    # OK.. all the objects passed in to this function are of type bytearray, but, it turns
    # out that the Cipher suite needs strings, despite saying in the documentation that it needs
    # bytes. Consequently all the parameter objects had to be converted to strings, hence the str()
    # around each one.
    # The moral of this story is strong typing is good.
    try:
        decryptor = Cipher(
            algorithms.AES(str(key)), modes.GCM(str(iv), str(tag)), backend=default_backend()
        ).decryptor()

        # We put associated_data back in or the tag will fail to verify
        # when we finalize the decryptor.
        decryptor.authenticate_additional_data(str(associated_data))

        # Decryption gets us the authenticated plaintext.
        # If the tag does not match an InvalidTag exception will be raised.
        ret = decryptor.update(str(ciphertext)) + decryptor.finalize()

    except Exception as e:
        print(" Failed to de-crypt Measurement with exception: {}: {}".format(e.__class__.__name__, e))
        ret = None

    return ret
Exemplo n.º 28
0
def encrypt(encryption_key, iv, data):
    """Encrypt the payload."""
    padder = padding.PKCS7(algorithms.AES.block_size).padder()
    data = padder.update(data.encode()) + padder.finalize()

    encryptor = Cipher(algorithms.AES(encryption_key), modes.CBC(iv), default_backend()).encryptor()
    return base64.urlsafe_b64encode(encryptor.update(data) + encryptor.finalize())
Exemplo n.º 29
0
def aes_decrypt(passphrase, data):
    data = data.split('\n')
    if len(data) < 3:
        raise ValueError('Invalid encryption data')

    enc_salt = base64.b64decode(data[0])
    enc_iv = base64.b64decode(data[1])
    enc_data = base64.b64decode(data[2])

    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA1(),
        length=32,
        salt=enc_salt,
        iterations=1000,
        backend=default_backend(),
    )
    enc_key = kdf.derive(passphrase)

    cipher = Cipher(
        algorithms.AES(enc_key),
        modes.CBC(enc_iv),
        backend=default_backend()
    ).decryptor()
    data = cipher.update(enc_data) + cipher.finalize()

    return data.replace('\x00', '')
Exemplo n.º 30
0
 def encrypt(data='', key='', mac_key='', iv=None, extra_data='', algorithm="AES", 
             mode="GCM", backend=BACKEND, iv_size=16, hash_algorithm="SHA256",
             return_mode="cryptogram"):
     """ Encrypts data with the specified key. Returns packed encrypted bytes.
         If an iv is not supplied a random one of iv_size will be generated.
         By default, the GCM mode of operation is used and the iv is 
         automatically included in the extra_data authenticated by the mode. 
         
         Note that not all algorithms may support all modes of operation
         with all backends. 
         
         A mac key is required when GCM mode is not in used. This function
         will refuse to encrypt data without authentication/integrity checks,
         as this is considered a serious flaw in security. 
         
         Technically speaking, 'iv' is not always the correct term for the
         parameter passed, depending on the mode of operation used. However,
         using two different fields for what are functionally the same would
         increase complexity needlessly. """
     assert data and key, "data" if not data else "key"
     if algorithm.lower() in hashlib.algorithms_guaranteed:
         return cryptographyless.encrypt(data, key, iv, extra_data, algorithm, mode,
                                         backend, iv_size, mac_key, hash_algorithm)
                                         
     header = algorithm + '_' + mode 
     if mode not in AEAD_MODES:
         if not mac_key:
             raise ValueError("Unable to authenticate data because no mac key was supplied for {} mode".format(header))        
         else:
             header += "_" + hash_algorithm
     else:
         header += "_" + "AEAD"
         
     if not iv and iv != 0: # 0 is a valid nonce for CTR mode.
         iv = random_bytes(iv_size)
         
     if mode != "ECB":
         mode_args = (iv, )
     else:
         mode_args = tuple()
     
     encryptor = Cipher(getattr(algorithms, algorithm)(key), 
                        getattr(modes, mode)(*mode_args), 
                        backend=BACKEND).encryptor()        
         
     if mode in AEAD_MODES:       
         encryptor.authenticate_additional_data(extra_data)            
     ciphertext = encryptor.update(data) + encryptor.finalize()          
                  
     if mode in AEAD_MODES:
         mac_tag = encryptor.tag
     else:
         mac_tag = generate_mac(mac_key, header + ciphertext + iv + extra_data, hash_algorithm) 
     
     if return_mode == "cryptogram":
         return save_data(header, ciphertext, iv, mac_tag, extra_data)
     else:
         assert return_mode == "values"
         return header, ciphertext, iv, mac_tag, extra_data
Exemplo n.º 31
0
def aes_key_wrap_with_padding(
    wrapping_key: bytes,
    key_to_wrap: bytes,
    backend: typing.Any = None,
) -> bytes:
    if len(wrapping_key) not in [16, 24, 32]:
        raise ValueError("The wrapping key must be a valid AES key length")

    aiv = b"\xA6\x59\x59\xA6" + struct.pack(">i", len(key_to_wrap))
    # pad the key to wrap if necessary
    pad = (8 - (len(key_to_wrap) % 8)) % 8
    key_to_wrap = key_to_wrap + b"\x00" * pad
    if len(key_to_wrap) == 8:
        # RFC 5649 - 4.1 - exactly 8 octets after padding
        encryptor = Cipher(AES(wrapping_key), ECB()).encryptor()
        b = encryptor.update(aiv + key_to_wrap)
        assert encryptor.finalize() == b""
        return b
    else:
        r = [key_to_wrap[i : i + 8] for i in range(0, len(key_to_wrap), 8)]
        return _wrap_core(wrapping_key, aiv, r)
Exemplo n.º 32
0
def list_command(args):
    print("received list command")
    #PEER_LIST['server']
    key = make_aes_key(PEER_LIST['server']['encryption_key'])
    print key
    print len(key)
    iv = os.urandom(12)
    encryptor = Cipher(algorithms.AES(key),
                       modes.GCM(iv),
                       backend=default_backend()).encryptor()
    encryption_prep = {'ask': args.user}
    cipherkt = encryptor.update(
        json.dumps(encryption_prep)) + encryptor.finalize()
    tagkey = encryptor.tag
    pickled_packet = pickle.dumps({
        'list_please': cipherkt,
        'IV': iv,
        'TAG': tagkey,
        'ask': args.user
    })
    PEER_SOCKETS['server'].send(base64.b64encode(pickled_packet))
Exemplo n.º 33
0
def solve_puzzle(args, pack):
    server_socket = PEER_SOCKETS['server']
    puz_num = pack['puzz']

    ans_puz = len(get_primes(puz_num))

    encryptor = Cipher(algorithms.AES(MASTER_KEY),
                       modes.GCM(MASTER_IV),
                       backend=default_backend()).encryptor()

    Na = random.randint(0, 65535)
    puzz_ans_packet = {'puzzle': ans_puz, 'Na': Na}
    packet_prep = json.dumps(puzz_ans_packet)

    cipherpuzzle = encryptor.update(packet_prep) + encryptor.finalize()
    tag = encryptor.tag

    aes_packet = {'solution': cipherpuzzle, 'iv': MASTER_IV, 'tag': tag}
    aes_packet_pickle = pickle.dumps(aes_packet).encode('base64', 'strict')

    server_socket.send(aes_packet_pickle)
Exemplo n.º 34
0
def decrypt_aes_gcm(key, initial_value, cipher_text, aad=None):
    """ Decrypt using AES-GCM
    Args:
        aes encryption key
        cipher text and tag
        initial value
        additional authenticated data
    Return:
        (true, plain text)
    """

    cipher = Cipher(algorithms.AES(key),
                    modes.GCM(initial_value, cipher_text[-16:]),
                    backend=default_backend()).decryptor()
    if aad:
        cipher.authenticate_additional_data(aad)
    try:
        plaintext = cipher.update(cipher_text[:-16]) + cipher.finalize()
        return plaintext
    except InvalidTag:
        print 'GCM decryption failed'
Exemplo n.º 35
0
def _unwrap_core(wrapping_key, a, r, backend):
    # Implement RFC 3394 Key Unwrap - 2.2.2 (index method)
    decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor()
    n = len(r)
    for j in reversed(range(6)):
        for i in reversed(range(n)):
            # pack/unpack are safe as these are always 64-bit chunks
            atr = (
                struct.pack(
                    ">Q", struct.unpack(">Q", a)[0] ^ ((n * j) + i + 1)
                )
                + r[i]
            )
            # every decryption operation is a discrete 16 byte chunk so
            # it is safe to reuse the decryptor for the entire operation
            b = decryptor.update(atr)
            a = b[:8]
            r[i] = b[-8:]

    assert decryptor.finalize() == b""
    return a, r
Exemplo n.º 36
0
Arquivo: Functs.py Projeto: diogo55/EC
def decifrar(msg, passphrase):
    ciphertext = msg['ciph']
    salt = msg['salt']
    tag = msg['tag']
    iv = msg['iv']
    key = passwd(passphrase, salt)

    #gerar mac utilizando a informação recebida e comparar
    if tag == mac(key, ciphertext):
        #desencriptar
        cipher = Cipher(algorithms.AES(key),
                        modes.CTR(iv),
                        backend=default_backend()).decryptor()
        plaintext = cipher.update(ciphertext) + cipher.finalize()
        print('Mensagem cifrada:', ciphertext)
        print('Mensagem decifrada:', plaintext)
    else:
        print('Tags diferentes')
        plaintext = b"erro"

    return plaintext
Exemplo n.º 37
0
def encrypt(key, plaintext, utf8_random, iv=None, associated_data=None):
    """Encrypt as done in Turtl: AES GCM with a prefix telling if it's
    UTF8 or binary,
    """
    # Generate a random 96-bit IV if needed
    if iv is None:
        iv = os.urandom(12)
    if isinstance(plaintext, str):
        utf8byte = chr(math.floor(utf8_random * (256 - 128)) + 128)
        plaintext = utf8byte.encode() + plaintext.encode()
    else:
        utf8byte = chr(math.floor(utf8_random * (256 - 128)))
        plaintext = utf8byte.encode() + plaintext
    encryptor = Cipher(
        algorithms.AES(key),
        modes.GCM(iv),
        backend=default_backend()
    ).encryptor()
    encryptor.authenticate_additional_data(associated_data)
    ciphertext = encryptor.update(plaintext) + encryptor.finalize()
    return (iv, ciphertext, encryptor.tag)
Exemplo n.º 38
0
def aes_decrypt(_key, iv, payload):
    """ Use AES128 GCM with the given key and iv to decrypt the payload. """
    if len(_key) >= 32:
        # XEP-0384
        log.debug('XEP Compliant Key/Tag')
        data = payload
        key = _key[:16]
        tag = _key[16:]
    else:
        # Legacy
        log.debug('Legacy Key/Tag')
        data = payload[:-16]
        key = _key
        tag = payload[-16:]
    if os.name == 'nt':
        _backend = backend
    else:
        _backend = default_backend()
    decryptor = Cipher(algorithms.AES(key), GCM(iv, tag=tag),
                       backend=_backend).decryptor()
    return decryptor.update(data) + decryptor.finalize()
Exemplo n.º 39
0
    def decrypt(self, ciphertext, ref_key, media_info):
        derived = HKDFv3().deriveSecrets(ref_key, media_info, 112)
        parts = ByteUtil.split(derived, 16, 32)
        iv = parts[0]
        key = parts[1]
        mac_key = derived[48:80]
        media_ciphertext = ciphertext[:-10]
        mac_value = ciphertext[-10:]

        mac = hmac.new(mac_key, digestmod=hashlib.sha256)
        mac.update(iv)
        mac.update(media_ciphertext)

        if mac_value != mac.digest()[:10]:
            raise ValueError("Invalid MAC")

        cipher_decryptor = Cipher(
            algorithms.AES(key), modes.CBC(iv), backend=default_backend()
        ).decryptor()

        return cipher_decryptor.update(media_ciphertext) + cipher_decryptor.finalize()
Exemplo n.º 40
0
    def decrypt_AES(self, key, iv, data_encrypted, modo, tag=None):
        if modo == "CBC":
            cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
            decryptor = cipher.decryptor()
            unpadder = padding.PKCS7(128).unpadder()

            data = decryptor.update(data_encrypted) + decryptor.finalize()
            info = unpadder.update(data) + unpadder.finalize()
            return info

        elif modo == "GCM":
            decryptor = Cipher(
                algorithms.AES(key),
                modes.GCM(iv, tag),
            ).decryptor()

            decryptor.authenticate_additional_data(b'associated_data')
            return decryptor.update(data_encrypted) + decryptor.finalize()
        else:
            print("Erro")
            sys.exit(0)
Exemplo n.º 41
0
def gcm_encrypt(plaintext, key, associated_data):
    # AES len(decode(key))*8 GCM
    # only 128, 192 or 256 bits long supported.

    try:
        key = decode(key)
    except Error:
        return False

    # 12 bytes IV is strongly suggested. do NOT change it.
    iv = os.urandom(12)

    encryptor = Cipher(algorithms.AES(key),
                       modes.GCM(iv),
                       backend=default_backend).encryptor()

    encryptor.authenticate_additional_data(associated_data.encode('utf-8'))

    return encode(
        encryptor.update(plaintext.encode('utf-8')) + encryptor.finalize(), iv,
        encryptor.tag)
Exemplo n.º 42
0
def _encrypt(pt, key, alg, iv=None):
    if iv is None:
        iv = b'\x00' * (alg.block_size // 8)

    if alg.is_insecure:
        raise PGPInsecureCipher(
            "{:s} is not secure. Do not use it for encryption!".format(
                alg.name))

    if not alg.is_supported:
        raise PGPEncryptionError("Cipher {:s} not supported".format(alg.name))

    try:
        encryptor = Cipher(alg.cipher(key), modes.CFB(iv),
                           default_backend()).encryptor()

    except UnsupportedAlgorithm as ex:  # pragma: no cover
        six.raise_from(PGPEncryptionError, ex)

    else:
        return bytearray(encryptor.update(pt) + encryptor.finalize())
Exemplo n.º 43
0
def receive_session_key(args, data):
    #print data
    print 'SESSION STUFF'
    server_socket = PEER_SOCKETS['server']
    tagkey = data['tag']
    kt_packet = data['acceptance']
    iv = data['IV']

    decryptor = Cipher(algorithms.AES(MASTER_KEY),
                       modes.GCM(iv, tagkey),
                       backend=default_backend()).decryptor()

    decrypted_packet = pickle.loads(
        base64.b64decode(decryptor.update(kt_packet) + decryptor.finalize()))
    #add nonce check
    PEER_LIST['server']['encryption_key'] = decrypted_packet['session_key']
    PEER_LIST[args.user]['TGT'] = decrypted_packet['TGT']

    print 'TGT and session key received'
    print PEER_LIST
    print 'Connected to remote server. You can start sending messages'
def encrypt(key, plaintext, associated_data):
    # Generate a random 96-bit IV.
    iv = os.urandom(12)

    # Construct an AES-GCM Cipher object with the given key and a
    # randomly generated IV.
    encryptor = Cipher(
        algorithms.AES(key),
        modes.GCM(iv),
        backend=default_backend()
    ).encryptor()

    # associated_data will be authenticated but not encrypted,
    # it must also be passed in on decryption.
    encryptor.authenticate_additional_data(associated_data)

    # Encrypt the plaintext and get the associated ciphertext.
    # GCM does not require padding.
    ciphertext = encryptor.update(plaintext) + encryptor.finalize()

    return (iv, ciphertext, encryptor.tag)
Exemplo n.º 45
0
def decrypt(master_keys, ciphertext_blob, encryption_context):
    """Decrypt a ciphertext blob using a master key material.

    NOTE: This is not necessarily what KMS does, but it retains the same properties.

    NOTE: This function is NOT compatible with KMS APIs.

    :param dict master_keys: Mapping of a KmsBackend's known master keys
    :param bytes ciphertext_blob: moto-structured ciphertext blob encrypted under a moto master key in master_keys
    :param dict[str, str] encryption_context: KMS-style encryption context
    :returns: plaintext bytes and moto key ID
    :rtype: bytes and str
    """
    try:
        ciphertext = _deserialize_ciphertext_blob(ciphertext_blob=ciphertext_blob)
    except Exception:
        raise InvalidCiphertextException()

    aad = _serialize_encryption_context(encryption_context=encryption_context)

    try:
        key = master_keys[ciphertext.key_id]
    except KeyError:
        raise AccessDeniedException(
            "The ciphertext refers to a customer master key that does not exist, "
            "does not exist in this region, or you are not allowed to access."
        )

    try:
        decryptor = Cipher(
            algorithms.AES(key.key_material),
            modes.GCM(ciphertext.iv, ciphertext.tag),
            backend=default_backend(),
        ).decryptor()
        decryptor.authenticate_additional_data(aad)
        plaintext = decryptor.update(ciphertext.ciphertext) + decryptor.finalize()
    except Exception:
        raise InvalidCiphertextException()

    return plaintext, ciphertext.key_id
Exemplo n.º 46
0
 def decriptografar(self):
     if self.__formulaHashOuCriptoEscolhida in self._Criptografia_para_escolher:
         cripto = self.__formulaHashOuCriptoEscolhida.split('_')
         algoritmo = getattr(algorithms, cripto[0])
         block_size = getattr(algoritmo, 'block_size', None)
         try:
             msgEnc = bytes.fromhex(self._txtEntradaDados.GetValue())
             chave = bytes.fromhex(self._txtChave.GetValue())
             iv = bytes.fromhex(self._txtIV.GetValue())
             if len(cripto) > 1:
                 modo = getattr(modes, cripto[1], None)
                 if cripto[1] == 'GCM':
                     tag = msgEnc[-16:]
                     msgEnc = msgEnc[0:-16]
                     modo = None if modo is None else modo(iv, tag)
                 else:
                     modo = None if modo is None else modo(iv)
             else:
                 modo = None
             if modo is not None:
                 decriptor = Cipher(algoritmo(chave),
                                    modo,
                                    backend=default_backend()).decryptor()
             else:
                 decriptor = Cipher(algoritmo(chave, iv),
                                    modo,
                                    backend=default_backend()).decryptor()
             mensagemDecriptada = decriptor.update(
                 msgEnc) + decriptor.finalize()
             if block_size is not None:
                 try:
                     unpadder = pad.PKCS7(block_size).unpadder()
                     mensagemDecriptada = unpadder.update(
                         mensagemDecriptada) + unpadder.finalize()
                 except:
                     pass
             self._txtSaidaDados.Clear()
             self._txtSaidaDados.WriteText(mensagemDecriptada.decode())
         except ValueError as error:
             self.error_dialog(error.args[0])
Exemplo n.º 47
0
def encrypt_into_file(infile, key=None, nonce=None, outfile=None):
    if isinstance(infile, bytes):
        infile = BytesIO(infile)
    elif isinstance(infile, str):
        infile = BytesIO(base64.b64decode(infile))
    if not outfile:
        outfile = tempfile.NamedTemporaryFile(
            suffix=".encrypt", dir=settings.FILE_UPLOAD_TEMP_DIR
        )
    nonce = os.urandom(13)
    if not key:
        key = os.urandom(32)
    encryptor = Cipher(algorithms.AES(key), modes.GCM(nonce)).encryptor()

    chunk = infile.read(512)
    while chunk:
        assert isinstance(chunk, bytes)
        outfile.write(encryptor.update(chunk))
        chunk = infile.read(512)
    outfile.write(encryptor.finalize())
    outfile.write(encryptor.tag)
    return outfile, nonce, key
Exemplo n.º 48
0
    def _decrypt_cryptography(cls, b_salt, b_ciphertext, b_password, key_length):

        bs = algorithms.AES.block_size // 8
        b_key, b_iv = cls._aes_derive_key_and_iv(b_password, b_salt, key_length, bs)
        cipher = C_Cipher(algorithms.AES(b_key), modes.CBC(b_iv), CRYPTOGRAPHY_BACKEND).decryptor()
        unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()

        try:
            b_plaintext_envelope = unpadder.update(
                cipher.update(b_ciphertext) + cipher.finalize()
            ) + unpadder.finalize()
        except ValueError:
            # In VaultAES, ValueError: invalid padding bytes can mean bad
            # password was given
            raise AnsibleError("Decryption failed")

        b_plaintext, b_this_sha, b_test_sha = cls._parse_plaintext_envelope(b_plaintext_envelope)

        if b_this_sha != b_test_sha:
            raise AnsibleError("Decryption failed")

        return b_plaintext
Exemplo n.º 49
0
def encrypt(key, iv, plaintext, associated_data):
    '''encrypt plaintext and mac with associated_data under key and iv

    uses AES-256-GCM
    '''
    # Construct an AES-GCM Cipher object with the given key and a
    # randomly generated parse_rescue_block.
    encryptor = Cipher(
        algorithms.AES(key),
        modes.GCM(iv),
        backend=default_backend()
    ).encryptor()

    # associated_data will be authenticated but not encrypted,
    # it must also be passed in on decryption.
    encryptor.authenticate_additional_data(associated_data)

    # Encrypt the plaintext and get the associated ciphertext.
    # GCM does not require padding.
    ciphertext = encryptor.update(plaintext) + encryptor.finalize()

    return (ciphertext, encryptor.tag)
Exemplo n.º 50
0
    def decrypt(self):
        """Decrypt a blob using LPS. Implements FALLBACK and DP methods to derive
        or obtain the encryption key from the one stored in the PSE/credential file and then uses
        that encryption key to decrypt the credential using the AES cipher.

        LPS-protected PSEs/credentials are verified with both a CRC32 checksum and an HMAC.
        Validation of the checksum and HMAC is not implemented.

        :return: decrypted object
        :rtype: string

        :raise NotImplemented: if the LPS method is not implemented
        :raise SAP_LPS_Decryption_Error: if there's an error decrypting the object
        """

        # Validate supported version
        if self.version != 2:
            log_lps.error("Version not supported")
            raise SAP_LPS_Decryption_Error("Version not supported")

        # TODO: Calculate and validate CRC32

        # Decrypt the encryption key using the LPS method
        if self.lps_type in lps_encryption_key_decryptor:
            encryption_key = lps_encryption_key_decryptor[self.lps_type](self)
        else:
            log_lps.error("Invalid LPS decryption method")
            raise SAP_LPS_Decryption_Error("Invalid LPS decryption method")

        # Decrypt the cipher text with the encryption key
        iv = "\x00" * 16
        decryptor = Cipher(algorithms.AES(encryption_key),
                           modes.CBC(iv),
                           backend=default_backend()).decryptor()
        plain = decryptor.update(self.encrypted_data) + decryptor.finalize()

        # TODO: Calculate and validate HMAC

        return plain
Exemplo n.º 51
0
    def wrap(self, key, keylen, cek):
        rk = self.get_key(key, 'encrypt')
        if not cek:
            cek = os.urandom(keylen)

        # Implement RFC 3394 Key Unwrap - 2.2.2
        # TODO: Use cryptography once issue #1733 is resolved
        iv = 'a6a6a6a6a6a6a6a6'
        A = unhexlify(iv)
        R = [cek[i:i+8] for i in range(0, len(cek), 8)]
        n = len(R)
        for j in range(0, 6):
            for i in range(0, n):
                e = Cipher(algorithms.AES(rk), modes.ECB(),
                           backend=self.backend).encryptor()
                B = e.update(A + R[i]) + e.finalize()
                A = _encode_int(_decode_int(B[:8]) ^ ((n*j)+i+1), 64)
                R[i] = B[-8:]
        ek = A
        for i in range(0, n):
            ek += R[i]
        return (cek, ek)
Exemplo n.º 52
0
    def decrypt(self,
                ciphertext,
                ciphertext_key,
                iv,
                tag,
                encryption_context={}):
        """Decrypt CIS payload using KMS encrypted key.

        :ciphertext: encrypted payload
        :ciphertext_key: encrypted KMS derived key
        :iv: AES initialization vector used to encrypt payload
        :tag: AES GCM authentication code
        """
        if self.plaintext_key is None:
            self.plaintext_key = self._decrypt_envelope_with_kms(
                ciphertext_key, encryption_context)

        decryptor = Cipher(algorithms.AES(self.plaintext_key),
                           modes.GCM(iv, tag),
                           backend=default_backend()).decryptor()

        return decryptor.update(ciphertext) + decryptor.finalize()
Exemplo n.º 53
0
 async def decrypt_file(key: bytes,
                        input_file_name: str,
                        output_file_name: str,
                        associated_data: bytes,
                        chunk_size: int = CHUNK_SIZE) -> None:
     async with aiofiles.open(input_file_name, 'rb') as fin, aiofiles.open(
             output_file_name, 'wb') as fout:
         _version, iv, tag = struct.unpack(
             '<Q12s16s', await fin.read(struct.calcsize('Q12s16s')))
         if _version != AESGCMEncrypt.VERSION:
             raise AESGCMEncrypt.VersionException(
                 f'Except {AESGCMEncrypt.VERSION} but {_version} found.')
         decryptor = Cipher(
             algorithms.AES(key),  # type: ignore
             modes.GCM(iv, tag),  # type: ignore
             backend=default_backend()).decryptor()
         decryptor.authenticate_additional_data(
             associated_data)  # type: ignore
         # reader = lib_aes_gcm.chunk_reader(fin, file_size)
         while chunk := await fin.read(chunk_size):
             await fout.write(decryptor.update(chunk))
         await fout.write(decryptor.finalize())
Exemplo n.º 54
0
    def decrypt(self, buf, ad=None):
        if len(buf) == 0:
            raise ValueError('buf should not be empty')

        ct, tag = buf[:self._tag_len * -1], buf[self._tag_len * -1:]

        if self._decryptor_skey is None:
            iv, ct = ct[:self._iv_len], ct[self._iv_len:]
            IV_CHECKER.check(self.__key, iv)
            self._decryptor_skey = self.key_expand(self.__key, iv,
                                                   hashlib.sha1)
            del self.__key

        nonce = struct.pack('<Q', self._decryptor_nonce) + b'\x00\x00\x00\x00'
        self._decryptor_nonce += 1
        decryptor = Cipher(self.algorithm(self._decryptor_skey),
                           modes.GCM(nonce, tag),
                           backend=default_backend()).decryptor()
        if ad:
            decryptor.authenticate_additional_data(ad)

        return decryptor.update(ct) + decryptor.finalize()
Exemplo n.º 55
0
class Decryptor(object):
    """Abstract decryption handler.

    :param algorithm: Algorithm used to encrypt this body
    :type algorithm: aws_encryption_sdk.identifiers.Algorithm
    :param bytes key: Raw source key
    :param bytes associated_data: Associated Data to send to decryption subsystem
    :param bytes iv: IV value with which to initialize decryption subsystem
    :param bytes tag: Tag with which to validate ciphertext
    """
    def __init__(self, algorithm, key, associated_data, iv, tag):
        """Prepares initial values."""
        self.source_key = key

        # Construct a decryptor object with the given key and a provided IV.
        # This is intentionally generic to leave an option for non-Cipher decryptor types in the future.
        self._decryptor = Cipher(algorithm.encryption_algorithm(key),
                                 algorithm.encryption_mode(iv, tag),
                                 backend=default_backend()).decryptor()

        # Put associated_data back in or the tag will fail to verify when the _decryptor is finalized.
        self._decryptor.authenticate_additional_data(associated_data)

    def update(self, ciphertext):
        """Updates _decryptor with provided ciphertext.

        :param bytes ciphertext: Ciphertext to decrypt
        :returns: Decrypted plaintext
        :rtype: bytes
        """
        return self._decryptor.update(ciphertext)

    def finalize(self):
        """Finalizes and closes _decryptor.

        :returns: Final decrypted plaintext
        :rtype: bytes
        """
        return self._decryptor.finalize()
Exemplo n.º 56
0
def aes_key_unwrap_with_padding(wrapping_key, wrapped_key, backend=None):
    backend = _get_backend(backend)
    if len(wrapped_key) < 16:
        raise InvalidUnwrap("Must be at least 16 bytes")

    if len(wrapping_key) not in [16, 24, 32]:
        raise ValueError("The wrapping key must be a valid AES key length")

    if len(wrapped_key) == 16:
        # RFC 5649 - 4.2 - exactly two 64-bit blocks
        decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor()
        b = decryptor.update(wrapped_key)
        assert decryptor.finalize() == b""
        a = b[:8]
        data = b[8:]
        n = 1
    else:
        r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)]
        encrypted_aiv = r.pop(0)
        n = len(r)
        a, r = _unwrap_core(wrapping_key, encrypted_aiv, r, backend)
        data = b"".join(r)

    # 1) Check that MSB(32,A) = A65959A6.
    # 2) Check that 8*(n-1) < LSB(32,A) <= 8*n.  If so, let
    #    MLI = LSB(32,A).
    # 3) Let b = (8*n)-MLI, and then check that the rightmost b octets of
    #    the output data are zero.
    (mli, ) = struct.unpack(">I", a[4:])
    b = (8 * n) - mli
    if (not bytes_eq(a[:4], b"\xa6\x59\x59\xa6")
            or not 8 * (n - 1) < mli <= 8 * n
            or (b != 0 and not bytes_eq(data[-b:], b"\x00" * b))):
        raise InvalidUnwrap()

    if b == 0:
        return data
    else:
        return data[:-b]
Exemplo n.º 57
0
    def decrypt(self,
                ciphertext,
                associated_data=b"authenticated but not encrypted payload"):
        # Construct a Cipher object, with the key, iv, and additionally the
        # GCM tag used for authenticating the message.

        iv, ciphertext = ciphertext[:self._block_size_bytes], ciphertext[
            self._block_size_bytes:]
        tag, ciphertext = ciphertext[:self._block_size_bytes], ciphertext[
            self._block_size_bytes:]

        decryptor = Cipher(algorithms.AES(self._key),
                           modes.GCM(iv, tag),
                           backend=default_backend()).decryptor()

        # We put associated_data back in or the tag will fail to verify
        # when we finalize the decryptor.
        decryptor.authenticate_additional_data(associated_data)

        # Decryption gets us the authenticated plaintext.
        # If the tag does not match an InvalidTag exception will be raised.
        return decryptor.update(ciphertext) + decryptor.finalize()
Exemplo n.º 58
0
    def decrypt(self, token, associated_data=b"", ttl=None):
        if not isinstance(token, bytes):
            raise TypeError("token must be bytes.")

        current_time = int(time.time())

        try:
            data = base64.urlsafe_b64decode(token)
        except (TypeError, binascii.Error):
            raise InvalidToken

        if not data or (six.indexbytes(data, 0) != 0x81):
            raise InvalidToken

        h = HMAC(self._signing_key, hashes.SHA256(), backend=self._backend)
        h.update(data[:-32] + associated_data)
        try:
            h.verify(data[-32:])
        except InvalidSignature:
            raise InvalidToken
        iv = data[1:17]
        ciphertext = data[17:-32]

        decryptor = Cipher(algorithms.AES(self._encryption_key), modes.CBC(iv),
                           self._backend).decryptor()

        plaintext_padded = decryptor.update(ciphertext)
        try:
            plaintext_padded += decryptor.finalize()
        except ValueError:
            raise InvalidToken
        unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()

        unpadded = unpadder.update(plaintext_padded)
        try:
            unpadded += unpadder.finalize()
        except ValueError:
            raise InvalidToken
        return unpadded
Exemplo n.º 59
0
def decrypt(data: bytes, privkey: datatypes.PrivateKey, shared_mac_data: bytes = b'') -> bytes:
    """Decrypt data with ECIES method using the given private key

    1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) )
    2) verify tag
    3) decrypt

    ecdhAgree(r, recipientPublic) == ecdhAgree(recipientPrivate, R)
    [where R = r*G, and recipientPublic = recipientPrivate*G]

    """
    if data[:1] != b'\x04':
        raise DecryptionError("wrong ecies header")

    #  1) generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) )
    shared = data[1:1 + PUBKEY_LEN]
    try:
        key_material = ecdh_agree(privkey, keys.PublicKey(shared))
    except _InvalidPublicKey as exc:
        raise DecryptionError(
            f"Failed to generate shared secret with pubkey {shared!r}: {exc}"
        ) from exc
    key = kdf(key_material)
    key_enc, key_mac = key[:KEY_LEN // 2], key[KEY_LEN // 2:]
    key_mac = sha256(key_mac).digest()
    tag = data[-KEY_LEN:]

    # 2) Verify tag
    expected_tag = hmac_sha256(key_mac, data[1 + PUBKEY_LEN:- KEY_LEN] + shared_mac_data)
    if not bytes_eq(expected_tag, tag):
        raise DecryptionError("Failed to verify tag")

    # 3) Decrypt
    algo = CIPHER(key_enc)
    blocksize = algo.block_size // 8
    iv = data[1 + PUBKEY_LEN:1 + PUBKEY_LEN + blocksize]
    ciphertext = data[1 + PUBKEY_LEN + blocksize:- KEY_LEN]
    ctx = Cipher(algo, MODE(iv), default_backend()).decryptor()
    return ctx.update(ciphertext) + ctx.finalize()
Exemplo n.º 60
0
def encrypt(plaintext, key):
    # AES len(decode(key))*8 CBC
    # only 128, 192 or 256 bits long supported.

    try:
        key = decode(key)
    except Error:
        return False

    # iv size = aes block size = 128 bits = 16 bytes
    iv = os.urandom(16)

    encryptor = Cipher(algorithms.AES(key),
                       modes.CBC(iv),
                       backend=default_backend).encryptor()

    plaintext = plaintext.encode('utf-8')

    if len(plaintext) % 16 != 0:
        plaintext += b' ' * (16 - len(plaintext) % 16)

    return encode(encryptor.update(plaintext) + encryptor.finalize(), iv)