import type { WebCryptoKey } from '../webcrypto'; import { type Bytes, type P256PublicJwk } from './primitives'; export declare const SCOPE_KEY_BYTES = 32; /** 16 bytes of the key-id HMAC, as unpadded base64url. */ export declare const SCOPE_KEY_ID_LENGTH = 22; export declare const SCOPE_KEY_ID_PATTERN: RegExp; /** Byte length of the per-content HKDF salt. */ export declare const SEALED_SALT_BYTES = 32; export declare const SCOPE_KEY_PACKAGE_VERSION = 1; export declare const SCOPE_KEY_HPKE_INFO = "byok-sdk.scope-key.v1"; /** Prepended to the canonical package bytes the sender signs. */ export declare const SCOPE_KEY_PACKAGE_DOMAIN_PREFIX = "byok-scope-key-package-v1\n"; /** A fresh scope key from the platform CSPRNG. */ export declare function generateScopeKey(): Bytes; export declare function deriveScopeKeyId(scopeKey: Uint8Array): Promise; /** The AES-256-GCM key of one sealed content. Each content has its own salt, so each key encrypts once. */ export declare function deriveSealedContentKey(scopeKey: Uint8Array, salt: Uint8Array): Promise; /** * The content-MAC key of one scope epoch. The design's salt is empty; HMAC * pads its key with zeros, so 32 zero bytes give the same output, and no * runtime has to accept a zero-length HKDF salt. */ export declare function deriveSealedMacKey(scopeKey: Uint8Array): Promise; export interface ScopeKeyPackageV1 { readonly v: typeof SCOPE_KEY_PACKAGE_VERSION; readonly tenantId: string; readonly scopeId: string; readonly epoch: number; readonly keyId: string; /** Member id of the member that can open the package. */ readonly recipient: string; /** Member id of the member that sealed and signed the package. */ readonly sender: string; /** HPKE encapsulated key: base64url of a 65-byte uncompressed P-256 point. */ readonly enc: string; /** HPKE ciphertext of the scope key: base64url of 48 bytes. */ readonly ciphertext: string; /** Sender's ECDSA P-256 / SHA-256 signature, base64url of the 64-byte P1363 form. */ readonly sig: string; } export interface SealScopeKeyPackageInput { readonly scopeKey: Uint8Array; readonly tenantId: string; readonly scopeId: string; readonly epoch: number; readonly recipient: { readonly memberId: string; readonly kemPublicJwk: P256PublicJwk; }; readonly sender: { readonly signingPublicJwk: P256PublicJwk; readonly signingPrivateKey: WebCryptoKey; }; } /** * Wrap one scope key to one member and sign the package. A signing private key * that does not pair with `sender.signingPublicJwk` throws * `sealed_secret_invalid`. */ export declare function sealScopeKeyPackage(input: SealScopeKeyPackageInput): Promise; export interface OpenScopeKeyPackageInput { readonly package: unknown; /** What the caller asked the Host for. A package for anything else is refused. */ readonly expected: { readonly tenantId: string; readonly scopeId: string; readonly epoch: number; }; readonly recipient: { readonly memberId: string; readonly kemPublicJwk: P256PublicJwk; readonly kemPrivateKey: WebCryptoKey; }; /** The signing key the caller's verified chain holds for `package.sender`. */ readonly senderSigningPublicJwk: P256PublicJwk; } export type ScopeKeyPackageOpenResult = { readonly ok: true; readonly scopeKey: Uint8Array; readonly keyId: string; } | { readonly ok: false; readonly reason: 'key_package_invalid' | 'key_package_signature_invalid' | 'key_package_open_failed'; }; /** * Verify and open one key package, in this order: shape; addressed to this * recipient for the expected tenant, scope and epoch; sender key matches the * sender id; sender signature; HPKE open; key length; and `keyId` equal to * the opened key's own id. Nothing here throws for hostile input. */ export declare function openScopeKeyPackage(input: OpenScopeKeyPackageInput): Promise;