Initial Commit
This commit is contained in:
53
packages/security-stack/security/jws/src/algorithms/rsa.md
Normal file
53
packages/security-stack/security/jws/src/algorithms/rsa.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# RSASSA-PKCS1-v1_5 algorithms (`RS256` / `RS384` / `RS512`)
|
||||
|
||||
## Purpose
|
||||
|
||||
RFC 7518 §3.3 RSASSA-PKCS1-v1_5 signing and verification. The signing input is hashed with SHA-256/SHA-384/SHA-512 respectively, EMSA-PKCS1-v1_5-encoded to the modulus length, and signed via the modular-exponentiation primitive from `@suaveplan/crypto-rsa`. This is the dominant JWS algorithm in production (OAuth/OIDC JWT signing, SafetyNet, Apple App Attest, GitHub workflow tokens) and the algorithm `webauthn` is unblocked on.
|
||||
|
||||
## Features
|
||||
|
||||
- `RS256` → RSASSA-PKCS1-v1_5 + SHA-256.
|
||||
- `RS384` → RSASSA-PKCS1-v1_5 + SHA-384.
|
||||
- `RS512` → RSASSA-PKCS1-v1_5 + SHA-512.
|
||||
- Delegates to `@suaveplan/crypto-rsa`'s `rsaVerifyPkcs1v15` / `rsaSignPkcs1v15`.
|
||||
- Key shape: `RsaPublicKey` (verify) / `RsaPrivateKey` (sign) — both from `@suaveplan/crypto-rsa`.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { generateRsaKeyPair, parseRsaPublicKeyJwk } from "@suaveplan/crypto-rsa";
|
||||
import { compactSign, compactVerify } from "@suaveplan/jws";
|
||||
|
||||
const { publicKey, privateKey } = await generateRsaKeyPair({ modulusLength: 2048 });
|
||||
const token = await compactSign("hello", privateKey, "RS256");
|
||||
const r = await compactVerify(token, publicKey, { algorithms: ["RS256"] });
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { parseRsaPublicKey } from "@suaveplan/crypto-rsa";
|
||||
import { compactVerify, rs256 } from "@suaveplan/jws";
|
||||
|
||||
// Verify a JWS whose key arrived as a DER-encoded SPKI from a registry:
|
||||
const spkiDer = await fetch("/.well-known/jwks-spki.der").then((r) => r.bytes());
|
||||
const pub = parseRsaPublicKey(spkiDer, { format: "spki" });
|
||||
const result = await compactVerify(token, pub, {
|
||||
algorithms: ["RS256", "RS384"],
|
||||
});
|
||||
|
||||
// Direct-impl access (e.g. signing custom binary payloads):
|
||||
const sig = await rs256.sign!(signingInput, priv);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `rs256: AlgorithmImpl<RsaPublicKey | RsaPrivateKey>`
|
||||
- `rs384: AlgorithmImpl<RsaPublicKey | RsaPrivateKey>`
|
||||
- `rs512: AlgorithmImpl<RsaPublicKey | RsaPrivateKey>`
|
||||
|
||||
Each `verify` returns `Promise<boolean>`; each `sign` returns `Promise<Uint8Array>` of length `Math.ceil(bitLength/8)`. Non-RSA-shaped keys throw `JwsError(JWS.KEY_ALG_MISMATCH)`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
This module is a thin façade over `@suaveplan/crypto-rsa` — it never reimplements PKCS#1 v2.2 or modular arithmetic. Verification swallows any low-level `CryptoRsaError` and returns `false` so structural malformation surfaces as `JWS.SIG_INVALID` at the pipeline level rather than leaking RSA-package-internal codes; signing propagates because a sign-side error means the caller's key is structurally wrong (modulus too short, missing CRT parameters, etc.) and they need the precise diagnostic. RSA private operations in `@suaveplan/crypto-rsa` run through CRT and apply RSA blinding (Kocher 1996 timing-attack defence) by default.
|
||||
Reference in New Issue
Block a user