Exemple #1
0
 def basic_encrypt(cls, key, plaintext):
     assert len(plaintext) % 8 == 0
     algo = ciphers.TripleDES(key.contents)
     cbc = modes.CBC(bytes(8))
     encryptor = Cipher(algo, cbc, default_backend()).encryptor()
     ciphertext = encryptor.update(plaintext)
     return ciphertext
Exemple #2
0
 def basic_decrypt(cls, key, ciphertext):
     assert len(ciphertext) % 8 == 0
     algo = ciphers.TripleDES(key.contents)
     cbc = modes.CBC(bytes(8))
     decryptor = Cipher(algo, cbc, default_backend()).decryptor()
     plaintext = decryptor.update(ciphertext)
     return plaintext
Exemple #3
0
def aes_cbc_dec(aesKey, bsEncMsg, bsMacMsg):
    '''
    AuthenticatedEncryption - Check mac then decrypt given encrypted message.
    '''
    ### Prepare for mac
    sha256 = SHA256()
    hmac = HMAC(aesKey, sha256, default_backend())
    ### do mac
    hmac.update(bsEncMsg)
    macMsg = hmac.finalize()
    if (macMsg != bsMacMsg):
        raise Exception("ERRR:AEDecrypt:Mismatch, skipping")
        return None
    ### Prepare for decryption
    blockLen = 16
    iv = os.urandom(blockLen)
    aes = AES(aesKey)
    cbc = CBC(iv)
    aesCbc = Cipher(aes, cbc, default_backend())
    aesCbcDec = aesCbc.decryptor()
    ### do decrypt
    decMsg = aesCbcDec.update(bsEncMsg)
    decFina = aesCbcDec.finalize()
    decMsg = decMsg + decFina
    # do pkcs7 depadding
    unpad = PKCS7(blockLen * 8).unpadder()
    decMsg = unpad.update(decMsg)
    decMsg += unpad.finalize()
    # Discard the initial random block, as corresponding enc and this dec uses
    # non communicated random iv and inturn discardable random 0th block
    decMsg = decMsg[blockLen:]
    return decMsg
 def test_nonexistent_aead_cipher(self):
     from cryptography.hazmat.backends.commoncrypto.backend import Backend
     b = Backend()
     cipher = Cipher(
         DummyCipher(), GCM(b"fake_iv_here"), backend=b,
     )
     with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER):
         cipher.encryptor()
 def test_nonexistent_aead_cipher(self):
     from cryptography.hazmat.backends.commoncrypto.backend import Backend
     b = Backend()
     cipher = Cipher(
         DummyCipher(), GCM(b"fake_iv_here"), backend=b,
     )
     with pytest.raises(UnsupportedAlgorithm):
         cipher.encryptor()
Exemple #6
0
 def test_nonexistent_aead_cipher(self):
     from cryptography.hazmat.backends.commoncrypto.backend import Backend
     b = Backend()
     cipher = Cipher(
         DummyCipher(), GCM(b"fake_iv_here"), backend=b,
     )
     with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER):
         cipher.encryptor()
Exemple #7
0
 def test_nonexistent_aead_cipher(self):
     from cryptography.hazmat.backends.commoncrypto.backend import Backend
     b = Backend()
     cipher = Cipher(
         DummyCipher(),
         GCM(b"fake_iv_here"),
         backend=b,
     )
     with pytest.raises(UnsupportedAlgorithm):
         cipher.encryptor()
