// Code generated by smithy-go-codegen DO NOT EDIT.

package kms

import (
	"context"
	"fmt"
	awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
	"github.com/aws/aws-sdk-go-v2/service/kms/types"
	"github.com/aws/smithy-go/middleware"
	smithyhttp "github.com/aws/smithy-go/transport/http"
)

// Decrypts ciphertext that was encrypted by a KMS key using any of the following
// operations:
//
// # Encrypt
//
// # GenerateDataKey
//
// # GenerateDataKeyPair
//
// # GenerateDataKeyWithoutPlaintext
//
// # GenerateDataKeyPairWithoutPlaintext
//
// You can use this operation to decrypt ciphertext that was encrypted under a
// symmetric encryption KMS key or an asymmetric encryption KMS key. When the KMS
// key is asymmetric, you must specify the KMS key and the encryption algorithm
// that was used to encrypt the ciphertext. For information about asymmetric KMS
// keys, see [Asymmetric KMS keys]in the Key Management Service Developer Guide.
//
// The Decrypt operation also decrypts ciphertext that was encrypted outside of
// KMS by the public key in an KMS asymmetric KMS key. However, it cannot decrypt
// symmetric ciphertext produced by other libraries, such as the [Amazon Web Services Encryption SDK]or [Amazon S3 client-side encryption]. These
// libraries return a ciphertext format that is incompatible with KMS.
//
// If the ciphertext was encrypted under a symmetric encryption KMS key, the KeyId
// parameter is optional. KMS can get this information from metadata that it adds
// to the symmetric ciphertext blob. This feature adds durability to your
// implementation by ensuring that authorized users can decrypt ciphertext decades
// after it was encrypted, even if they've lost track of the key ID. However,
// specifying the KMS key is always recommended as a best practice. When you use
// the KeyId parameter to specify a KMS key, KMS only uses the KMS key you
// specify. If the ciphertext was encrypted under a different KMS key, the Decrypt
// operation fails. This practice ensures that you use the KMS key that you intend.
//
// Whenever possible, use key policies to give users permission to call the Decrypt
// operation on a particular KMS key, instead of using IAM policies. Otherwise, you
// might create an IAM policy that gives the user Decrypt permission on all KMS
// keys. This user could decrypt ciphertext that was encrypted by KMS keys in other
// accounts if the key policy for the cross-account KMS key permits it. If you must
// use an IAM policy for Decrypt permissions, limit the user to particular KMS
// keys or particular trusted accounts. For details, see [Best practices for IAM policies]in the Key Management
// Service Developer Guide.
//
// Decrypt also supports [Amazon Web Services Nitro Enclaves] and NitroTPM, which provide attested environments in
// Amazon EC2. To call Decrypt for a Nitro enclave or NitroTPM, use the [Amazon Web Services Nitro Enclaves SDK] or any
// Amazon Web Services SDK. Use the Recipient parameter to provide the attestation
// document for the attested environment. Instead of the plaintext data, the
// response includes the plaintext data encrypted with the public key from the
// attestation document ( CiphertextForRecipient ). For information about the
// interaction between KMS and Amazon Web Services Nitro Enclaves or Amazon Web
// Services NitroTPM, see [Cryptographic attestation support in KMS]in the Key Management Service Developer Guide.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see [Key states of KMS keys]in the Key Management Service Developer Guide.
//
// Cross-account use: Yes. To specify a KMS key in a different Amazon Web Services
// account, use the [key ARN]or [alias ARN]. A short [key ID] is also acceptable when decrypting symmetric
// ciphertexts, though using a full key ARN is recommended to be more explicit
// about the intended KMS key.
//
// Required permissions: [kms:Decrypt] (key policy)
//
// Related operations:
//
// # Encrypt
//
// # GenerateDataKey
//
// # GenerateDataKeyPair
//
// # ReEncrypt
//
// Eventual consistency: The KMS API follows an eventual consistency model. For
// more information, see [KMS eventual consistency].
//
// [Cryptographic attestation support in KMS]: https://docs.aws.amazon.com/kms/latest/developerguide/cryptographic-attestation.html
// [key ID]: https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-id
// [kms:Decrypt]: https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html
// [Asymmetric KMS keys]: https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html
// [Amazon Web Services Nitro Enclaves]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitro-enclave.html
// [Amazon S3 client-side encryption]: https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingClientSideEncryption.html
// [alias ARN]: https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-alias-ARN
// [KMS eventual consistency]: https://docs.aws.amazon.com/kms/latest/developerguide/accessing-kms.html#programming-eventual-consistency
// [Amazon Web Services Nitro Enclaves SDK]: https://docs.aws.amazon.com/enclaves/latest/user/developing-applications.html#sdk
// [Amazon Web Services Encryption SDK]: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/
// [key ARN]: https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN
// [Key states of KMS keys]: https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html
// [Best practices for IAM policies]: https://docs.aws.amazon.com/kms/latest/developerguide/iam-policies.html#iam-policies-best-practices
func (c *Client) Decrypt(ctx context.Context, params *DecryptInput, optFns ...func(*Options)) (*DecryptOutput, error) {
	if params == nil {
		params = &DecryptInput{}
	}

	result, metadata, err := c.invokeOperation(ctx, "Decrypt", params, optFns, c.addOperationDecryptMiddlewares)
	if err != nil {
		return nil, err
	}

	out := result.(*DecryptOutput)
	out.ResultMetadata = metadata
	return out, nil
}

