import { type TArg, type TRet } from '@noble/hashes/utils.js'; import * as P from 'micro-packed'; /** Byte-array alias used across the PGP helpers. */ export type Bytes = Uint8Array; /** * RFC 4880 multi-precision integer coder. * @example * Encode one RFC 4880 multi-precision integer. * ```ts * import { mpi } from 'micro-key-producer/pgp.js'; * mpi.encode(1n); * ``` */ export declare const mpi: P.CoderType; /** * Opaque MPI coder used by OpenPGP secret-key packets. * @example * Encode one opaque MPI for an OpenPGP secret-key packet. * ```ts * import { opaquempi } from 'micro-key-producer/pgp.js'; * opaquempi.encode(new Uint8Array([1, 2])); * ``` */ export declare const opaquempi: TRet>; /** * OpenPGP packet-length coder. * RFC 9580 §4.2.1.2 limits packet-body two-octet lengths to first octets * 192..223; §4.2.1.4 reserves 224..254 for partial body lengths, which this * definite-length packet codec intentionally rejects. * @example * Encode one OpenPGP packet length. * ```ts * import { PacketLen } from 'micro-key-producer/pgp.js'; * PacketLen.encode(191); * ``` */ export declare const PacketLen: P.CoderType; declare const SignatureSubpacketLen: P.CoderType; type S2KType = { TAG: 'simple'; data: { hash: string; }; } | { TAG: 'salted'; data: { hash: string; salt: Bytes; }; } | { TAG: 'iterated'; data: { hash: string; salt: Bytes; count: number; }; } | { TAG: 'argon2'; data: { salt: Bytes; t: number; p: number; encodedM: number; }; }; declare const S2KEnum: P.CoderType; declare const S2K: P.CoderType; type V4SymmetricKeyEncryptedSessionKeyPacketType = { version?: undefined; enc: string; S2K: S2KType; encryptedSessionKey: Bytes; }; type V6SymmetricKeyEncryptedSessionKeyPacketType = { version: 6; enc: string; aead: string; S2K: S2KType; iv: Bytes; encryptedSessionKey: Bytes; tag: Bytes; }; type SymmetricKeyEncryptedSessionKeyPacketType = V4SymmetricKeyEncryptedSessionKeyPacketType | V6SymmetricKeyEncryptedSessionKeyPacketType; type ECDSAPubType = { curve: string; pub: bigint; }; type ECDHPubType = { curve: string; pub: bigint; params: { hash: string; encryption: string; }; }; type NativePubType = { pub: Bytes; }; /** Supported OpenPGP public-key packet algorithms. */ export type PubKeyPacketAlgo = { TAG: 'EdDSA'; data: ECDSAPubType; } | { TAG: 'ECDSA'; data: ECDSAPubType; } | { TAG: 'ECDH'; data: ECDHPubType; } | { TAG: 'X25519'; data: NativePubType; } | { TAG: 'X448'; data: NativePubType; } | { TAG: 'Ed25519'; data: NativePubType; } | { TAG: 'Ed448'; data: NativePubType; }; /** Parsed OpenPGP public-key packet body. */ export type PubKeyPacketType = { version?: undefined | 6; created: number; algo: PubKeyPacketAlgo; }; export declare const PubKeyPacket: TRet>; declare const PlainSecretKey: P.CoderType<{ secret: Bytes; }>; type EncryptedSecretKeyParamsType = { enc: string; S2K: S2KType; iv: Bytes; }; declare const EncryptedSecretKey: P.CoderType; type SecretKeyProtectionType = { TAG: 'plain'; data: P.UnwrapCoder; } | { TAG: 'aead'; data: { enc: string; aead: string; S2K: S2KType; iv: Bytes; secret: Bytes; }; } | { TAG: 'encrypted'; data: P.UnwrapCoder; } | { TAG: 'encrypted2'; data: P.UnwrapCoder; } | { TAG: 'encryptedDirect'; data: { enc: string; iv: Bytes; secret: Bytes; }; }; declare const SecretKeyPacket: P.CoderType<{ pub: PubKeyPacketType; type: SecretKeyProtectionType; }>; type SecretKeyType = P.UnwrapCoder; declare const AEADCiphersuite: P.CoderType<{ enc: string; aead: string; }>; type SignatureSubpacketBodyType = { TAG: 'issuerFingerprint'; data: { version?: undefined | 6; fingerprint: string; }; } | { TAG: 'intendedRecipientFingerprint'; data: { version?: undefined | 6; fingerprint: string; }; } | { TAG: 'signatureCreationTime'; data: number; } | { TAG: 'signatureExpirationTime'; data: number; } | { TAG: 'exportableCertification'; data: boolean; } | { TAG: 'revocable'; data: boolean; } | { TAG: 'keyExpirationTime'; data: number; } | { TAG: 'revocationKey'; data: { class: number; algo: string; fingerprint: string; }; } | { TAG: 'notationData'; data: { humanReadable: boolean; name: string; value: Uint8Array; }; } | { TAG: 'keyFlags'; data: Record; } | { TAG: 'preferredEncryptionAlgorithms'; data: string[]; } | { TAG: 'preferredHashAlgorithms'; data: string[]; } | { TAG: 'preferredCompressionAlgorithms'; data: string[]; } | { TAG: 'preferredAEADAlgorithms'; data: string[]; } | { TAG: 'preferredAEADCiphersuites'; data: P.UnwrapCoder[]; } | { TAG: 'features'; data: Record; } | { TAG: 'keyServerPreferences'; data: Record; } | { TAG: 'preferredKeyServer'; data: string; } | { TAG: 'policyURI'; data: string; } | { TAG: 'issuer'; data: string; } | { TAG: 'primaryUserID'; data: boolean; } | { TAG: 'signersUserID'; data: string; } | { TAG: 'reasonForRevocation'; data: { code: number; reason: string; }; } | { TAG: 'embeddedSignature'; data: SignaturePacketType; }; type SignatureSubpacketType = SignatureSubpacketBodyType & { critical?: boolean; }; declare const SignatureSubpacket: P.CoderType; type SignatureHeadType = { version?: undefined | 6; type: string; algo: string; hash: string; hashed: SignatureSubpacketType[]; }; declare const SignatureHead: P.CoderType; type SignaturePacketType = { head: SignatureHeadType; unhashed: SignatureSubpacketType[]; hashPrefix: Bytes; salt?: Bytes; sig: bigint[] | Bytes; }; declare const SignaturePacket: P.CoderType; type SignatureType = P.UnwrapCoder; type OnePassSignaturePacketType = { version?: undefined; type: string; hash: string; algo: string; keyId: string; last: boolean; } | { version: 6; type: string; hash: string; algo: string; salt: Bytes; fingerprint: string; last: boolean; }; type LiteralDataPacketType = { format: string; filename: string; created: number; data: Bytes; }; type PKESKFingerprintType = { version?: undefined | 6; fingerprint: string; } | undefined; type PublicKeyEncryptedSessionKeyPacketType = { version: 6; fingerprint?: PKESKFingerprintType; algo: string; ephemeral: Bytes; encryptedSessionKey: Bytes; }; type HashUserData = { user: string; }; type SelfCertData = { pubKey: PubKeyPacketType; user: HashUserData; }; type SubKeyCertData = { pubKey: PubKeyPacketType; subKey: PubKeyPacketType; }; type SignatureData = SelfCertData | PubKeyPacketType | SubKeyCertData | Bytes | string; type PacketHeadType = { magic?: undefined; version?: undefined; tag: string; lenType?: number; newFormat?: boolean; }; type PacketData = { public_key_encrypted_session_key: PublicKeyEncryptedSessionKeyPacketType; symmetric_key_encrypted_session_key: SymmetricKeyEncryptedSessionKeyPacketType; userId: string; signature: SignaturePacketType; onePassSignature: OnePassSignaturePacketType; publicKey: PubKeyPacketType; publicSubkey: PubKeyPacketType; secretKey: SecretKeyType; secretSubkey: SecretKeyType; literalData: LiteralDataPacketType; encryptedProtectedData: Bytes; padding: Bytes; }; type PacketHeader = { newFormat?: true; partialLengths?: number[]; }; /** Parsed OpenPGP packet union used by the packet stream and ASCII armor helpers. */ export type Packet = { [K in keyof PacketData]: { TAG: K; data: PacketData[K]; } & PacketHeader; }[keyof PacketData]; declare function decryptV6PKESK(secretKey: TArg, packet: TArg): TRet; declare function decryptV6SKESK(password: TArg, packet: TArg): TRet; declare function decryptV2SEIPD(sessionKey: TArg, data: TArg): TRet; export declare const Stream: TRet>; export declare const __TESTS: { PacketHead: P.CoderType; SignatureHead: typeof SignatureHead; SignatureSubpacket: typeof SignatureSubpacket; SignatureSubpacketLen: typeof SignatureSubpacketLen; signData: typeof signData; verifyData: typeof verifyData; decryptV6PKESK: typeof decryptV6PKESK; decryptV6SKESK: typeof decryptV6SKESK; decryptV2SEIPD: typeof decryptV2SEIPD; S2KEnum: typeof S2KEnum; S2K: typeof S2K; }; declare function signData(head: TArg, unhashed: TArg, data: TArg, privateKey: TArg): SignatureType; type VerifyDataResult = { head: SignatureHeadType; hashPrefix: Bytes; hash: Bytes; verified: boolean; }; declare function verifyData(head: TArg, data: TArg, sig: TArg, publicKey: TArg, salt?: TArg): TRet; type SecretKeyPacketTag = 'secretKey' | 'secretSubkey'; /** * Decrypts the secret scalar from a PGP secret-key packet. * @param password - Secret-key passphrase. * @param key - Parsed secret-key packet. * @param packetTag - Optional outer packet tag for AEAD secret keys. * @returns Secret scalar as a bigint. * @throws If the packet uses unsupported encryption or fails checksum validation. {@link Error} * @example * Decrypt the secret scalar stored inside an armored private key packet. * ```ts * import { randomBytes } from '@noble/hashes/utils.js'; * import { decodeSecretKey, getKeys, privArmor } from 'micro-key-producer/pgp.js'; * const seed = randomBytes(32); * const packet = privArmor * .decode(getKeys(seed, 'alice@example.com', 'password').privateKey) * .find((p) => p.TAG === 'secretKey'); * if (!packet) throw new Error('missing secret-key packet'); * decodeSecretKey('password', packet.data); * ``` */ export declare function decodeSecretKey(password: string, key: TArg, packetTag?: SecretKeyPacketTag): bigint; /** * Password protection for generated secret-key packets. * - `'argon2'` (default): Argon2id S2K + AES-256-GCM, RFC 9580 usage 253. Memory-hard, * but GnuPG 2.4 and earlier cannot import such keys. * - `'legacy'`: iterated-salted SHA-1 S2K + AES-128-CFB, usage 254. Weaker KDF; kept for * interoperability with GnuPG <= 2.4. Distinct from the even older read-only * direct-cipher "LegacyCFB" format that `decodeSecretKey()` accepts. */ export type KeyProtection = 'argon2' | 'legacy'; type KeygenOpts = { protection?: KeyProtection; }; /** * ASCII armor for PGP public key blocks. * @example * Decode the armored public block that `getKeys()` produces. * ```ts * import { randomBytes } from '@noble/hashes/utils.js'; * import { getKeys, pubArmor } from 'micro-key-producer/pgp.js'; * const seed = randomBytes(32); * pubArmor.decode(getKeys(seed, 'alice@example.com').publicKey); * ``` */ export declare const pubArmor: TRet>; /** * ASCII armor for PGP private key blocks. * @example * Decode the armored private block back into OpenPGP packets. * ```ts * import { randomBytes } from '@noble/hashes/utils.js'; * import { getKeys, privArmor } from 'micro-key-producer/pgp.js'; * const seed = randomBytes(32); * privArmor.decode(getKeys(seed, 'alice@example.com').privateKey); * ``` */ export declare const privArmor: TRet>; /** * ASCII armor for detached PGP signatures. * @example * Decode an armored detached signature back into its packet list. * ```ts * import { randomBytes } from '@noble/hashes/utils.js'; * import { sigArmor, signDetached } from 'micro-key-producer/pgp.js'; * const seed = randomBytes(32); * sigArmor.decode(signDetached(seed, 'hello')); * ``` */ export declare const sigArmor: TRet>; /** * Formats the armored public half of a deterministic OpenPGP keypair. * @param edPriv - Ed25519 signing private key. * @param cvPriv - Curve25519 encryption private key. * @param user - OpenPGP user ID string. * @param createdAt - Key creation time as UNIX timestamp in seconds. * @returns ASCII-armored public key block. * @throws If the supplied key material or timestamp cannot be encoded as OpenPGP packets. {@link Error} * @example * Build the public OpenPGP block from the signing key and its Curve25519 subkey. * ```ts * import { randomBytes } from '@noble/hashes/utils.js'; * import { formatPublic } from 'micro-key-producer/pgp.js'; * import { ed25519 } from '@noble/curves/ed25519.js'; * const seed = randomBytes(32); * const cvPriv = ed25519.utils.getExtendedPublicKey(seed).head; * formatPublic(seed, cvPriv, 'alice@example.com', 0); * ``` */ export declare function formatPublic(edPriv: TArg, cvPriv: TArg, user: string, createdAt: number): string; /** * Formats the armored private half of a deterministic OpenPGP keypair. * @param edPriv - Ed25519 signing private key. * @param cvPriv - Curve25519 encryption private key. * @param user - OpenPGP user ID string. * @param password - Optional secret-key passphrase. * @param createdAt - Key creation time as UNIX timestamp in seconds. * @param opts - Optional `{ protection }`; see {@link KeyProtection}. * @returns ASCII-armored private key block. * @throws If the supplied key material or timestamp cannot be encoded as OpenPGP packets. {@link Error} * @example * Build the password-protected private key block and matching encryption subkey. * ```ts * import { randomBytes } from '@noble/hashes/utils.js'; * import { formatPrivate } from 'micro-key-producer/pgp.js'; * import { ed25519 } from '@noble/curves/ed25519.js'; * const seed = randomBytes(32); * const cvPriv = ed25519.utils.getExtendedPublicKey(seed).head; * formatPrivate(seed, cvPriv, 'alice@example.com', 'password'); * ``` */ export declare function formatPrivate(edPriv: TArg, cvPriv: TArg, user: string, password?: string, createdAt?: number, opts?: KeygenOpts): string; /** * Derives PGP key ID from the private key. * PGP key depends on its date of creation. * @param edPrivKey - Ed25519 signing private key. * @param createdAt - Key creation time as UNIX timestamp in seconds. * @returns Public packets plus fingerprint and key ID. * @throws If the key material or creation time cannot be encoded as OpenPGP packets. {@link Error} * @example * Recompute the OpenPGP fingerprint and key ID for an existing signing key. * ```ts * import { randomBytes } from '@noble/hashes/utils.js'; * import { getKeyId } from 'micro-key-producer/pgp.js'; * getKeyId(randomBytes(32)).keyId; * ``` */ export declare function getKeyId(edPrivKey: TArg, createdAt?: number): { edPubPacket: { readonly created: number; readonly algo: { readonly TAG: 'EdDSA'; readonly data: { readonly curve: 'ed25519'; readonly pub: bigint; }; }; }; fingerprint: string; keyId: string; cvPubPacket: { readonly created: number; readonly algo: { readonly TAG: 'ECDH'; readonly data: { readonly curve: 'curve25519'; readonly pub: bigint; readonly params: { readonly hash: 'sha256'; readonly encryption: 'aes128'; }; }; }; }; }; /** * Derives PGP private key, public key and fingerprint. * Uses S2K KDF, which means it's slow. Use `getKeyId` if you want to get key id in a fast way. * PGP key depends on its date of creation. * NOTE: gpg: warning: lower 3 bits of the secret key are not cleared * happens even for keys generated with GnuPG 2.3.6, because check looks at item as Opaque MPI, when it is just MPI. See {@link https://dev.gnupg.org/rGdbfb7f809b89cfe05bdacafdb91a2d485b9fe2e0 | the GnuPG bugtracker note}. * @param privKey - Ed25519 signing private key. * @param user - OpenPGP user ID string. * @param password - Optional secret-key passphrase. * @param createdAt - Key creation time as UNIX timestamp in seconds. * @param opts - Optional `{ protection }`; see {@link KeyProtection}. Pass * `{ protection: 'legacy' }` for password-protected keys that GnuPG <= 2.4 can import. * @returns Armored keypair plus fingerprint data. * @throws If the key material or creation time cannot be encoded as OpenPGP packets. {@link Error} * @example * Derive the armored OpenPGP keypair from one Ed25519 private key. * ```ts * import { randomBytes } from '@noble/hashes/utils.js'; * import { getKeys } from 'micro-key-producer/pgp.js'; * const seed = randomBytes(32); * getKeys(seed, 'alice@example.com').publicKey; * ``` */ export declare function getKeys(privKey: TArg, user: string, password?: string, createdAt?: number, opts?: { protection?: KeyProtection; }): { keyId: string; fingerprint: string; privateKey: string; publicKey: string; }; /** * Default export for deterministic OpenPGP key derivation. * @param privKey - Ed25519 signing private key. * @param user - OpenPGP user ID string. * @param password - Optional secret-key passphrase. * @param createdAt - Key creation time as UNIX timestamp in seconds. * @returns Armored keypair plus fingerprint data. * @throws If the key material or creation time cannot be encoded as OpenPGP packets. {@link Error} * @example * Use the default export when you want the full armored OpenPGP bundle in one call. * ```ts * import getKeys from 'micro-key-producer/pgp.js'; * import { randomBytes } from '@noble/hashes/utils.js'; * const seed = randomBytes(32); * getKeys(seed, 'alice@example.com').publicKey; * ``` */ export default getKeys; /** Options for detached OpenPGP signature creation. */ export type SignDetachedOptions = { /** Creation time of the version-4 OpenPGP signing-key packet. */ keyCreatedAt?: number; /** Signature creation time as a UNIX timestamp in seconds. */ signedAt?: number; }; /** * Creates an armored detached OpenPGP signature. * @param privateKey - Ed25519 signing private key. * @param data - Binary or text payload to sign. * @param options - Signing-key and signature creation times. * @returns ASCII-armored detached signature. * @throws If the detached payload cannot be encoded or signed as OpenPGP data. {@link Error} * @example * Create a detached signature you can send alongside the original text payload. * ```ts * import { randomBytes } from '@noble/hashes/utils.js'; * import { signDetached } from 'micro-key-producer/pgp.js'; * const seed = randomBytes(32); * signDetached(seed, 'hello'); * ``` */ export declare function signDetached(privateKey: TArg, data: TArg, options?: TArg): string; /** Options for detached OpenPGP signature verification. */ export type VerifyDetachedOptions = { /** Expected fingerprint of a complete public-key packet. */ fingerprint?: string; }; /** * @param signature - ASCII-armored detached signature. * @param data - Original binary or text payload. * @param publicKey - Raw Ed25519 bytes for cryptographic verification, or a complete parsed * OpenPGP public-key packet for identity-bound verification. * @param options - Optional expected fingerprint; requires a complete public-key packet. * @returns Whether the detached signature verifies. * @throws If the signature, payload, public-key packet, or fingerprint binding is invalid. {@link Error} * @example * Verify the detached signature and bind it to the complete signing-key packet. * ```ts * import { randomBytes } from '@noble/hashes/utils.js'; * import { getKeyId, signDetached, verifyDetached } from 'micro-key-producer/pgp.js'; * const privateKey = randomBytes(32); * const { edPubPacket, fingerprint } = getKeyId(privateKey); * const signature = signDetached(privateKey, 'hello'); * verifyDetached(signature, 'hello', edPubPacket, { fingerprint }); * ``` */ export declare function verifyDetached(signature: string, data: TArg, publicKey: TArg, options?: TArg): boolean; /** Parsed primary Ed25519 secret-key material from an armored OpenPGP private key. */ export type ParsedPrivateKey = { /** Raw 32-byte Ed25519 private key seed extracted from the primary secret-key packet. */ privateKey: Bytes; /** Primary key creation time as a UNIX timestamp in seconds. */ created: number; /** Recomputed OpenPGP fingerprint for the extracted primary key. */ fingerprint: string; /** Low-64-bit OpenPGP key ID derived from the recomputed fingerprint. */ keyId: string; /** Raw 32-byte Ed25519 public key derived from `privateKey`. */ publicKey: Bytes; /** First User ID packet from the armored block, if present. NOT certification-validated. */ user?: string; }; /** * This is a basic parsing to extract enough information to signDetached signatures. * Supports keys generated by us or PGP (ed25519 only + default opts), doesn't extract ECDH (x25519) keys. * @param privateKey - ASCII-armored private key block. * @param getPassword - Optional callback used to fetch the secret-key passphrase. * @returns Parsed secret key bytes and identifying metadata. * @throws If the armored packet layout, password callback, or decoded key material is invalid. {@link Error} * @remarks Argon2 S2K derivation is synchronous. RFC 9580 §3.7.1.4 illustrates its first * recommended option with `m=2^21` KiB (2 GiB), and this parser accepts that case for * interoperability. Isolate password-based parsing of untrusted private keys from the main event * loop. * @example * Parse an armored secret key back into raw key bytes and OpenPGP metadata. * ```ts * import { randomBytes } from '@noble/hashes/utils.js'; * import { getKeys, parsePrivateKey } from 'micro-key-producer/pgp.js'; * const seed = randomBytes(32); * const { privateKey } = getKeys(seed, 'alice@example.com'); * parsePrivateKey(privateKey).then(({ keyId }) => keyId); * ``` */ export declare function parsePrivateKey(privateKey: string, getPassword?: () => Promise): Promise>;