# JWK — keys as JSON

A **JSON Web Key** ([RFC 7517](https://www.rfc-editor.org/rfc/rfc7517)) is a portable JSON representation of a cryptographic key. Every signing, verifying, encrypting, and decrypting operation in unjwt starts with a key — and JWK is the lingua franca for carrying that key through config files, environment variables, databases, and across the wire.

```json
{
  "kty": "oct",
  "k": "GawgguFyGrWKav7AX4VKUg",
  "alg": "HS256",
  "kid": "4c3d-..."
}
```

Import:

```ts
import { generateJWK, importKey, exportKey } from "unjwt/jwk";
// or from the flat barrel:
import { generateJWK } from "unjwt";
```

## Basic usage

The most common operation — **create a key**:

```ts [generate.ts]
import { generateJWK } from "unjwt/jwk";

// Symmetric — one JWK
const hmacKey = await generateJWK("HS256");
// { kty: "oct", k: "...", alg: "HS256", kid: "4c3d-..." }

// Asymmetric — a pair
const { privateKey, publicKey } = await generateJWK("RS256");
```

Every JWK produced by `generateJWK()` includes:

- `kty` — key type (`"oct"` | `"RSA"` | `"EC"` | `"OKP"`).
- `alg` — the algorithm it's meant for (e.g. `"HS256"`, `"RS256"`, `"Ed25519"`).
- `kid` — an auto-generated UUID, which any JWT signed with this key will carry in its header for routing.

Those three fields are why the rest of the library "just works" — `sign()`, `verify()`, `encrypt()`, `decrypt()` all read them and do the right thing.

## The JWK shape

Every JWK has a `kty` (key type) field that determines its other properties:

<table>
<thead>
  <tr>
    <th>
      <code>
        kty
      </code>
    </th>
    
    <th>
      Meaning
    </th>
    
    <th>
      Key fields
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        "oct"
      </code>
    </td>
    
    <td>
      Symmetric (secret)
    </td>
    
    <td>
      <code>
        k
      </code>
      
       (base64url-encoded bytes)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        "RSA"
      </code>
    </td>
    
    <td>
      RSA keypair
    </td>
    
    <td>
      <code>
        n
      </code>
      
      , <code>
        e
      </code>
      
      , and <code>
        d
      </code>
      
      /<code>
        p
      </code>
      
      /<code>
        q
      </code>
      
      /<code>
        dp
      </code>
      
      /<code>
        dq
      </code>
      
      /<code>
        qi
      </code>
      
       if private
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        "EC"
      </code>
    </td>
    
    <td>
      Elliptic curve
    </td>
    
    <td>
      <code>
        crv
      </code>
      
      , <code>
        x
      </code>
      
      , <code>
        y
      </code>
      
      , and <code>
        d
      </code>
      
       if private
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        "OKP"
      </code>
    </td>
    
    <td>
      "Octet Key Pair" (EdDSA / X25519 / Ed448)
    </td>
    
    <td>
      <code>
        crv
      </code>
      
      , <code>
        x
      </code>
      
      , and <code>
        d
      </code>
      
       if private
    </td>
  </tr>
</tbody>
</table>

A JWK is **public** if it carries no `d` (or has no `d` equivalent for `oct`); **private** if it does.

unjwt provides [type guards](/utilities#type-guards) to distinguish:

```ts
import { isPublicJWK, isPrivateJWK, isSymmetricJWK } from "unjwt/utils";

if (isSymmetricJWK(key)) {
  /* kty === "oct" */
}
if (isPublicJWK(key)) {
  /* asymmetric, no d */
}
if (isPrivateJWK(key)) {
  /* asymmetric, has d */
}
```

## What you can do with a JWK

- **Generate** one — [`generateJWK()`](/jwk/generating).
- **Import** existing material — [`importKey()`](/jwk/import-export).
- **Export** a `CryptoKey` to JWK — [`exportKey()`](/jwk/import-export).
- **Convert to/from PEM** — [`importPEM()`](/jwk/pem) / [`exportPEM()`](/jwk/pem).
- **Wrap / unwrap** a key with another key — [`wrapKey()`](/jwk/wrapping) / [`unwrapKey()`](/jwk/wrapping).
- **Derive** from a password — [`deriveJWKFromPassword()`](/jwk/password-derivation).
- **Rotate** using a JWK Set — [JWK Sets](/jwk/jwk-sets).
- **Cache** to avoid repeat imports — [JWK cache](/jwk/cache).

## Going further

- [Generating keys →](/jwk/generating) — `generateKey` vs `generateJWK`, algorithms, curves, RSA modulus.
- [Importing & exporting →](/jwk/import-export) — `importKey`, `exportKey`, the `expect` option.
- [PEM conversion →](/jwk/pem) — `importPEM` / `exportPEM`.
- [Wrapping & unwrapping →](/jwk/wrapping) — wrapping a CEK for custom protocols.
- [Password derivation →](/jwk/password-derivation) — PBES2 and PBKDF2.
- [JWK Sets →](/jwk/jwk-sets) — multi-key selection, JWKS endpoints, key rotation.
- [JWK cache →](/jwk/cache) — controlling how imported CryptoKeys are memoized.
