Importing and exporting

Importing & exporting

unjwt functions accept keys in many shapes — JWK, CryptoKey, Uint8Array, password strings. Internally, everything is normalized through importKey().

Import:

import { importKey, exportKey } from "unjwt/jwk";

importKey

importKey(key, algOrOptions?)

Takes any supported input shape and returns a CryptoKey (for asymmetric JWKs) or a Uint8Array (for symmetric material, by default).

Input shapes

InputOutput (default)Notes
stringUint8Array (UTF-8 bytes)Treat as a password or raw secret.
Uint8ArraySame Uint8ArrayReturned as-is.
CryptoKeySame CryptoKeyReturned as-is (subject to expect validation).
JWK_octUint8Array (from k)Bytes — pass asCryptoKey: true to get a CryptoKey.
JWK_Public / JWK_Private (asymmetric)CryptoKeyRequires alg (from the JWK or explicit option).

The expect option

expect: "public" | "private" validates the caller's intent before the import runs. If the key type doesn't match, importKey() throws ERR_JWK_INVALID instead of silently succeeding:

expect.ts
import { importKey } from "unjwt/jwk";

// Good: recipient public JWK passed with expect: "public"
const pubKey = await importKey(recipientJwk, { alg: "RSA-OAEP-256", expect: "public" });

// Will throw if somebody accidentally passed a private JWK here

expect is a no-op for symmetric JWKs and "secret"-type CryptoKeys — they have no public/private distinction.

verify() passes expect: "public" and decrypt() passes expect: "private" automatically. You only need expect when calling importKey() directly — which is rare; you'd typically just pass the JWK straight to sign/verify/encrypt/decrypt.

asCryptoKey: true for JWK_oct

By default, a JWK_oct imports as raw bytes. Opt in to a non-extractable CryptoKey:

as-cryptokey.ts
const aesCryptoKey = await importKey(symJwk, {
  asCryptoKey: true,
  algorithm: { name: "AES-GCM", length: 256 },
  usage: ["encrypt", "decrypt"],
  extractable: false, // default
});

Handy when you want the bytes to stay inside Web Crypto and never be retrievable.

Full options

// For JWK_oct
interface ImportOctOptions {
  asCryptoKey: true;
  algorithm: AlgorithmIdentifier | HmacImportParams | AesDerivedKeyParams;
  usage: KeyUsage[];
  extractable?: boolean; // default false for asCryptoKey: true
}

// For asymmetric JWK
interface ImportAsymmetricOptions {
  alg?: JWSAlgorithm | KeyManagementAlgorithm; // required if JWK.alg is missing
  expect?: "public" | "private";
}

exportKey

exportKey(key, jwkParams?)

Exports a CryptoKey as a JWK. Optionally merges metadata fields into the result.

export.ts
import { exportKey } from "unjwt/jwk";

const cryptoKey = await crypto.subtle.generateKey(/* ... */);
const jwk = await exportKey(cryptoKey, { kid: "legacy-1", use: "sig" });
// { kty, alg, key_ops, ext, ...actual key fields, kid: "legacy-1", use: "sig" }

The authoritative fields (alg, kty, key_ops, ext) come from Web Crypto's export and cannot be overridden via jwkParams. Only additive metadata (kid, use, x5c, x5t, x5u, custom fields) is merged.

Most of the time you won't call exportKey() directly — the output of generateJWK() is already a JWK. You'd use exportKey() when you've received or imported a CryptoKey from an external source (Web Crypto directly, another library) and need to serialize it.

See also