Exemple #8
0
def aes_cbc_enc(aesKey, sPlainMsg):
    '''
    AuthenticatedEncryption - Do a encrypt then mac operation on given message.

        a random iv is generated but not transmitted, instead a random block is
        prepended to the message and encrypted. Inturn the same can be discarded
        during decrypting. Each CBC block depends on the previous encrypted block
        so the 0th block acts as a inplace iv at one level.

        Encryption uses AES in CBC mode with PKCS7 padding where required.
        MAC uses HMAC with SHA256

            As encryption and mac using independent algorithms so the key is
            shared wrt encryption and mac operations.

        With aes length of key passed is independent of the block size used, and
        user can use any valid aes key size.

        This is similar to the age old encrypt as well as sign messages to ensure
        confidentiality as well as authenticity. But then instead of using asymm
        logic for signing, use a hash with hidden key based logic. Also make sure
        that one checks the authenticity before trying to use it or work on it, so
        that new oracles arent opened up, beyond the minimal unavoidable oracle.
    '''
    ### Prepare for encryption
    blockLen = 16
    iv = os.urandom(blockLen)
    aes = AES(aesKey)
    cbc = CBC(iv)
    aesCbc = Cipher(aes, cbc, default_backend())
    aesCbcEnc = aesCbc.encryptor()
    random0thBlock = os.urandom(blockLen)
    # This allows iv to be discarded
    # so also while decrypting discard the 0th block
    plainMsg = random0thBlock + sPlainMsg.encode('utf-8')
    # do PKCS7 padding
    if bInternalPadder:
        padLen = blockLen - (len(plainMsg) % blockLen)
        for i in range(padLen):
            plainMsg += int.to_bytes(padLen, 1, 'little')
    else:
        pad = PKCS7(blockLen * 8).padder()
        plainMsg = pad.update(plainMsg)
        plainMsg += pad.finalize()
    ### do encrypt
    encMsg = aesCbcEnc.update(plainMsg)
    encFina = aesCbcEnc.finalize()
    encMsg = encMsg + encFina
    ### Prepare for mac
    sha256 = SHA256()
    hmac = HMAC(aesKey, sha256, default_backend())
    ### do mac
    hmac.update(encMsg)
    macMsg = hmac.finalize()
    return encMsg, macMsg
Exemple #9
0
    def encrypt(cls, key, keyusage, plaintext, confounder):
        if confounder is None:
            confounder = get_random_bytes(8)
        ki = HMAC_HASH(key.contents, cls.usage_str(keyusage), hashes.MD5)
        cksum = HMAC_HASH(ki, confounder + plaintext, hashes.MD5)
        ke = HMAC_HASH(ki, cksum, hashes.MD5)

        encryptor = Cipher(
            ciphers.ARC4(ke), None, default_backend()).encryptor()
        ctext = encryptor.update(confounder + plaintext)

        return cksum + ctext
Exemple #10
0
def decrypt(ciphertext, key, iv):
    """
    Decrypt ciphertext
    """
    assert len(key) == len(iv) == 32

    cipher = Cipher(
        algorithms.AES(key), modes.CBC(iv[:16]), CRYPTO_BACKEND).decryptor()
    del key
    plaintext_padded = cipher.update(ciphertext) + cipher.finalize()

    unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
    plaintext = unpadder.update(plaintext_padded) + unpadder.finalize()

    return plaintext
Exemple #11
0
    def basic_decrypt(cls, key, ciphertext):
        assert len(ciphertext) >= 16

        algo = ciphers.AES(key.contents)
        cbc = modes.CBC(bytes(16))
        aes_ctx = Cipher(algo, cbc, default_backend())

        def aes_decrypt(ciphertext):
            decryptor = aes_ctx.decryptor()
            plaintext = decryptor.update(ciphertext)
            return plaintext

        if len(ciphertext) == 16:
            return aes_decrypt(ciphertext)
        # Split the ciphertext into blocks.  The last block may be partial.
        cblocks = [ciphertext[p:p + 16] for p in range(0, len(ciphertext), 16)]
        lastlen = len(cblocks[-1])
        # CBC-decrypt all but the last two blocks.
        prev_cblock = bytes(16)
        plaintext = b''
        for b in cblocks[:-2]:
            plaintext += _xorbytes(aes_decrypt(b), prev_cblock)
            prev_cblock = b
        # Decrypt the second-to-last cipher block.  The left side of
        # the decrypted block will be the final block of plaintext
        # xor'd with the final partial cipher block; the right side
        # will be the omitted bytes of ciphertext from the final
        # block.
        b = aes_decrypt(cblocks[-2])
        lastplaintext = _xorbytes(b[:lastlen], cblocks[-1])
        omitted = b[lastlen:]
        # Decrypt the final cipher block plus the omitted bytes to get
        # the second-to-last plaintext block.
        plaintext += _xorbytes(aes_decrypt(cblocks[-1] + omitted), prev_cblock)
        return plaintext + lastplaintext
Exemple #12
0
def encrypt(plaintext, key, iv):
    """
    Encrypt plaintext
    """
    assert len(key) == len(iv) == 32

    cipher = Cipher(
        algorithms.AES(key), modes.CBC(iv[:16]), CRYPTO_BACKEND).encryptor()
    del key

    padder = padding.PKCS7(algorithms.AES.block_size).padder()
    padded_data = padder.update(plaintext) + padder.finalize()

    ciphertext = cipher.update(padded_data) + cipher.finalize()

    assert ciphertext
    return ciphertext
