def encrypt_message(secret, topic, message):
    """Encrypt message."""

    keylen = SecretBox.KEY_SIZE

    if isinstance(secret, dict):
        key = secret.get(topic)
    else:
        key = secret

    if key is None:
        _LOGGER.warning(
            "Unable to encrypt payload because no decryption key known "
            "for topic %s",
            topic,
        )
        return None

    key = key.encode("utf-8")
    key = key[:keylen]
    key = key.ljust(keylen, b"\0")

    try:
        message = message.encode("utf-8")
        payload = SecretBox(key).encrypt(message, encoder=Base64Encoder)
        _LOGGER.debug("Encrypted message: %s to %s", message, payload)
        return payload.decode("utf-8")
    except ValueError:
        _LOGGER.warning("Unable to encrypt message for topic %s", topic)
        return None
Exemple #2
0
async def test_registration_encryption(hass, hass_client):
    """Test that registrations happen."""
    try:
        from nacl.encoding import Base64Encoder
        from nacl.secret import SecretBox
    except (ImportError, OSError):
        pytest.skip("libnacl/libsodium is not installed")
        return

    await async_setup_component(hass, DOMAIN, {DOMAIN: {}})

    api_client = await hass_client()

    resp = await api_client.post("/api/mobile_app/registrations",
                                 json=REGISTER)

    assert resp.status == 201
    register_json = await resp.json()

    keylen = SecretBox.KEY_SIZE
    key = register_json[CONF_SECRET].encode("utf-8")
    key = key[:keylen]
    key = key.ljust(keylen, b"\0")

    payload = json.dumps(RENDER_TEMPLATE["data"]).encode("utf-8")

    data = SecretBox(key).encrypt(payload,
                                  encoder=Base64Encoder).decode("utf-8")

    container = {
        "type": "render_template",
        "encrypted": True,
        "encrypted_data": data
    }

    resp = await api_client.post("/api/webhook/{}".format(
        register_json[CONF_WEBHOOK_ID]),
                                 json=container)

    assert resp.status == 200

    webhook_json = await resp.json()
    assert "encrypted_data" in webhook_json

    decrypted_data = SecretBox(key).decrypt(webhook_json["encrypted_data"],
                                            encoder=Base64Encoder)
    decrypted_data = decrypted_data.decode("utf-8")

    assert json.loads(decrypted_data) == {"one": "Hello world"}
Exemple #3
0
def decrypt_payload(secret_key, encrypted_data):
    """Return a decrypted payload given a key and a string of encrypted data."""
    try:
        from nacl.encoding import Base64Encoder
        from nacl.secret import SecretBox
    except (ImportError, OSError):
        pytest.skip("libnacl/libsodium is not installed")
        return

    import json

    prepped_key = unhexlify(secret_key)

    decrypted_data = SecretBox(prepped_key).decrypt(encrypted_data,
                                                    encoder=Base64Encoder)
    decrypted_data = decrypted_data.decode("utf-8")

    return json.loads(decrypted_data)
Exemple #4
0
async def test_webhook_handle_decryption(
        webhook_client,  # noqa: F811
        create_registrations):  # noqa: F401, F811, E501
    """Test that we can encrypt/decrypt properly."""
    try:
        # pylint: disable=unused-import
        from nacl.secret import SecretBox  # noqa: F401
        from nacl.encoding import Base64Encoder  # noqa: F401
    except (ImportError, OSError):
        pytest.skip("libnacl/libsodium is not installed")
        return

    import json

    keylen = SecretBox.KEY_SIZE
    key = create_registrations[0]['secret'].encode("utf-8")
    key = key[:keylen]
    key = key.ljust(keylen, b'\0')

    payload = json.dumps(RENDER_TEMPLATE['data']).encode("utf-8")

    data = SecretBox(key).encrypt(payload,
                                  encoder=Base64Encoder).decode("utf-8")

    container = {
        'type': 'render_template',
        'encrypted': True,
        'encrypted_data': data,
    }

    resp = await webhook_client.post('/api/webhook/{}'.format(
        create_registrations[0]['webhook_id']),
                                     json=container)

    assert resp.status == 200

    webhook_json = await resp.json()
    assert 'encrypted_data' in webhook_json

    decrypted_data = SecretBox(key).decrypt(webhook_json['encrypted_data'],
                                            encoder=Base64Encoder)
    decrypted_data = decrypted_data.decode("utf-8")

    assert json.loads(decrypted_data) == {'one': 'Hello world'}
