Corbie

Plugins

crypto

This plugin hashes, signs, encrypts and encodes data, and makes random bytes.

crypto.hash(data, { algorithm, as })the hash crypto.hmac(data, { key, algorithm, as })the HMAC crypto.random(n, { as })n random bytes, 1048576 at most crypto.uuid()a random UUID, as text crypto.sign(data, { key, algorithm, as })the signature crypto.verify(data, { key, signature, algorithm })true if the signature is of the data, false if not crypto.encrypt(data, { key, as })the data, encrypted crypto.decrypt(data, { key, as })the data that was encrypted crypto.encode(data, { as })the data as text crypto.decode(text, { from, as })the bytes that the text encodes

data is text, bytes or a blob of at most 64 MiB. For crypto.decrypt it is bytes or a blob.

Options:

algorithm"sha256", "sha512", "sha1" or "md5"; default "sha256" from"base64", "base64url" or "hex"; default "base64" signaturebytes; crypto.decode turns a signature in text into bytes

as is the form of the result.

hash, hmac, random"hex", "base64", "base64url" or "bytes"; default "hex" sign, encryptthe same four; default "bytes" encode"base64", "base64url" or "hex"; default "base64" decrypt, decode"bytes", "text" or "json"; default "bytes"

key is text, bytes or a handle to a secret (secrets).

hmacany text or bytes signa private key in PEM: PRIVATE KEY, RSA PRIVATE KEY or EC PRIVATE KEY verifya public key in PEM: PUBLIC KEY encrypt, decrypt16, 24 or 32 bytes, such as the 32 characters that openssl rand -hex 16 prints
  • A key that signs or verifies is RSA, EC or Ed25519, with no passphrase.
  • algorithm is the hash that is signed, the same to sign and to verify. An Ed25519 key signs the data itself and takes none.
  • An RSA signature is PKCS #1 v1.5, and an EC signature is DER.
  • crypto.verify returns false for a signature of other data, with no error.
  • crypto.encrypt uses AES in Galois counter mode.
  • Its result is 12 random bytes, the encrypted data and a tag of 16 bytes, so the same data never encrypts to the same bytes twice.
  • crypto.decrypt with another key, or after a byte has changed, is an error.
  • A call whose key is a handle returns ordinary data, which the script can send anywhere, so the secret's entry must be secret:NAME@*.
  • data is never a handle.

Errors:

  bad_input   an unknown algorithm or form, a key of the wrong kind or size, a signature that is
              not bytes, text that is not in the encoding, or data that does not decrypt

Needs secret:NAME@* for a secret used as a key, and nothing otherwise.

These calls hash, encode, decode and make random values.

crypto.hash("hello", { algorithm: "md5" })         // gives "5d41402abc4b2a76b9719d911017c592"
crypto.encode("hi")                                // gives "aGk="
crypto.decode("aGk=", { as: "text" })              // gives "hi"
crypto.random(16).length                           // gives 32
crypto.uuid().length                               // gives 36

This script signs with a secret private key and verifies with the public key.

allow: ["secret:RELEASE_KEY@*"]

const release = "corbie 1.4, as built"
const signature = crypto.sign(release, { key: secrets.get("RELEASE_KEY") })
crypto.encode(signature, { as: "hex" }).slice(0, 16)       // gives "e9bea10d9a6f5ab3"

const theirs = `-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAiRjIS/cn74dGizRuH5M9NgFrAsVHGRKz+313ziVPp6A=
-----END PUBLIC KEY-----`
crypto.verify(release, { key: theirs, signature })         // gives true
crypto.verify("corbie 1.5", { key: theirs, signature })    // gives false

This script encrypts and decrypts with a secret key.

allow: ["secret:VAULT_KEY@*"]

const key = secrets.get("VAULT_KEY")
const sealed = crypto.encrypt("the note", { key })
sealed.length                                      // gives 36
crypto.decrypt(sealed, { key, as: "text" })        // gives "the note"

This script computes an HMAC with a secret key.

allow: ["secret:SIGNING@*"]

const signed = crypto.hmac("the body", { key: secrets.get("SIGNING") })
signed.length                                      // gives 64