@Override
  public ListenableFuture<byte[]> unwrapKeyAsync(final byte[] encryptedKey, final String algorithm)
      throws NoSuchAlgorithmException {

    if (encryptedKey == null) {
      throw new IllegalArgumentException("encryptedKey ");
    }

    // Interpret the requested algorithm
    if (Strings.isNullOrWhiteSpace(algorithm)) {
      throw new IllegalArgumentException("algorithm");
    }

    // Interpret the requested algorithm
    Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithm);

    if (baseAlgorithm == null || !(baseAlgorithm instanceof AsymmetricEncryptionAlgorithm)) {
      throw new NoSuchAlgorithmException(algorithm);
    }

    AsymmetricEncryptionAlgorithm algo = (AsymmetricEncryptionAlgorithm) baseAlgorithm;

    ICryptoTransform transform;
    ListenableFuture<byte[]> result;

    try {
      transform = algo.CreateDecryptor(_keyPair, _provider);
      result = Futures.immediateFuture(transform.doFinal(encryptedKey));
    } catch (Exception e) {
      result = Futures.immediateFailedFuture(e);
    }

    return result;
  }
  @Override
  public ListenableFuture<Triple<byte[], byte[], String>> encryptAsync(
      final byte[] plaintext,
      final byte[] iv,
      final byte[] authenticationData,
      final String algorithm)
      throws NoSuchAlgorithmException {

    if (plaintext == null) {
      throw new IllegalArgumentException("plaintext");
    }

    // Interpret the requested algorithm
    String algorithmName =
        (Strings.isNullOrWhiteSpace(algorithm) ? getDefaultEncryptionAlgorithm() : algorithm);
    Algorithm baseAlgorithm = AlgorithmResolver.Default.get(algorithmName);

    if (baseAlgorithm == null || !(baseAlgorithm instanceof AsymmetricEncryptionAlgorithm)) {
      throw new NoSuchAlgorithmException(algorithmName);
    }

    AsymmetricEncryptionAlgorithm algo = (AsymmetricEncryptionAlgorithm) baseAlgorithm;

    ICryptoTransform transform;
    ListenableFuture<Triple<byte[], byte[], String>> result;

    try {
      transform = algo.CreateEncryptor(_keyPair, _provider);
      result =
          Futures.immediateFuture(
              Triple.of(transform.doFinal(plaintext), (byte[]) null, algorithmName));
    } catch (Exception e) {
      result = Futures.immediateFailedFuture(e);
    }

    return result;
  }