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
| Input | Output (default) | Notes |
|---|---|---|
string | Uint8Array (UTF-8 bytes) | Treat as a password or raw secret. |
Uint8Array | Same Uint8Array | Returned as-is. |
CryptoKey | Same CryptoKey | Returned as-is (subject to expect validation). |
JWK_oct | Uint8Array (from k) | Bytes — pass asCryptoKey: true to get a CryptoKey. |
JWK_Public / JWK_Private (asymmetric) | CryptoKey | Requires 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:
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:
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.
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.
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
- Generating keys →
- PEM conversion → — for keys in
.pemfiles. - JWK cache → —
importKeymemoization.