# KMS

## Data Encryption & Decryption with KMS

KMS can directly encrypt/decrypt data but only up to 4096 bytes. Anything over this size limit requires leveraging a Data Encryption Key (DEK). Reference the [official docs](https://docs.aws.amazon.com/kms/latest/developerguide/overview.html) for more as there are other use cases and types of keys.&#x20;

### Encrypting Data

When leveraging the AWS CLI (AWS SDK under the hood), the data is sent to the KMS service, and a KMS key is used to encrypt the data. The data is sent to the service because the KMS key cannot leave.

{% code overflow="wrap" %}

```bash
# encrypting plaintext data directly
aws kms encrypt --key-id <keyId> --plaintext <plaintextData>

# encrypting a file containing plaintext
aws kms encrypt --key-id <keyId> --plaintext fileb://<plaintextFile>
```

{% endcode %}

### Decrypting Data

Again, the data is sent to the KMS service to be decrypted.&#x20;

{% code overflow="wrap" %}

```bash
# decrypting ciphertext data directly
aws kms decrypt --key-id <kms-key-id> --ciphertext <ciphertextData>

# decrypting a file containing encrypted data
aws kms decrypt --key-id <kms-key-id> --ciphertext-blob fileb://<encryptedFile> --output text --query Plaintext | base64 --decode > <outputFileName>
```

{% endcode %}

## Data Encryption & Decryption with KMS Data Encryption Key (DEK)

Data encryption keys can be generated when you need to encrypt / decrypt data larger than 4096 bytes. These keys are generated from a KMS key and the plaintext version performs the encryption. After the plaintext key encrypts the data, it should be deleted, and the encrypted version of the key stored alongside the encrypted data. The encrypted key contains metadata which describes the KMS key required to decrypt itself.&#x20;

When generating a data encryption key using the AWS CLI (or AWS SDK) you must remember to delete the plaintext key otherwise an attacker can access your data. The AWS Encryption SDK can perform this task for you.&#x20;

### Generating a DEK

{% code overflow="wrap" %}

```bash
aws kms generate-data-key --key-id <kms-key-id> --key-spec AES_256                                                        
{
    "CiphertextBlob": "AQIDAHjBdOEYbwSwF+14[snip]",
    "Plaintext": "AzSMaOZqgt[snip]",
    "KeyId": "arn:aws:kms:us-east-1:<aws-account-id>:key/<kms-key-id>"
}
```

{% endcode %}

Store the `CiphertextBlob` and `Plaintext` like so.

{% code overflow="wrap" %}

```bash
echo "AQIDAHj..." | base64 --decode > encrypted_key
echo "AzSMaOZqgt..." | base64 --decode > plaintext_key
```

{% endcode %}

### Encrypting Data with DEK

Since the AWS CLI cannot utilize data encryption keys, you must use another solution such as `openssl`.&#x20;

{% code overflow="wrap" %}

```bash
openssl enc -in <fileToEncrypt> -out <newEncryptedFileName> -e -aes256 -k fileb://plaintext_key 
```

{% endcode %}

Now, the `plaintext_key` should be deleted and the `encrypted_key` stored alongside the encrypted data.&#x20;

### Decrypting Data with DEK

Now, use the KMS key to decrypt the the `encrypted_key` and store the plaintext key in a file, `plaintext_key` .&#x20;

{% code overflow="wrap" %}

```bash
aws kms decrypt --ciphertext-blob fileb://encrypted_key --key-id <kms-key-id> --query Plaintext --out text | base64 --decode > plaintext_key
```

{% endcode %}

Again, leverage `openssl` or similar to decrypt the data.&#x20;

{% code overflow="wrap" %}

```bash
openssl enc -in encrypted_large_file.txt -out decrypted_large_file.txt -d -aes256 -k fileb://plaintext_key
```

{% endcode %}

## AWS Encryption SDK

The [AWS Encryption SDK](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/programming-languages.html) can be leveraged as a CLI tool or in code such as Python, Java, JavaScript, .NET, and C. Utilizing this SDK will handle KMS and DEKs for you, simplifying the process compared to the previous examples of generating DEKs and using 3rd party solutions like `openssl`.&#x20;

### Encrypting Data with Encryption SDK (CLI)

{% code overflow="wrap" %}

```bash
aws-encryption-cli --encrypt --input plaintext_sdk_example.txt --output encrypted_sdk_example.txt --wrapping-keys key=<kms-key-id> --commitment-policy require-encrypt-require-decrypt --metadata-output metadata
```

{% endcode %}

A metadata file is generated which details the encryption process such as the KMS key used, algorithm, and more.

{% code overflow="wrap" %}

```bash
cat metadata

    {"header": {"algorithm": "AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384", "commitment_key": "YVeJwji5Cx1NYBizsDfi3u6Z7yydR3DSvtVBmb985BE=", "content_type": 2, "encrypted_data_keys": [{"encrypted_data_key":[snip]
```

{% endcode %}

### Decrypting Data with Encryption SDK (CLI)

{% code overflow="wrap" %}

```bash
aws-encryption-cli --decrypt --input encrypted_sdk_example.txt --output decrypted_sdk_example.txt --wrapping-keys key=<kms-key-arn> --metadata-output metadata_d --max-encrypted-data-keys 1 --buffer --commitment-policy require-encrypt-require-decrypt
```

{% endcode %}

***

## Offensive Security Tactics & Techniques <a href="#offensive-security-tactics-and-techniques" id="offensive-security-tactics-and-techniques"></a>

### Privilege Escalation

{% embed url="<https://www.techwithtyler.dev/cloud-security/aws/aws-offensive-security/aws-privilege-escalation/rds>" %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.techwithtyler.dev/cloud-security/aws/aws/security/kms.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
