first commit
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
# emsa-pkcs1-v1\_5
|
||||
|
||||
## Purpose
|
||||
|
||||
Implements EMSA-PKCS1-v1\_5-ENCODE from RFC 8017 §9.2 — the encoding
|
||||
method underlying RSASSA-PKCS1-v1\_5 signatures. This module also pins
|
||||
the four DigestInfo prefix byte sequences from §9.2 note 1 as named
|
||||
constants so consumers and tests can audit the bytes against the RFC.
|
||||
|
||||
## Features
|
||||
|
||||
- Hard-coded `DIGEST_INFO_PREFIX_*` constants for SHA-1, SHA-256, SHA-384, SHA-512
|
||||
- `digestInfoPrefix(hash)` lookup — throws `CRYPTO_RSA.UNSUPPORTED_HASH` on unknown algorithm
|
||||
- `emsaPkcs1v15Encode(message, emLen, hash)` — RFC 8017 §9.2 conformant encoder
|
||||
- Detects modulus-too-short conditions (`emLen < tLen + 11`) and throws `CRYPTO_RSA.INVALID_KEY`
|
||||
- Returns a fresh `Uint8Array` of length exactly `emLen`
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { emsaPkcs1v15Encode } from "@suaveplan/crypto-rsa/encoding/emsa-pkcs1-v1_5";
|
||||
|
||||
const message = new TextEncoder().encode("hello");
|
||||
const em = emsaPkcs1v15Encode(message, 256, "SHA-256");
|
||||
console.log(em.length); // 256
|
||||
console.log(em[0], em[1]); // 0x00, 0x01
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
The encoded message is the input to the RSA private-key operation in
|
||||
`rsaSignPkcs1v15`. To verify a signature, the same encoder is run on the
|
||||
candidate message and the result is constant-time compared against the
|
||||
public-key recovery of the signature.
|
||||
|
||||
```ts
|
||||
import { emsaPkcs1v15Encode, digestInfoPrefix } from "@suaveplan/crypto-rsa/encoding/emsa-pkcs1-v1_5";
|
||||
import { toHex } from "@suaveplan/crypto-utils";
|
||||
|
||||
const prefix = digestInfoPrefix("SHA-256");
|
||||
console.log(toHex(prefix as Uint8Array));
|
||||
// 3031300d060960864801650304020105000420
|
||||
|
||||
const em1 = emsaPkcs1v15Encode(new Uint8Array([1, 2, 3]), 256, "SHA-256");
|
||||
const em2 = emsaPkcs1v15Encode(new Uint8Array([1, 2, 3]), 256, "SHA-256");
|
||||
// em1 and em2 are byte-identical (encoding is deterministic)
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `emsaPkcs1v15Encode(message, emLen, hash): Uint8Array`
|
||||
|
||||
- `message: Uint8Array` — the bytes that will be digested
|
||||
- `emLen: number` — the target encoded-message length, equal to `byteLength(n)`
|
||||
- `hash: RsaHashAlgorithm` — `"SHA-1" | "SHA-256" | "SHA-384" | "SHA-512"`
|
||||
- **returns** `Uint8Array` of length exactly `emLen`
|
||||
- **throws** `CryptoRsaError(CRYPTO_RSA.INVALID_KEY)` when `emLen < tLen + 11` (modulus too short for the chosen hash)
|
||||
- **throws** `CryptoRsaError(CRYPTO_RSA.UNSUPPORTED_HASH)` on unknown algorithm
|
||||
|
||||
### `digestInfoPrefix(hash): Readonly<Uint8Array>`
|
||||
|
||||
Returns the immutable RFC 8017 §9.2 note 1 DigestInfo prefix for `hash`.
|
||||
|
||||
### `DIGEST_INFO_PREFIX_SHA1` / `_SHA256` / `_SHA384` / `_SHA512`
|
||||
|
||||
Read-only `Uint8Array` constants holding the byte-exact DigestInfo
|
||||
prefix sequences from RFC 8017 §9.2 note 1.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The encoded message structure is `0x00 || 0x01 || PS || 0x00 || T`,
|
||||
where `PS` is at least 8 bytes of `0xff` (per RFC 8017 §9.2 step 3).
|
||||
The `tLen + 11` floor encodes the 2-byte header (`0x00 || 0x01`), the
|
||||
1-byte separator (`0x00`), and the 8-byte minimum for `PS`.
|
||||
- The DigestInfo prefix bytes are pinned as literal byte arrays — not
|
||||
ASN.1 encoder calls — so a single misbyte in the RFC table would be
|
||||
caught by the bytewise prefix tests against the RFC reference.
|
||||
- The `emLen` parameter is supplied by the caller (= `byteLength(n)` for
|
||||
RSASSA-PKCS1-v1\_5). This module does not compute `emLen` from a key;
|
||||
that responsibility belongs to the higher-level signature scheme.
|
||||
- Encoding is deterministic — the same `(message, emLen, hash)` triple
|
||||
always produces the same `EM` bytes.
|
||||
- Hash dispatch goes through `digestWith` from `mgf1.ts`, so SHA-2
|
||||
flows through `@suaveplan/crypto-hash` and SHA-1 through Noble.
|
||||
Reference in New Issue
Block a user