0.0.7 • Published 4 years ago

@snoculars/encrypt-workers-kv v0.0.7

Weekly downloads
28
License
MIT
Repository
github
Last release
4 years ago

🔑 Encrypt Cloudflare Workers KV

This library provides wrappers on the put and get functions from the Cloudflare Workers runtime API for writing to and reading from Workers KV, encrypting values before put and decrypting values after get. Encryption is implemented using the Web Crypto API to derive AES-GCM keys from a password based key (PBKDF2).

By default all data stored in Cloudflare Workers KV is encrypted at rest:

All values are encrypted at rest with 256-bit AES-GCM, and only decrypted by the process executing your Worker scripts or responding to your API requests. (docs)

However, there are a variety of reasons you may want to add your own encryption to the values stored in Workers KV. For example, permissions to access Workers KV are scoped at the account level. For those working in shared team or organizational accounts, this means you cannot limit access to specific KV namespaces, as anyone in that account with access to Workers can read the stored data in all KV namespaces in that account.

🔋 Installation

You have a few options to install this package!

Install with npm

npm i @snoculars/encrypt-workers-kv

Install with yarn

yarn add @snoculars/encrypt-workers-kv

⚙️ Usage

putEncryptedKV(namespace, key, data, password, options)

Wrapper on Workers KV put command that encrypts data prior to storage

ParamTypeDescription
namespaceKVNamespacethe binding to the namespace that script references
keystringthe key in the namespace used to reference the stored value
datastring or ArrayBufferthe data to encrypt and store in KV
passwordstringthe password to be used to encrypt the data
iterationsnumberoptional number of iterations used by the PBKDF2 to derive the key. Default 10000
optionsObjectoptional KV put fields (docs)

Returns encrypted value as string - Promise<ArrayBuffer>

Sample implementation:

let data = await request.text()
try {
  await putEncryptedKV(ENCRYPTED, 'data', data, password)
  return new Response('Secret stored successfully')
} catch (e) {
  return new Response(e.message, { status: e.status })
}

getDecryptedKV(namespace, key, password)

Wrapper on Workers KV get command that decrypts data after getting from storage

ParamTypeDescription
namespaceKVNamespacethe binding to the namespace that script references
keystringthe key in the namespace used to reference the stored value
passwordstringthe password used to encrypt the data

Returns decrypted value as string - Promise<ArrayBuffer>

Sample implementation:

try {
  let decryptedData = await getDecryptedKV(ENCRYPTED, 'data', password)
  let strDecryptedData = dec.decode(decryptedData)
  return new Response(`${strDecryptedData}`, {
    headers: { 'content-type': 'text/html; charset=utf-8' },
  })
} catch (e) {
  return new Response(e.message, { status: e.status })
}

Logic Flow

An explanation of the steps used behind the scenes for encryption and decryption in src/index.ts.

Encryption:

  1. Creates a password based key (PBKDF2) that will be used to derive the AES-GCM key used for encryption / decryption.
  2. Creates an AES-GCM key using the PBKDF2 key and a randomized salt value.
  3. Encrypts the input data using the AES-GCM key and a randomized initialization vector (iv).
  4. The values used for the password, salt, iv for encryption are needed for decryption. Therefore, creates an ArrayBuffer to be stored that includes the salt that was used when creating the password based key (PBKDF2), iv used for creating the AES key, and the encrypted content. The password should remain secret, so recommend storing it as a Worker Secret.

Decryption:

  1. Derives the salt, iv, and encrypted data from the ArrayBuffer.
  2. Creates a password based key (PBKDF2) that will be used to derive the AES-GCM key used for encryption / decryption. Password must be the same used for encryption and is obtained from the Workers Secret.
  3. Creates an AES-GCM key using the PBKDF2 key and the salt from the ArrayBuffer.
  4. Decrypts the input data using the AES-GCM key and the iv from the ArrayBuffer.

Build and Test

A test worker is used to test the library, located in test-worker/. Configure wrangler.toml in that folder with your account information. Then, create a new Workers KV namespace and add the configuration to wrangler.toml.

wrangler kv:namespace create "ENCRYPTED"

Add the password for PBKDF2 as a Workers Secret.

wrangler secret put PASSWORD

To deploy the test worker and run the the automated tests, change directory back to the project root directory and:

npm run test:deploy && npm run test

Sample Implementation

A sample implementation is available in the Workers Azure AD auth example, which uses encrypt-workers-kv to encrypt session token information stored as values in Workers KV.

References

Further info on Web Crypto usage:

0.0.7

4 years ago

0.0.6

4 years ago

0.0.5

4 years ago

0.0.4

4 years ago

0.0.3

4 years ago