type DecryptInput struct {

	// Ciphertext to be decrypted. The blob includes metadata.
	//
	// This parameter is required in all cases except when DryRun is true and
	// DryRunModifiers is set to IGNORE_CIPHERTEXT .
	CiphertextBlob []byte

	// Checks if your request will succeed. DryRun is an optional parameter.
	//
	// To learn more about how to use this parameter, see [Testing your permissions] in the Key Management
	// Service Developer Guide.
	//
	// [Testing your permissions]: https://docs.aws.amazon.com/kms/latest/developerguide/testing-permissions.html
	DryRun *bool

	// Specifies the modifiers to apply to the dry run operation. DryRunModifiers is
	// an optional parameter that only applies when DryRun is set to true .
	//
	// When set to IGNORE_CIPHERTEXT , KMS performs only authorization validation
	// without ciphertext validation. This allows you to test permissions without
	// requiring a valid ciphertext blob.
	//
	// To learn more about how to use this parameter, see [Testing your permissions] in the Key Management
	// Service Developer Guide.
	//
	// [Testing your permissions]: https://docs.aws.amazon.com/kms/latest/developerguide/testing-permissions.html
	DryRunModifiers []types.DryRunModifierType

	// Specifies the encryption algorithm that will be used to decrypt the ciphertext.
	// Specify the same algorithm that was used to encrypt the data. If you specify a
	// different algorithm, the Decrypt operation fails.
	//
	// This parameter is required only when the ciphertext was encrypted under an
	// asymmetric KMS key. The default value, SYMMETRIC_DEFAULT , represents the only
	// supported algorithm that is valid for symmetric encryption KMS keys.
	EncryptionAlgorithm types.EncryptionAlgorithmSpec

	// Specifies the encryption context to use when decrypting the data. An encryption
	// context is valid only for [cryptographic operations]with a symmetric encryption KMS key. The standard
	// asymmetric encryption algorithms and HMAC algorithms that KMS uses do not
	// support an encryption context.
	//
	// An encryption context is a collection of non-secret key-value pairs that
	// represent additional authenticated data. When you use an encryption context to
	// encrypt data, you must specify the same (an exact case-sensitive match)
	// encryption context to decrypt the data. An encryption context is supported only
	// on operations with symmetric encryption KMS keys. On operations with symmetric
	// encryption KMS keys, an encryption context is optional, but it is strongly
	// recommended.
	//
	// For more information, see [Encryption context] in the Key Management Service Developer Guide.
	//
	// [cryptographic operations]: https://docs.aws.amazon.com/kms/latest/developerguide/kms-cryptography.html#cryptographic-operations
	// [Encryption context]: https://docs.aws.amazon.com/kms/latest/developerguide/encrypt_context.html
	EncryptionContext map[string]string

	// A list of grant tokens.
	//
	// Use a grant token when your permission to call this operation comes from a new
	// grant that has not yet achieved eventual consistency. For more information, see [Grant token]
	// and [Using a grant token]in the Key Management Service Developer Guide.
	//
	// [Grant token]: https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token
	// [Using a grant token]: https://docs.aws.amazon.com/kms/latest/developerguide/using-grant-token.html
	GrantTokens []string

	// Specifies the KMS key that KMS uses to decrypt the ciphertext.
	//
	// Enter a key ID of the KMS key that was used to encrypt the ciphertext. If you
	// identify a different KMS key, the Decrypt operation throws an
	// IncorrectKeyException .
	//
	// This parameter is required only when the ciphertext was encrypted under an
	// asymmetric KMS key or when DryRun is true and DryRunModifiers is set to
	// IGNORE_CIPHERTEXT . If you used a symmetric encryption KMS key, KMS can get the
	// KMS key from metadata that it adds to the symmetric ciphertext blob. However, it
	// is always recommended as a best practice. This practice ensures that you use the
	// KMS key that you intend.
	//
	// To specify a KMS key, use its key ID, key ARN, alias name, or alias ARN. When
	// using an alias name, prefix it with "alias/" . To specify a KMS key in a
	// different Amazon Web Services account, you should use the key ARN or alias ARN.
	//
	// For example:
	//
	//   - Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
	//
	//   - Key ARN:
	//   arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
	//
	//   - Alias name: alias/ExampleAlias
	//
	//   - Alias ARN: arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias
	//
	// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey. To get the alias name
	// and alias ARN, use ListAliases.
	KeyId *string

	// A signed [attestation document] from an Amazon Web Services Nitro enclave or NitroTPM, and the
	// encryption algorithm to use with the public key in the attestation document. The
	// only valid encryption algorithm is RSAES_OAEP_SHA_256 .
	//
	// This parameter supports the [Amazon Web Services Nitro Enclaves SDK] or any Amazon Web Services SDK for Amazon Web
	// Services Nitro Enclaves. It supports any Amazon Web Services SDK for Amazon Web
	// Services NitroTPM.
	//
	// When you use this parameter, instead of returning the plaintext data, KMS
	// encrypts the plaintext data with the public key in the attestation document, and
	// returns the resulting ciphertext in the CiphertextForRecipient field in the
	// response. This ciphertext can be decrypted only with the private key in the
	// attested environment. The Plaintext field in the response is null or empty.
	//
	// For information about the interaction between KMS and Amazon Web Services Nitro
	// Enclaves or Amazon Web Services NitroTPM, see [Cryptographic attestation support in KMS]in the Key Management Service
	// Developer Guide.
	//
	// [Cryptographic attestation support in KMS]: https://docs.aws.amazon.com/kms/latest/developerguide/cryptographic-attestation.html
	// [attestation document]: https://docs.aws.amazon.com/enclaves/latest/user/nitro-enclave-concepts.html#term-attestdoc
	// [Amazon Web Services Nitro Enclaves SDK]: https://docs.aws.amazon.com/enclaves/latest/user/developing-applications.html#sdk
	Recipient *types.RecipientInfo

	noSmithyDocumentSerde
}

