# secretorprivatekey must be an asymmetric key when using rs256

## TL;DR
You asked the jsonwebtoken library to use RS256, which is RSA asymmetric signing, but handed it a plain string secret, which only works with HS256. Generate an RSA key pair, sign with the private key, and verify with the public key. If you actually want a shared string secret, switch the algorithm back to HS256 explicitly instead.

```text
secretorprivatekey must be an asymmetric key when using rs256
```

## Use this when
- Node throws this error from jwt.sign or jwt.verify
- You are migrating an app from HS256 to RS256
- A tutorial's RS256 example fails because the key material is a string
- Verify works in one service and throws this in another (mismatched key material)

## Not for this skill when
- Tokens fail with expiry or audience errors (the keys are fine there)
- You are debugging key rotation or JWKS fetching
- The error is about PEM formatting rather than key type

## Steps
1. Generate an RSA key pair with openssl:
   ```bash
   openssl genrsa -out private.pem 2048
   openssl rsa -in private.pem -pubout -out public.pem
   ```
   Expected: two files, private.pem starting with a PRIVATE KEY header and public.pem with a PUBLIC KEY header.

2. Sign with the private key and verify with the public key:
   ```js
   const fs = require('fs');
   const jwt = require('jsonwebtoken');
   const signWith = fs.readFileSync('private.pem');
   const verifyWith = fs.readFileSync('public.pem');
   const signed = jwt.sign({ sub: '[user id]' }, signWith, { algorithm: 'RS256', expiresIn: '15m' });
   const decoded = jwt.verify(signed, verifyWith, { algorithms: ['RS256'] });
   ```
   Expected: verify returns the payload object with no throw. Note the explicit `algorithms` list on verify, which pins verification to RS256.

3. Store the keys properly. The private key belongs in a secret manager or a file with tight permissions, loaded at startup. The public key is not sensitive and can live in config or be published at a JWKS endpoint.
   Expected: the app boots, signs, and verifies with no key-type errors, and the private key is not in source control.

4. If you truly want symmetric signing, be explicit. Change both sign and verify to `HS256` and use your string secret on both sides. Do not mix: signing HS256 and verifying RS256 (or the reverse) fails.
   Expected: consistent algorithm on both ends, and you have consciously accepted that one shared secret signs and verifies.

### Variant: verifying RS256 with the private key
It technically works, since the private key contains the public parts, but it is wrong in spirit: verifiers should only ever hold the public key. Pass the public key to verify.

### Variant: "error:0909006C:PEM routines" after fixing the key type
You cleared the type error and now the PEM itself is malformed. Check for truncated files, Windows line endings, or a key pasted with missing header and footer lines.

### Variant: passphrase-protected private key
openssl can encrypt the private key. Then you must supply the passphrase when loading it, or the sign call fails. For services, prefer an unencrypted key file with strict file permissions over a passphrase in config.

### Variant: same error from a different library
Every JWT library enforces the same rule: asymmetric algorithms need asymmetric keys. The fix is identical, only the option names differ.

## Why this happens
RS256 signs with an RSA private key and verifies with the matching public key, so the signer and verifier do not have to share a secret. The library refuses a string secret for RS256 on purpose: silently accepting it would either produce broken signatures or, worse, tempt a downgrade to symmetric verification where anyone holding the public key could forge tokens.

## Edge cases and pitfalls
- Key files committed to git are compromised the moment they are pushed. Rotate and move them to a secret manager.
- 2048-bit RSA is the sane minimum. Larger keys slow signing with little benefit for session tokens.
- Reading the key on every request instead of once at startup is a needless performance hit and a file-handle leak risk.
- If verification must happen in another service or language, export the public key in a standard format (PEM or JWK) rather than inventing your own serialization.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_cvFPxFJltFyvy1Npzh2OcQ
