AdvancedEncrypting Requests

Encrypting Requests

Use HTTP content-coding in a message header to encrypt the body of an HTTPS request, following the IETF Encrypted Content-Encoding draft.

In the course of developing server-to-server solutions, it may be necessary to encrypt the contents of an HTTPS request. Although requests are encrypted via HTTPS when they are in flight, you can also encrypt them in storage. Doing so creates a kind of safebox for the request and its payload, ensuring that you alone can access it at a subsequent time.

For example, you may want to store a log file on a server without exposing its contents to that server. That same encrypted log file can be replicated on other servers, making it more resistant to server or network failure, or it could be downloaded by clients, making it available offline. In all cases, the contents of the file are not exposed.

This document provides a basic understanding of how to use HTTP content-coding in a message header to encrypt the body (message payload) of an HTTP request. It reflects the methodology detailed in the Internet-Draft Encrypted Content-Encoding for HTTP, which is a working document of the Internet Engineering Task Force (IETF).

Sample Request

Review the sample request in this section to understand how to code the request header. The most important parameters used to encrypt the body of the request include:

  • keyid - Identifies the keying material that is used. When the Crypto-Key header field is used, the keyid identifies a matching value in that field. The keyid parameter MUST be used if keying material included in an Crypto-Key header field is needed to derive the content encryption key. The keyid parameter can also be used to identify keys in an application-specific fashion.
  • salt - Contains base64url-encoded octets that are used as salt in deriving a unique content encryption key. The salt parameter must be present, and must be exactly 16 octets long when decoded. In addition, the salt parameter must not be reused for two different payload bodies that have the same input keying material; generating a random salt for every application of the content encoding ensures that content encryption key reuse is highly unlikely. Consider the following sample request:

Sample Request

POST /quotes HTTP/1.1
Content-Encoding: aes-256-cfb
Encryption: keyid="key1"; salt="Zlx7Drxdhji39P4IIrin0Q"
Crypto-Key: keyid="key1"; aes-256-cfb="TV0tg787F8xGAcXJ0hhdu6430QAdloY7khG2lllWFTI"

pP3dbF//eBI3V9y1vs50EGNL1qH3g9UwfUcxwEs/mg4qDOwkdKA3c9q/dehJj6jclhd7

The actual decrypted body of the request is "You can't win a game if you don't score any points."

Note: The body of this request is base64 encoded, and the body of the Crypto-Key header is for testing purposes only.

Encryption Procedure

To encrypt a request:

  1. Produce a unique key to encrypt the request. For example:

    shared_secure_key = urlsafe_base64_decode "TV0tg787F8xGAcXJ0hhdu6430QAdloY7khG2lllWFT"
    salt = urlsafe_base64_decode "Zlx7Drxdhji39P4IIrin0Q"
    pseudo_random_key = sha256_hmac(salt, shared_secure_key)
    
  2. You can add a context for an additional security measure such as a shared salt which would protect the request data further.

  3. With the generated key, encode the body of the request. For example:

    content_encoding_key = sha256_hmac(pseudo_random_key, "Content-Encoding: aes-256-cfb" + 0x00 + context + 0x01)
    
  4. Set the initialization vector. For example:

    nonce = sha256_hmac(pseudo_random_key, "Content-Encoding: nonce" + 0x00 + context + 0x01).slice(0, 16)
    

    Note: The nonce for each record is a 16 octet (128 bit) value produced from the record sequence number and a value derived from the input keying material.

  5. Now encrypt the request body using the key, iv and payload parameters. For example:

    encrypted_body = aes_256_cfb_encrypt(content_encoding_key, nonce, "You can't win a game if you don't score any points.")
    
  6. The request body can also be decrypted via the key, iv and payload parameters. For example:

    decoded_body = aes_256_cfb_decrypt(content_encoding_key, nonce, base64_decode("pP3dbF//eBI3V9y1vs50EGNL1qH3g9UwfUcxwEs/mg4qDOwkdKA3c9q/dehJj6jclhd7"))
    

For more information on encrypting requests, please consult your Customer Success contact.