type DecryptOutput struct {

	// The plaintext data encrypted with the public key from the attestation document.
	// This ciphertext can be decrypted only by using a private key from the attested
	// environment.
	//
	// This field is included in the response only when the Recipient parameter in the
	// request includes a valid attestation document from an Amazon Web Services Nitro
	// enclave or NitroTPM. For information about the interaction between KMS and
	// Amazon Web Services Nitro Enclaves or Amazon Web Services NitroTPM, see [Cryptographic attestation support in KMS]in the
	// Key Management Service Developer Guide.
	//
	// [Cryptographic attestation support in KMS]: https://docs.aws.amazon.com/kms/latest/developerguide/cryptographic-attestation.html
	CiphertextForRecipient []byte

	// The encryption algorithm that was used to decrypt the ciphertext.
	EncryptionAlgorithm types.EncryptionAlgorithmSpec

	// The Amazon Resource Name ([key ARN] ) of the KMS key that was used to decrypt the
	// ciphertext.
	//
	// [key ARN]: https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN
	KeyId *string

	// The identifier of the key material used to decrypt the ciphertext. This field
	// is present only when the operation uses a symmetric encryption KMS key. This
	// field is omitted if the request includes the Recipient parameter.
	KeyMaterialId *string

	// Decrypted plaintext data. When you use the HTTP API or the Amazon Web Services
	// CLI, the value is Base64-encoded. Otherwise, it is not Base64-encoded.
	//
	// If the response includes the CiphertextForRecipient field, the Plaintext field
	// is null or empty.
	Plaintext []byte

	// Metadata pertaining to the operation's result.
	ResultMetadata middleware.Metadata

	noSmithyDocumentSerde
}

