import * as ZLIB from 'node:zlib'; import * as CRYPTO from 'node:crypto'; export declare const AUTHORITY = "AUTHORITY.PEM"; /** An archive to be built or verified: a path on disk, or the bytes themselves. */ export type ArchiveSource = string | Buffer; /** A parsed `SIGNED::[:=]*` marker. */ export interface SignatureMarker { hash: string; sig: string; /** The trailing unsigned attributes, keyed by upper-case name. */ fields: Map; } /** What `checkIntegrity()` found. */ export interface IntegrityResult { /** The bytes hold together: the recorded hash, when there is one, and every member's digest. */ ok: boolean; /** Why not, or what was checked. */ reason: string; /** The digest the archive's manifest names for its hashes. */ hashAlg?: string | undefined; /** The whole-file hash, hex. */ hash?: string | undefined; /** `:`: the form attestations, install records and a host's parts name it by. */ pin?: string | undefined; /** Member name -> recorded hex digest. */ digests?: Map | undefined; /** Whether it carries a signature marker. Whether the signature is any good is not looked at. */ signed?: boolean | undefined; } /** * Check that an archive's bytes are what they say they are: the whole-file * hash against the one its comment records (`SIGNED:` or `UNSIGNED:`), and * — with `deep`, the default — every member's content against its digest. * An archive that records no hash at all is not one of ours, and not ok. * * It says nothing about who made the archive: anyone can recompute these. * Compare `pin` with a hash someone you trust gave you, and it says that * these are those bytes. */ export declare function checkIntegrity(source: ArchiveSource, { deep, archive }?: { deep?: boolean | undefined; /** An archive already open over `source`; left open for the caller. */ archive?: ZLIB.ZipFile | ZLIB.ZipBuffer | undefined; }): IntegrityResult; /** * Every member's recorded digest, checked against its content when `deep`; * or, as a string, the first way that fails. The manifest and directories * carry none. */ export declare function memberDigests(present: Map, hashAlg: string, deep: boolean): Map | string; /** The digest an `AUTHORITY.PEM` names for the whole-file hash and the members. */ export declare function hashAlgOf(content: Buffer | string): string; /** * The whole-file hash of `source` — what a signature covers and what an * attestation names — without verifying anything. Null when `source` is not an * archive with a manifest. This is the "which proofs do I need?" question asked * before a verification that will need them; the verification recomputes it. */ export declare function wholeFileHash(source: ArchiveSource): { hashAlg: string; hash: string; } | null; /** * The whole-file hash as `:` — `sha256:3f1a…` — the form a host's * `bundle.parts` pins a part by. Null for anything that is not an archive * with a manifest. */ export declare function pinOf(source: ArchiveSource): string | null; /** * The whole-file hash an unsigned archive records — `UNSIGNED:`, which * `bundle create` writes — or null. It says what the bytes should hash to, * not who made them: anyone can recompute it, so it catches damage and * accidents, and only a signature speaks to authorship. */ export declare function parseUnsigned(comment: string): string | null; /** * Parse an EOCD comment of the form * `SIGNED::[:=]*`, or null when the * archive is unsigned (no such marker). Field values never contain a `:`, which * is what keeps splitting on it unambiguous (base64 does not use one). */ export declare function parseSignature(comment: string): SignatureMarker | null; /** * The signature marker carried by `source`, or null when it carries none — * including when it is not a ZIP at all. Reads only the tail of the file, so it * is cheap enough to use as a "does this claim to be one of ours?" test before * committing to a full verification. */ export declare function signatureOf(source: ArchiveSource): SignatureMarker | null; /** * Whether `source` ends in a ZIP archive: one whose end-of-central-directory * record, comment included, runs exactly to the end of the file. A file can * contain an archive without ending in one — a SEA's own embedded file system * sits inside its blob, with more of the executable after it — and only an * archive at the very end is one that was appended. */ export declare function endsInArchive(source: ArchiveSource): boolean; export declare function isStructuralError(err: unknown): boolean; export interface ArchiveReader { entries(): Iterable<[string, ZLIB.ZipEntry]>; close(): void; } export declare function readerFor(archive: ZLIB.ZipFile | ZLIB.ZipBuffer): ArchiveReader; export interface Source { size: number; tail(): Buffer; feed(sink: CRYPTO.Hash, end: number): void; open(): ZLIB.ZipFile | ZLIB.ZipBuffer; } export declare function sourceOf(source: ArchiveSource): Source; /** The hash of the first `end` bytes: the region a signature covers. */ export declare function regionHash(io: Source, hashAlg: string, end: number): string; /** * Find the end-of-central-directory record in `tail` (the last bytes of a file * of total length `size`) and return { start, comment } with `start` absolute. * The EOCD must be the last structure in the file, so its comment runs to EOF. */ export declare function locateEocd(tail: Buffer, size: number): { start: number; comment: Buffer; }; /** An error's message, for errors that arrive as `unknown`. */ export declare function message(err: unknown): string; //# sourceMappingURL=integrity.d.ts.map