class Kalium implements Encryptor {

    @Override
    public byte[] seal(
            final byte[] message, final Nonce nonce, final PublicKey publicKey, final PrivateKey privateKey) {
        /*
         * The Kalium library uses the C API
         * which expects the first CRYPTO_BOX_CURVE25519XSALSA20POLY1305_ZEROBYTES bytes to be zero
         */
        final byte[] paddedMessage = pad(message, CRYPTO_BOX_CURVE25519XSALSA20POLY1305_ZEROBYTES);
        final byte[] output = new byte[paddedMessage.length];

        LOGGER.info("Sealing message using public key {}", publicKey);
        LOGGER.debug(
                "Sealing message using nonce {}, public key {} and private key {}",
                nonce,
                publicKey,
                privateKey);

        final int sodiumResult =
                sodium.crypto_box_curve25519xsalsa20poly1305(
                        output,
                        paddedMessage,
                        paddedMessage.length,
                        nonce.getNonceBytes(),
                        publicKey.getKeyBytes(),
                        privateKey.getKeyBytes());

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

        LOGGER.info("Created sealed payload for public key {}", publicKey);
        LOGGER.debug(
                "Created sealed payload 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 message, and must be stripped out
         */
        return extract(output, CRYPTO_BOX_CURVE25519XSALSA20POLY1305_BOXZEROBYTES);
    }

    public  Kalium(final NaCl.Sodium sodium);

}