def encrypt(raw, key, hmac_key=None, key_is_hash=False, b64=True, bits=256):
    """
    Encrypt bytes with AES-CBC

    Args:
        raw: bytes to encrypt
        key: encryption key
        hmac_key: HMAC key (optional), True or custom key
        key_is_hash: consider encryption key is sha256 hash
        b64: encode result in base64 (default: True)
        bits: key size (128, 192 or 256, default is 256)
    Returns:
        encrypted block + 32-byte HMAC signature (if hmac_key is specified)

    note: if hmac_key is True and key is hash, sha512 sum is required
    """
    from Crypto.Cipher import AES
    from Crypto import Random
    import hashlib
    import hmac
    if isinstance(raw, str):
        raw = raw.encode()
    if hmac_key is True:
        h = key if key_is_hash else hashlib.sha512(key.encode() if
            isinstance(key, str) else key).digest()
        keyhash = h[:bits // 8]
        hmac_key = h[:-32]
    else:
        keyhash = key if key_is_hash else hashlib.sha256(key.encode() if
            isinstance(key, str) else key).digest()[:bits // 8]
    length = 16 - len(raw) % 16
    raw += bytes([length]) * length
    iv = Random.new().read(AES.block_size)
    cipher = AES.new(keyhash, AES.MODE_CBC, iv)
    val = iv + cipher.encrypt(raw)
    if hmac_key:
        val += hmac.new(hmac_key.encode() if isinstance(hmac_key, str) else
            hmac_key, val, hashlib.sha256).digest()
    if b64:
        import base64
        return base64.b64encode(val).decode()
    else:
        return val
