class Kalium implements Encryptor {

    @Override
    public byte[] openAfterPrecomputation(final byte[] encryptedPayload, final Nonce nonce, final SharedKey sharedKey) {
        LOGGER.info("Opening message using shared key {}", sharedKey);
        LOGGER.debug(
                "Opening message using nonce {} and shared key {}",
                nonce,
                sharedKey);

        /*
         * 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(encryptedPayload, CRYPTO_BOX_CURVE25519XSALSA20POLY1305_BOXZEROBYTES);
        final byte[] paddedOutput = new byte[paddedInput.length];

        final int sodiumResult =
                this.sodium.crypto_box_curve25519xsalsa20poly1305_open_afternm(
                        paddedOutput, paddedInput, paddedInput.length, nonce.getNonceBytes(), sharedKey.getKeyBytes());

        if (sodiumResult == -1) {
            LOGGER.error("Could not open sealed payload using shared key {}", sharedKey);
            throw new EncryptorException("Kalium could not open the payload using the shared key");
        }

        LOGGER.info("Opened sealed payload for shared key {}", sharedKey);
        LOGGER.debug(
                "Opened payload using nonce {} and sharedKey {}",
                nonce,
                sharedKey);

        return extract(paddedOutput, CRYPTO_BOX_CURVE25519XSALSA20POLY1305_ZEROBYTES);
    }

    public  Kalium(final NaCl.Sodium sodium);

}