
Encrypted-Content-Encoding for HTTP
An implementation of RFC 8188
in Go and JavaScript/TypeScript.
ECE for HTTP defines a way to use standard HTTP content encoding to exchange
AES-GCM encrypted payloads between a client and server.
While the RFC only mentions 128-bit encryption with AES-128-GCM, this
library provides support for AES-256-GCM as well when a key sufficiently
long (32 bytes) is provided.
JavaScript / TypeScript
npm i @mzattahri/ece
See js/README.md for full documentation.
Go
See also: TypeScript/JavaScript implementation
The library exposes 4 basic elements:
- A
Reader to decrypt;
- A
Writer to encrypt;
- An HTTP middleware to handle server-side encryption/decryption;
- An HTTP
Transport for client-side encryption/decryption.
Reader
Reader deciphers data from a reader (io.Reader) containing encrypted
data.
var key []byte
var cipher io.ReadCloser
r := ece.NewReader(key, cipher)
plain, err := io.ReadAll(r)
if err != nil {
log.Fatalf("error during decryption: %v", err)
}
defer r.Close()
fmt.Println(plain)
Writer
Writer writes encrypted data into another writer (io.Writer).
var key = []byte("16 or 32 bytes long key")
var dest io.Writer
var (
salt = ece.GenerateSalt(rand.Reader)
recordSize = 4096
keyID = "ID of the main key"
)
w, err := ece.NewWriter(key, salt, recordSize, keyID, dest)
if err != nil {
log.Fatalf("error initializing writer: %v", err)
}
defer w.Close()
if _, err := io.WriteString(w, "Hello, World!"); err != nil {
log.Fatalf("error writing cipher: %v", err)
}
log.Println("dest now contains encrypted data")
HTTP Handler
Handler is an HTTP middleware you can use to transparently
decrypt incoming requests and encrypt outgoing responses.
Incoming requests are decrypted if they come with a header Content-Encoding
set to either aes128gcm or aes256gcm. Similarly, responses are encrypted
if the request's Accept-Encoding or X-Accept-Encoding headers are set
to either value.
h := http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
},
)
var (
key = []byte("256-bit long key")
rs = 4096
)
http.ListenAndServe(":8000", ece.Handler(key, rs, h))
HTTP Transport
Transport is an http.RoundTripper that handles the encryption of
outgoing requests and the decryption of responses. Use it with any
http.Client.
Requests are systematically encrypted, while responses are only decrypted if
the Content-Encoding header is set to aes128gcm or aes256gcm.
var (
keyID = "ID of the key below"
key = []byte("16 or 32 byte long key")
payload = strings.NewReader(`{"key": "value"}`)
)
transport, err := ece.AES128GCM.NewTransport(key, keyID, 4096, nil)
if err != nil {
log.Fatalf("error initializing transport: %v", err)
}
client := &http.Client{Transport: transport}
resp, err := client.Post("https://api.example.com", "application/json", payload)
if err != nil {
log.Fatalf("HTTP request failed: %v", err)
}
data, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatalf("error reading response: %v", err)
}
log.Println(data)
Generating Keys
Use the GenerateKey method on the encoding to create a key of the correct size:
import "crypto/rand"
key256 := ece.AES256GCM.GenerateKey(rand.Reader)
key128 := ece.AES128GCM.GenerateKey(rand.Reader)
Contributions
Contributions are welcome via Pull Requests.