async def test_webhook_handle_decryption(webhook_client,  # noqa: F811
                                         create_registrations):  # noqa: F401, F811, E501
    """Test that we can encrypt/decrypt properly."""
    try:
        # pylint: disable=unused-import
        from nacl.secret import SecretBox  # noqa: F401
        from nacl.encoding import Base64Encoder  # noqa: F401
    except (ImportError, OSError):
        pytest.skip("libnacl/libsodium is not installed")
        return

    import json

    keylen = SecretBox.KEY_SIZE
    key = create_registrations[0]['secret'].encode("utf-8")
    key = key[:keylen]
    key = key.ljust(keylen, b'\0')

    payload = json.dumps(RENDER_TEMPLATE['data']).encode("utf-8")

    data = SecretBox(key).encrypt(payload,
                                  encoder=Base64Encoder).decode("utf-8")

    container = {
        'type': 'render_template',
        'encrypted': True,
        'encrypted_data': data,
    }

    resp = await webhook_client.post(
        '/api/webhook/{}'.format(create_registrations[0]['webhook_id']),
        json=container
    )

    assert resp.status == 200

    webhook_json = await resp.json()
    assert 'encrypted_data' in webhook_json

    decrypted_data = SecretBox(key).decrypt(webhook_json['encrypted_data'],
                                            encoder=Base64Encoder)
    decrypted_data = decrypted_data.decode("utf-8")

    assert json.loads(decrypted_data) == {'one': 'Hello world'}
async def test_webhook_handle_decryption(webhook_client, create_registrations):
    """Test that we can encrypt/decrypt properly."""
    try:
        # pylint: disable=unused-import
        from nacl.secret import SecretBox  # noqa: F401
        from nacl.encoding import Base64Encoder  # noqa: F401
    except (ImportError, OSError):
        pytest.skip("libnacl/libsodium is not installed")
        return

    import json

    keylen = SecretBox.KEY_SIZE
    key = create_registrations[0]["secret"].encode("utf-8")
    key = key[:keylen]
    key = key.ljust(keylen, b"\0")

    payload = json.dumps(RENDER_TEMPLATE["data"]).encode("utf-8")

    data = SecretBox(key).encrypt(payload,
                                  encoder=Base64Encoder).decode("utf-8")

    container = {
        "type": "render_template",
        "encrypted": True,
        "encrypted_data": data
    }

    resp = await webhook_client.post("/api/webhook/{}".format(
        create_registrations[0]["webhook_id"]),
                                     json=container)

    assert resp.status == 200

    webhook_json = await resp.json()
    assert "encrypted_data" in webhook_json

    decrypted_data = SecretBox(key).decrypt(webhook_json["encrypted_data"],
                                            encoder=Base64Encoder)
    decrypted_data = decrypted_data.decode("utf-8")

    assert json.loads(decrypted_data) == {"one": "Hello world"}
Exemple #7
0
def decrypt_payload_legacy(secret_key, encrypted_data):
    """Return a decrypted payload given a key and a string of encrypted data."""
    try:
        from nacl.encoding import Base64Encoder
        from nacl.secret import SecretBox
    except (ImportError, OSError):
        pytest.skip("libnacl/libsodium is not installed")
        return

    import json

    keylen = SecretBox.KEY_SIZE
    prepped_key = secret_key.encode("utf-8")
    prepped_key = prepped_key[:keylen]
    prepped_key = prepped_key.ljust(keylen, b"\0")

    decrypted_data = SecretBox(prepped_key).decrypt(encrypted_data,
                                                    encoder=Base64Encoder)
    decrypted_data = decrypted_data.decode("utf-8")

    return json.loads(decrypted_data)
