first commit
This commit is contained in:
87
docs/security-stack/crypto/crypto-rsa/src/verify/pss.md
Normal file
87
docs/security-stack/crypto/crypto-rsa/src/verify/pss.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# verify/pss
|
||||
|
||||
## Purpose
|
||||
|
||||
RSASSA-PSS signature verification per RFC 8017 §8.1.2. Recovers the
|
||||
encoded message via `s^e mod n`, then runs the EMSA-PSS verifier against
|
||||
the digest of the message under the given `(hash, mgfHash, saltLength)`
|
||||
triple.
|
||||
|
||||
## Features
|
||||
|
||||
- RFC 8017 §8.1.2 conformant
|
||||
- Uses `emsaPssVerify` for the structural check (which uses `constantTimeEqual` for the salt+hash compare)
|
||||
- Returns `false` on rejection; throws only on signature length mismatch
|
||||
- `saltLength` defaults to `hashOutputLength(hash)`
|
||||
- `mgfHash` defaults to `hash`
|
||||
- Modulus-length policy gates run on every call
|
||||
- Records `crypto_rsa.verify_duration_ms{scheme="pss",hash,engine}` and outcome counter on every call
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { rsaVerifyPss } from "@suaveplan/crypto-rsa/verify/pss";
|
||||
import { rsaSignPss } from "@suaveplan/crypto-rsa/sign/pss";
|
||||
|
||||
const message = new TextEncoder().encode("hello");
|
||||
const sig = rsaSignPss(privateKey, message, { hash: "SHA-256" });
|
||||
console.log(rsaVerifyPss(publicKey, message, sig, { hash: "SHA-256" })); // true
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { rsaVerifyPss } from "@suaveplan/crypto-rsa/verify/pss";
|
||||
import { rsaSignPss } from "@suaveplan/crypto-rsa/sign/pss";
|
||||
|
||||
// Custom saltLength: must match the value used by the signer.
|
||||
const sig = rsaSignPss(privateKey, message, { hash: "SHA-256", saltLength: 16 });
|
||||
console.log(rsaVerifyPss(publicKey, message, sig, { hash: "SHA-256", saltLength: 16 })); // true
|
||||
console.log(rsaVerifyPss(publicKey, message, sig, { hash: "SHA-256", saltLength: 32 })); // false
|
||||
|
||||
// mgfHash distinct from hash.
|
||||
const xSig = rsaSignPss(privateKey, message, {
|
||||
hash: "SHA-256",
|
||||
mgfHash: "SHA-1",
|
||||
});
|
||||
console.log(
|
||||
rsaVerifyPss(publicKey, message, xSig, {
|
||||
hash: "SHA-256",
|
||||
mgfHash: "SHA-1",
|
||||
})
|
||||
); // true
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `rsaVerifyPss(key, message, signature, options): boolean`
|
||||
|
||||
- `key: RsaPublicKey | RsaPrivateKey`
|
||||
- `message: Uint8Array`
|
||||
- `signature: Uint8Array` — must be exactly `byteLength(n)` long
|
||||
- `options.hash: RsaHashAlgorithm`
|
||||
- `options.saltLength?: number` — defaults to `hashOutputLength(hash)`
|
||||
- `options.mgfHash?: RsaHashAlgorithm` — defaults to `options.hash`
|
||||
- `options.allowLegacy?: boolean`
|
||||
- `options.allowOversize?: boolean`
|
||||
- **returns** `true` on valid, `false` on verify-level rejection
|
||||
- **throws** `CryptoRsaError(CRYPTO_RSA.INVALID_SIGNATURE)` on signature length mismatch
|
||||
- **throws** `CryptoRsaError(CRYPTO_RSA.MODULUS_TOO_SHORT)` / `MODULUS_TOO_LARGE` / `UNSUPPORTED_HASH`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- `s = os2ip(signature)` is checked against `s < n` before the modular
|
||||
exponentiation; signatures with `s >= n` are rejected with `false`.
|
||||
- The encoded message produced by `i2osp(s^e mod n, emLen)` has length
|
||||
`emLen = ceil((modulusBits - 1) / 8)`. This is one byte shorter than
|
||||
the signature itself when `modulusBits` is a multiple of 8 — the
|
||||
high-order zero pad is stripped here and the leftmost-bit clearance
|
||||
rule in `emsaPssVerify` enforces that the original encoding had the
|
||||
expected zero in that position.
|
||||
- The constant-time guarantee for the final salt+hash compare is
|
||||
delivered by `emsaPssVerify`'s use of `constantTimeEqual`. The
|
||||
earlier structural checks (length mismatch, `s >= n`) are guarded by
|
||||
fast-fail paths that do NOT leak the secret-derived signal — they
|
||||
test only public inputs.
|
||||
- The `verify_duration_ms` histogram is recorded on every code path
|
||||
(success, rejection, structural error).
|
||||
Reference in New Issue
Block a user