class Kalium implements Encryptor {

    @Override
    public byte[] open(
            final byte[] cipherText, final Nonce nonce, final PublicKey publicKey, final PrivateKey privateKey) {
        LOGGER.info("Opening message using public key {}", publicKey);
        LOGGER.debug(
                "Opening message using nonce {}, public key {} and private key {}",
                nonce,
                publicKey,
                privateKey);

        /*
         * NaCL C API states that first crypto_secretbox_BOXZEROBYTES must be zero
         * but these are not part of the ciphertext, and must be added in
         */
        final byte[] paddedInput = pad(cipherText, CRYPTO_BOX_CURVE25519XSALSA20POLY1305_BOXZEROBYTES);
        final byte[] paddedOutput = new byte[paddedInput.length];

        final int sodiumResult =
                sodium.crypto_box_curve25519xsalsa20poly1305_open(
                        paddedOutput,
                        paddedInput,
                        paddedInput.length,
                        nonce.getNonceBytes(),
                        publicKey.getKeyBytes(),
                        privateKey.getKeyBytes());

        if (sodiumResult == -1) {
            LOGGER.error(
                    "Could not open sealed payload using public key {} and private key {}", publicKey, privateKey);
            throw new EncryptorException("Kalium could not open the payload using the provided keys directly");
        }

        LOGGER.info("Opened sealed payload for public key {}", publicKey);
        LOGGER.debug(
                "Opened payload using nonce {}, public key {} and private key {}",
                nonce,
                publicKey,
                privateKey);

        return extract(paddedOutput, CRYPTO_BOX_CURVE25519XSALSA20POLY1305_ZEROBYTES);
    }

    public  Kalium(final NaCl.Sodium sodium);

}