Initial Commit
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
# keys/jwk-policy
|
||||
|
||||
## Purpose
|
||||
|
||||
Cross-check a JWK's `key_ops`, `use`, and `alg` members against the
|
||||
requested operation per RFC 7517 §4.2 / §4.3 / §4.4 + RFC 7518 §6.3.
|
||||
Prevents the common operational mistake of using a JWK marked
|
||||
`use: "sig"` for encryption (or vice-versa), which leaks both the key
|
||||
purpose and the operator intent into the wrong code path.
|
||||
|
||||
## Features
|
||||
|
||||
- Validates `key_ops` ⊃ requested operation (with the standard
|
||||
encrypt → wrapKey, decrypt → unwrapKey aliases)
|
||||
- Validates `use === "sig"` permits only sign/verify and `use === "enc"`
|
||||
permits only encrypt/decrypt
|
||||
- Validates `alg` is one of the RSA-compatible JWA registry values
|
||||
(`RS{256,384,512}`, `PS{256,384,512}`, `RSA-OAEP{,−256,−384,−512}`,
|
||||
`RSA1_5`) AND is appropriate for the requested operation class
|
||||
- Each violation throws `CRYPTO_RSA.KEY_OP_NOT_PERMITTED` with a
|
||||
`reason` attribute (`"key_ops"` / `"use"` / `"alg"`) plus context
|
||||
identifying the offending member
|
||||
- Skips checks when the JWK omits the corresponding member (RFC 7517
|
||||
semantics: absence ≠ denial)
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { enforceJwkPolicy } from "@suaveplan/crypto-rsa/keys/jwk-policy";
|
||||
|
||||
const jwk = {
|
||||
kty: "RSA",
|
||||
n: "...",
|
||||
e: "AQAB",
|
||||
use: "sig",
|
||||
alg: "RS256",
|
||||
key_ops: ["sign"],
|
||||
};
|
||||
enforceJwkPolicy(jwk, "sign"); // no-op
|
||||
enforceJwkPolicy(jwk, "encrypt"); // throws KEY_OP_NOT_PERMITTED
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
Wire policy enforcement into a higher-level signer that accepts both
|
||||
canonical `RsaPrivateKey` and JWK inputs; only run the policy check on
|
||||
the JWK path because canonical keys carry no policy fields:
|
||||
|
||||
```ts
|
||||
import { enforceJwkPolicy, parseRsaPrivateKey } from "@suaveplan/crypto-rsa";
|
||||
|
||||
function loadSigningKey(input: RsaJwk | Uint8Array): RsaPrivateKey {
|
||||
if (typeof input === "object" && "kty" in input) {
|
||||
enforceJwkPolicy(input, "sign");
|
||||
return parseRsaPrivateKey(input, { format: "jwk" });
|
||||
}
|
||||
return parseRsaPrivateKey(input, { format: "pkcs8" });
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `enforceJwkPolicy(jwk, operation): void`
|
||||
|
||||
- `jwk: RsaJwk`
|
||||
- `operation: "sign" | "verify" | "encrypt" | "decrypt"`
|
||||
- **throws** `CryptoRsaError(CRYPTO_RSA.KEY_OP_NOT_PERMITTED)` on any
|
||||
cross-policy violation; the error context carries `reason` (which
|
||||
member triggered the rejection) plus the member value
|
||||
|
||||
### `JwkOperation`
|
||||
|
||||
`"sign" | "verify" | "encrypt" | "decrypt"`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The canonical `RsaPublicKey` / `RsaPrivateKey` shapes have no
|
||||
`key_ops` / `use` / `alg` fields, so direct callers using the
|
||||
canonical types bypass policy enforcement entirely. Wrap the policy
|
||||
check at the JWK ingestion boundary if you need it; the package's
|
||||
built-in sign / encrypt surfaces accept canonical keys precisely so
|
||||
they don't impose JWK-specific semantics.
|
||||
- The encrypt → wrapKey / decrypt → unwrapKey aliases follow RFC 7517
|
||||
§4.3 (`key_ops` value definitions); a JWK marked `key_ops: ["wrapKey"]`
|
||||
is permitted to encrypt because the cryptographic operation is the
|
||||
same (RSA public encryption).
|
||||
- When `use` and `alg` both appear they MUST be consistent (RFC 7517
|
||||
§4.4); this implementation does not cross-check them against each
|
||||
other because the JWA registry ties algorithm IDs to a single use,
|
||||
so the per-member checks already cover the cross-product.
|
||||
- `key_ops` and `use` together are RFC-permitted but discouraged
|
||||
(RFC 7517 §4.3 last paragraph); both checks fire independently when
|
||||
both are present.
|
||||
Reference in New Issue
Block a user