Exemple #8
0
async def test_registration(hass, hass_client):
    """Test that registrations happen."""
    try:
        # pylint: disable=unused-import
        from nacl.secret import SecretBox  # noqa: F401
        from nacl.encoding import Base64Encoder  # noqa: F401
    except (ImportError, OSError):
        pytest.skip("libnacl/libsodium is not installed")
        return

    import json

    await async_setup_component(hass, DOMAIN, {DOMAIN: {}})

    api_client = await hass_client()

    resp = await api_client.post(
        '/api/mobile_app/registrations', json=REGISTER
    )

    assert resp.status == 201
    register_json = await resp.json()
    assert CONF_WEBHOOK_ID in register_json
    assert CONF_SECRET in register_json

    entries = hass.config_entries.async_entries(DOMAIN)

    assert entries[0].data['app_data'] == REGISTER['app_data']
    assert entries[0].data['app_id'] == REGISTER['app_id']
    assert entries[0].data['app_name'] == REGISTER['app_name']
    assert entries[0].data['app_version'] == REGISTER['app_version']
    assert entries[0].data['device_name'] == REGISTER['device_name']
    assert entries[0].data['manufacturer'] == REGISTER['manufacturer']
    assert entries[0].data['model'] == REGISTER['model']
    assert entries[0].data['os_name'] == REGISTER['os_name']
    assert entries[0].data['os_version'] == REGISTER['os_version']
    assert entries[0].data['supports_encryption'] == \
        REGISTER['supports_encryption']

    keylen = SecretBox.KEY_SIZE
    key = register_json[CONF_SECRET].encode("utf-8")
    key = key[:keylen]
    key = key.ljust(keylen, b'\0')

    payload = json.dumps(RENDER_TEMPLATE['data']).encode("utf-8")

    data = SecretBox(key).encrypt(payload,
                                  encoder=Base64Encoder).decode("utf-8")

    container = {
        'type': 'render_template',
        'encrypted': True,
        'encrypted_data': data,
    }

    resp = await api_client.post(
        '/api/webhook/{}'.format(register_json[CONF_WEBHOOK_ID]),
        json=container
    )

    assert resp.status == 200

    webhook_json = await resp.json()
    assert 'encrypted_data' in webhook_json

    decrypted_data = SecretBox(key).decrypt(webhook_json['encrypted_data'],
                                            encoder=Base64Encoder)
    decrypted_data = decrypted_data.decode("utf-8")

    assert json.loads(decrypted_data) == {'one': 'Hello world'}
async def test_registration(hass, hass_client):  # noqa: F811
    """Test that registrations happen."""
    try:
        # pylint: disable=unused-import
        from nacl.secret import SecretBox  # noqa: F401
        from nacl.encoding import Base64Encoder  # noqa: F401
    except (ImportError, OSError):
        pytest.skip("libnacl/libsodium is not installed")
        return

    import json

    await async_setup_component(hass, DOMAIN, {DOMAIN: {}})

    api_client = await hass_client()

    resp = await api_client.post(
        '/api/mobile_app/registrations', json=REGISTER
    )

    assert resp.status == 201
    register_json = await resp.json()
    assert CONF_WEBHOOK_ID in register_json
    assert CONF_SECRET in register_json

    entries = hass.config_entries.async_entries(DOMAIN)

    assert entries[0].data['app_data'] == REGISTER['app_data']
    assert entries[0].data['app_id'] == REGISTER['app_id']
    assert entries[0].data['app_name'] == REGISTER['app_name']
    assert entries[0].data['app_version'] == REGISTER['app_version']
    assert entries[0].data['device_name'] == REGISTER['device_name']
    assert entries[0].data['manufacturer'] == REGISTER['manufacturer']
    assert entries[0].data['model'] == REGISTER['model']
    assert entries[0].data['os_name'] == REGISTER['os_name']
    assert entries[0].data['os_version'] == REGISTER['os_version']
    assert entries[0].data['supports_encryption'] == \
        REGISTER['supports_encryption']

    keylen = SecretBox.KEY_SIZE
    key = register_json[CONF_SECRET].encode("utf-8")
    key = key[:keylen]
    key = key.ljust(keylen, b'\0')

    payload = json.dumps(RENDER_TEMPLATE['data']).encode("utf-8")

    data = SecretBox(key).encrypt(payload,
                                  encoder=Base64Encoder).decode("utf-8")

    container = {
        'type': 'render_template',
        'encrypted': True,
        'encrypted_data': data,
    }

    resp = await api_client.post(
        '/api/webhook/{}'.format(register_json[CONF_WEBHOOK_ID]),
        json=container
    )

    assert resp.status == 200

    webhook_json = await resp.json()
    assert 'encrypted_data' in webhook_json

    decrypted_data = SecretBox(key).decrypt(webhook_json['encrypted_data'],
                                            encoder=Base64Encoder)
    decrypted_data = decrypted_data.decode("utf-8")

    assert json.loads(decrypted_data) == {'one': 'Hello world'}