func (c *Client) addOperationDecryptMiddlewares(stack *middleware.Stack, options Options) (err error) {
	if err := stack.Serialize.Add(&setOperationInputMiddleware{}, middleware.After); err != nil {
		return err
	}
	err = stack.Serialize.Add(&awsAwsjson11_serializeOpDecrypt{}, middleware.After)
	if err != nil {
		return err
	}
	err = stack.Deserialize.Add(&awsAwsjson11_deserializeOpDecrypt{}, middleware.After)
	if err != nil {
		return err
	}
	if err := addProtocolFinalizerMiddlewares(stack, options, "Decrypt"); err != nil {
		return fmt.Errorf("add protocol finalizers: %v", err)
	}

	if err = addlegacyEndpointContextSetter(stack, options); err != nil {
		return err
	}
	if err = addSetLoggerMiddleware(stack, options); err != nil {
		return err
	}
	if err = addClientRequestID(stack); err != nil {
		return err
	}
	if err = addComputeContentLength(stack); err != nil {
		return err
	}
	if err = addResolveEndpointMiddleware(stack, options); err != nil {
		return err
	}
	if err = addComputePayloadSHA256(stack); err != nil {
		return err
	}
	if err = addRetry(stack, options, c); err != nil {
		return err
	}
	if err = addRawResponseToMetadata(stack); err != nil {
		return err
	}
	if err = addRecordResponseTiming(stack); err != nil {
		return err
	}
	if err = addSpanRetryLoop(stack, options); err != nil {
		return err
	}
	if err = addClientUserAgent(stack, options); err != nil {
		return err
	}
	if err = smithyhttp.AddErrorCloseResponseBodyMiddleware(stack); err != nil {
		return err
	}
	if err = smithyhttp.AddCloseResponseBodyMiddleware(stack); err != nil {
		return err
	}
	if err = addSetLegacyContextSigningOptionsMiddleware(stack); err != nil {
		return err
	}
	if err = addUserAgentRetryMode(stack, options); err != nil {
		return err
	}
	if err = addCredentialSource(stack, options); err != nil {
		return err
	}
	if err = stack.Initialize.Add(newServiceMetadataMiddleware_opDecrypt(options.Region), middleware.Before); err != nil {
		return err
	}
	if err = addRecursionDetection(stack); err != nil {
		return err
	}
	if err = addRequestIDRetrieverMiddleware(stack); err != nil {
		return err
	}
	if err = addResponseErrorMiddleware(stack); err != nil {
		return err
	}
	if err = addRequestResponseLogging(stack, options); err != nil {
		return err
	}
	if err = addDisableHTTPSMiddleware(stack, options); err != nil {
		return err
	}
	if err = addInterceptBeforeRetryLoop(stack, options); err != nil {
		return err
	}
	if err = addInterceptAttempt(stack, options); err != nil {
		return err
	}
	if err = addInterceptors(stack, options); err != nil {
		return err
	}
	return nil
}

func newServiceMetadataMiddleware_opDecrypt(region string) *awsmiddleware.RegisterServiceMetadata {
	return &awsmiddleware.RegisterServiceMetadata{
		Region:        region,
		ServiceID:     ServiceID,
		OperationName: "Decrypt",
	}
}
