private String decryptAndVerify(final Serializable value, final Key encryptionKey, final Key signingKey) {
        Objects.requireNonNull(value, () -> """
            Value to verify/decrypt cannot be null. This is likely because keys used to sign and encrypt the value do not match.
            """.stripIndent().trim());
        var encodedObj = value.toString();
        if (isEncryptionPossible(encryptionKey)) {
            LOGGER.trace("Attempting to decrypt value based on encryption key defined by [{}]", getEncryptionKeySetting());
            encodedObj = EncodingUtils.decryptJwtValue(encryptionKey, encodedObj);
        }
        val currentValue = encodedObj.getBytes(StandardCharsets.UTF_8);
        val encoded = FunctionUtils.doIf(this.signingEnabled, () -> {
            LOGGER.trace("Attempting to verify signature based on signing key defined by [{}]", getSigningKeySetting());
            return verifySignature(currentValue, signingKey);
        }, () -> currentValue).get();
        return new String(encoded, StandardCharsets.UTF_8);
    }
The {@link BaseStringCipherExecutor} is the default
implementation of {@link CipherExecutor}. It provides
a facade API to encrypt, sign, and verify values.

@author Misagh Moayyed
@since 4.1
core/cas-server-core-util-api/src/main/java/org/apereo/cas/util/cipher/BaseStringCipherExecutor.java