Exemple #13
0
    def decrypt(cls, key, keyusage, ciphertext):
        if len(ciphertext) < 24:
            raise ValueError('ciphertext too short')
        cksum, basic_ctext = ciphertext[:16], ciphertext[16:]
        ki = HMAC_HASH(key.contents, cls.usage_str(keyusage), hashes.MD5)
        ke = HMAC_HASH(ki, cksum, hashes.MD5)

        decryptor = Cipher(
            ciphers.ARC4(ke), None, default_backend()).decryptor()
        basic_plaintext = decryptor.update(basic_ctext)

        exp_cksum = HMAC_HASH(ki, basic_plaintext, hashes.MD5)
        ok = _mac_equal(cksum, exp_cksum)
        if not ok and keyusage == 9:
            # Try again with usage 8, due to RFC 4757 errata.
            ki = HMAC_HASH(key.contents, pack('<i', 8), hashes.MD5)
            exp_cksum = HMAC_HASH(ki, basic_plaintext, hashes.MD5)
            ok = _mac_equal(cksum, exp_cksum)
        if not ok:
            raise InvalidChecksum('ciphertext integrity failure')
        # Discard the confounder.
        return basic_plaintext[8:]
Exemple #14
0
    def basic_encrypt(cls, key, plaintext):
        assert len(plaintext) >= 16

        algo = ciphers.AES(key.contents)
        cbc = modes.CBC(bytes(16))
        aes_ctx = Cipher(algo, cbc, default_backend())

        def aes_encrypt(plaintext):
            encryptor = aes_ctx.encryptor()
            ciphertext = encryptor.update(plaintext)
            return ciphertext

        ctext = aes_encrypt(_zeropad(plaintext, 16))
        if len(plaintext) > 16:
            # Swap the last two ciphertext blocks and truncate the
            # final block to match the plaintext length.
            lastlen = len(plaintext) % 16 or 16
            ctext = ctext[:-32] + ctext[-16:] + ctext[-32:-16][:lastlen]
        return ctext
def test_gmac2():
    encryption_key = bytes.fromhex("000102030405060708090A0B0C0D0E0F")
    authentication_key = bytes.fromhex("D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF")
    security_control = SecurityControlField(
        security_suite=0, authenticated=True, encrypted=False
    )
    client_invocation_counter = int.from_bytes(bytes.fromhex("00000001"), "big")
    client_system_title = bytes.fromhex("4D4D4D0000000001")
    # server_system_title = bytes.fromhex("4D4D4D0000BC614E")
    # server_invocation_counter = int.from_bytes(bytes.fromhex("01234567"), "big")
    # client_to_server_challenge = bytes.fromhex("4B35366956616759")
    server_to_client_challenge = bytes.fromhex("503677524A323146")

    iv = client_system_title + client_invocation_counter.to_bytes(4, "big")

    assert iv == bytes.fromhex("4D4D4D000000000100000001")

    # Construct an AES-GCM Cipher object with the given key and iv
    encryptor = Cipher(
        algorithms.AES(encryption_key),
        modes.GCM(initialization_vector=iv, tag=None, min_tag_length=12),
    ).encryptor()

    # associated_data will be authenticated but not encrypted,
    # it must also be passed in on decryption.
    associated_data = (
        security_control.to_bytes() + authentication_key + server_to_client_challenge
    )

    assert associated_data == bytes.fromhex(
        "10D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF503677524A323146"
    )
    encryptor.authenticate_additional_data(associated_data)

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

    # dlms uses a tag lenght of 12 not the default of 16. Since we have set the minimum
    # tag length to 12 it is ok to truncated the tag.
    tag = encryptor.tag[:12]

    assert ciphertext == b""
    result = ciphertext + tag

    assert result == bytes.fromhex("1A52FE7DD3E72748973C1E28")
 def aes_decrypt(data, iv, key):
     cipher = Cipher(AES(key), CBC(iv), default_backend())
     decryptor = cipher.decryptor()
     plain_text = decryptor.update(data) + decryptor.finalize()
     padding = plain_text[len(plain_text) - 1]
     return plain_text[:len(plain_text) - padding]