mdenc 0.1.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -11
- package/dist/cli.js +1007 -372
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +144 -126
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -4
- package/dist/index.d.ts +2 -4
- package/dist/index.js +144 -126
- package/dist/index.js.map +1 -1
- package/package.json +10 -9
- package/dist/chunk-DQSJGHST.js +0 -688
- package/dist/chunk-DQSJGHST.js.map +0 -1
- package/dist/hooks-7DUHI6MG.js +0 -16
- package/dist/hooks-7DUHI6MG.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/git/hooks.ts","../src/encrypt.ts","../src/chunking.ts","../src/kdf.ts","../src/types.ts","../src/crypto-utils.ts","../src/aead.ts","../src/header.ts","../src/git/password.ts","../src/git/utils.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync, statSync, unlinkSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport { encrypt, decrypt } from '../encrypt.js';\nimport { resolvePassword } from './password.js';\nimport {\n findGitRoot,\n findMarkedDirs,\n getMdFilesInDir,\n getMdencFilesInDir,\n gitAdd,\n gitRmCached,\n isFileStaged,\n} from './utils.js';\n\nfunction needsReEncryption(mdPath: string, mdencPath: string): boolean {\n if (!existsSync(mdencPath)) return true;\n const mdMtime = statSync(mdPath).mtimeMs;\n const mdencMtime = statSync(mdencPath).mtimeMs;\n return mdMtime > mdencMtime;\n}\n\nexport async function preCommitHook(): Promise<void> {\n const repoRoot = findGitRoot();\n const password = resolvePassword(repoRoot);\n\n if (!password) {\n process.stderr.write(\n 'mdenc: no password available (set MDENC_PASSWORD or create .mdenc-password). Skipping encryption.\\n',\n );\n process.exit(0);\n }\n\n const markedDirs = findMarkedDirs(repoRoot);\n if (markedDirs.length === 0) process.exit(0);\n\n let encryptedCount = 0;\n let skippedCount = 0;\n let errorCount = 0;\n\n for (const dir of markedDirs) {\n const mdFiles = getMdFilesInDir(dir);\n\n for (const mdFile of mdFiles) {\n const mdPath = join(dir, mdFile);\n const mdencPath = mdPath.replace(/\\.md$/, '.mdenc');\n const relMdPath = relative(repoRoot, mdPath);\n const relMdencPath = relative(repoRoot, mdencPath);\n\n // Skip if .md hasn't changed since last encryption\n if (!needsReEncryption(mdPath, mdencPath)) {\n skippedCount++;\n // Still ensure the .mdenc is staged if it exists\n if (existsSync(mdencPath)) {\n gitAdd(repoRoot, [relMdencPath]);\n }\n continue;\n }\n\n try {\n const plaintext = readFileSync(mdPath, 'utf-8');\n\n // Read existing .mdenc for previousFile optimization\n let previousFile: string | undefined;\n if (existsSync(mdencPath)) {\n previousFile = readFileSync(mdencPath, 'utf-8');\n }\n\n const encrypted = await encrypt(plaintext, password, { previousFile });\n writeFileSync(mdencPath, encrypted);\n gitAdd(repoRoot, [relMdencPath]);\n\n // Belt-and-suspenders: unstage .md if accidentally staged\n if (isFileStaged(repoRoot, relMdPath)) {\n gitRmCached(repoRoot, [relMdPath]);\n }\n\n encryptedCount++;\n } catch (err) {\n process.stderr.write(\n `mdenc: failed to encrypt ${relMdPath}: ${err instanceof Error ? err.message : err}\\n`,\n );\n errorCount++;\n }\n }\n }\n\n if (encryptedCount > 0) {\n process.stderr.write(`mdenc: encrypted ${encryptedCount} file(s)\\n`);\n }\n\n if (errorCount > 0) {\n process.stderr.write(\n `mdenc: ${errorCount} file(s) failed to encrypt. Aborting commit.\\n`,\n );\n process.exit(1);\n }\n\n process.exit(0);\n}\n\n/**\n * Decrypt all .mdenc files in marked directories, then clean up\n * orphaned .md files (those without a corresponding .mdenc).\n * Returns { decrypted, cleaned } counts.\n */\nexport async function decryptAll(): Promise<{ decrypted: number; cleaned: number }> {\n const repoRoot = findGitRoot();\n const password = resolvePassword(repoRoot);\n\n if (!password) {\n process.stderr.write(\n 'mdenc: no password available. Skipping decryption.\\n',\n );\n return { decrypted: 0, cleaned: 0 };\n }\n\n const markedDirs = findMarkedDirs(repoRoot);\n let decrypted = 0;\n\n for (const dir of markedDirs) {\n const mdencFiles = getMdencFilesInDir(dir);\n\n for (const mdencFile of mdencFiles) {\n const mdencPath = join(dir, mdencFile);\n const mdPath = mdencPath.replace(/\\.mdenc$/, '.md');\n const relMdPath = relative(repoRoot, mdPath);\n\n // Overwrite protection: skip if .md is newer than .mdenc\n if (existsSync(mdPath)) {\n const mdMtime = statSync(mdPath).mtimeMs;\n const mdencMtime = statSync(mdencPath).mtimeMs;\n if (mdMtime > mdencMtime) {\n process.stderr.write(\n `mdenc: skipping ${relMdPath} (local .md is newer than .mdenc)\\n`,\n );\n continue;\n }\n }\n\n try {\n const encrypted = readFileSync(mdencPath, 'utf-8');\n const plaintext = await decrypt(encrypted, password);\n writeFileSync(mdPath, plaintext);\n decrypted++;\n } catch (err) {\n process.stderr.write(\n `mdenc: failed to decrypt ${relative(repoRoot, mdencPath)}: ${err instanceof Error ? err.message : err}\\n`,\n );\n }\n }\n }\n\n // Clean up orphaned .md files (no corresponding .mdenc)\n let cleaned = 0;\n for (const dir of markedDirs) {\n const mdFiles = getMdFilesInDir(dir);\n\n for (const mdFile of mdFiles) {\n const mdPath = join(dir, mdFile);\n const mdencPath = mdPath.replace(/\\.md$/, '.mdenc');\n\n if (!existsSync(mdencPath)) {\n const relMdPath = relative(repoRoot, mdPath);\n unlinkSync(mdPath);\n process.stderr.write(`mdenc: removed orphaned ${relMdPath}\\n`);\n cleaned++;\n }\n }\n }\n\n return { decrypted, cleaned };\n}\n\nfunction formatDecryptResult({ decrypted, cleaned }: { decrypted: number; cleaned: number }): string {\n const parts: string[] = [];\n if (decrypted > 0) parts.push(`decrypted ${decrypted} file(s)`);\n if (cleaned > 0) parts.push(`removed ${cleaned} orphan(s)`);\n return parts.length > 0 ? `mdenc: ${parts.join(', ')}\\n` : '';\n}\n\nexport async function postCheckoutHook(): Promise<void> {\n const result = await decryptAll();\n const msg = formatDecryptResult(result);\n if (msg) process.stderr.write(msg);\n process.exit(0);\n}\n\nexport async function postMergeHook(): Promise<void> {\n const result = await decryptAll();\n const msg = formatDecryptResult(result);\n if (msg) process.stderr.write(msg);\n process.exit(0);\n}\n\nexport async function postRewriteHook(): Promise<void> {\n const result = await decryptAll();\n const msg = formatDecryptResult(result);\n if (msg) process.stderr.write(msg);\n process.exit(0);\n}\n","import { hmac } from '@noble/hashes/hmac';\nimport { sha256 } from '@noble/hashes/sha256';\nimport { chunkByParagraph, chunkByFixedSize } from './chunking.js';\nimport { deriveMasterKey, deriveKeys } from './kdf.js';\nimport { encryptChunk, decryptChunk } from './aead.js';\nimport {\n serializeHeader,\n parseHeader,\n authenticateHeader,\n verifyHeader,\n generateSalt,\n generateFileId,\n toBase64,\n fromBase64,\n} from './header.js';\nimport { ChunkingStrategy, DEFAULT_SCRYPT_PARAMS } from './types.js';\nimport type { EncryptOptions, MdencHeader } from './types.js';\nimport { constantTimeEqual, zeroize } from './crypto-utils.js';\n\nexport async function encrypt(\n plaintext: string,\n password: string,\n options?: EncryptOptions,\n): Promise<string> {\n const chunking = options?.chunking ?? ChunkingStrategy.Paragraph;\n const maxChunkSize = options?.maxChunkSize ?? 65536;\n const scryptParams = options?.scrypt ?? DEFAULT_SCRYPT_PARAMS;\n\n // Chunk the plaintext\n let chunks: string[];\n if (chunking === ChunkingStrategy.FixedSize) {\n const fixedSize = options?.fixedChunkSize ?? 4096;\n chunks = chunkByFixedSize(plaintext, fixedSize);\n } else {\n chunks = chunkByParagraph(plaintext, maxChunkSize);\n }\n\n // If previousFile provided, extract salt/fileId/keys from its header to avoid\n // deriving the same master key twice (same password + same salt).\n let salt: Uint8Array;\n let fileId: Uint8Array;\n let masterKey: Uint8Array;\n\n const prev = options?.previousFile\n ? parsePreviousFileHeader(options.previousFile, password)\n : undefined;\n\n if (prev) {\n salt = prev.salt;\n fileId = prev.fileId;\n masterKey = prev.masterKey;\n } else {\n salt = generateSalt();\n fileId = generateFileId();\n masterKey = deriveMasterKey(password, salt, scryptParams);\n }\n\n const { encKey, headerKey, nonceKey } = deriveKeys(masterKey);\n\n try {\n // Build header\n const header: MdencHeader = { version: 'v1', salt, fileId, scrypt: scryptParams };\n const headerLine = serializeHeader(header);\n const headerHmac = authenticateHeader(headerKey, headerLine);\n const headerAuthLine = `hdrauth_b64=${toBase64(headerHmac)}`;\n\n // Encrypt chunks — deterministic encryption handles reuse automatically\n const chunkLines: string[] = [];\n for (const chunkText of chunks) {\n const chunkBytes = new TextEncoder().encode(chunkText);\n const payload = encryptChunk(encKey, nonceKey, chunkBytes, fileId);\n chunkLines.push(toBase64(payload));\n }\n\n // Compute seal HMAC over header + auth + chunk lines\n const sealInput = headerLine + '\\n' + headerAuthLine + '\\n' + chunkLines.join('\\n');\n const sealData = new TextEncoder().encode(sealInput);\n const sealHmac = hmac(sha256, headerKey, sealData);\n const sealLine = `seal_b64=${toBase64(sealHmac)}`;\n\n return [headerLine, headerAuthLine, ...chunkLines, sealLine, ''].join('\\n');\n } finally {\n zeroize(masterKey, encKey, headerKey, nonceKey);\n }\n}\n\nexport async function decrypt(\n fileContent: string,\n password: string,\n): Promise<string> {\n const lines = fileContent.split('\\n');\n\n // Remove trailing empty line if present\n if (lines.length > 0 && lines[lines.length - 1] === '') {\n lines.pop();\n }\n\n if (lines.length < 3) {\n throw new Error('Invalid mdenc file: too few lines');\n }\n\n // Parse header\n const headerLine = lines[0];\n const header = parseHeader(headerLine);\n\n // Parse header auth\n const authLine = lines[1];\n const authMatch = authLine.match(/^hdrauth_b64=([A-Za-z0-9+/=]+)$/);\n if (!authMatch) {\n throw new Error('Invalid mdenc file: missing hdrauth_b64 line');\n }\n const headerHmac = fromBase64(authMatch[1]);\n\n // Derive keys\n const masterKey = deriveMasterKey(password, header.salt, header.scrypt);\n const { encKey, headerKey, nonceKey } = deriveKeys(masterKey);\n\n try {\n // Verify header HMAC\n if (!verifyHeader(headerKey, headerLine, headerHmac)) {\n throw new Error('Header authentication failed (wrong password or tampered header)');\n }\n\n // Collect chunk lines and seal line\n const remaining = lines.slice(2);\n const sealIndex = remaining.findIndex(l => l.startsWith('seal_b64='));\n if (sealIndex < 0) {\n throw new Error('Invalid mdenc file: missing seal');\n }\n\n const chunkLines = remaining.slice(0, sealIndex);\n if (chunkLines.length === 0) {\n throw new Error('Invalid mdenc file: no chunk lines');\n }\n\n // Verify seal HMAC\n const sealMatch = remaining[sealIndex].match(/^seal_b64=([A-Za-z0-9+/=]+)$/);\n if (!sealMatch) throw new Error('Invalid mdenc file: malformed seal line');\n const storedSealHmac = fromBase64(sealMatch[1]);\n\n const sealInput = headerLine + '\\n' + authLine + '\\n' + chunkLines.join('\\n');\n const sealData = new TextEncoder().encode(sealInput);\n const computedSealHmac = hmac(sha256, headerKey, sealData);\n if (!constantTimeEqual(computedSealHmac, storedSealHmac)) {\n throw new Error('Seal verification failed (file tampered or chunks reordered)');\n }\n\n // Decrypt chunks\n const plaintextParts: string[] = [];\n for (const line of chunkLines) {\n const payload = fromBase64(line);\n const decrypted = decryptChunk(encKey, payload, header.fileId);\n plaintextParts.push(new TextDecoder().decode(decrypted));\n }\n\n return plaintextParts.join('');\n } finally {\n zeroize(masterKey, encKey, headerKey, nonceKey);\n }\n}\n\nfunction parsePreviousFileHeader(\n fileContent: string,\n password: string,\n): { salt: Uint8Array; fileId: Uint8Array; masterKey: Uint8Array } | undefined {\n try {\n const lines = fileContent.split('\\n');\n if (lines.length > 0 && lines[lines.length - 1] === '') lines.pop();\n if (lines.length < 3) return undefined;\n\n const headerLine = lines[0];\n const header = parseHeader(headerLine);\n\n // Parse and verify header HMAC before trusting\n const authLine = lines[1];\n const authMatch = authLine.match(/^hdrauth_b64=([A-Za-z0-9+/=]+)$/);\n if (!authMatch) return undefined;\n const headerHmac = fromBase64(authMatch[1]);\n\n const masterKey = deriveMasterKey(password, header.salt, header.scrypt);\n const { headerKey } = deriveKeys(masterKey);\n\n if (!verifyHeader(headerKey, headerLine, headerHmac)) {\n zeroize(masterKey, headerKey);\n return undefined;\n }\n\n zeroize(headerKey);\n // Return masterKey for reuse — same password + same salt produces the same key,\n // so the caller can skip a redundant scrypt derivation.\n return { salt: header.salt, fileId: header.fileId, masterKey };\n } catch {\n return undefined;\n }\n}\n","const DEFAULT_MAX_CHUNK_SIZE = 65536; // 64 KiB\n\nexport function chunkByParagraph(text: string, maxSize = DEFAULT_MAX_CHUNK_SIZE): string[] {\n // Normalize line endings\n const normalized = text.replace(/\\r\\n/g, '\\n');\n\n if (normalized.length === 0) {\n return [''];\n }\n\n // Split on runs of 2+ newlines, attaching each boundary to the preceding chunk\n const chunks: string[] = [];\n const boundary = /\\n{2,}/g;\n let lastEnd = 0;\n let match: RegExpExecArray | null;\n\n while ((match = boundary.exec(normalized)) !== null) {\n // Content up to and including the boundary goes to the preceding chunk\n const chunkEnd = match.index + match[0].length;\n chunks.push(normalized.slice(lastEnd, chunkEnd));\n lastEnd = chunkEnd;\n }\n\n // Remaining content after the last boundary (or the entire string if no boundary)\n if (lastEnd < normalized.length) {\n chunks.push(normalized.slice(lastEnd));\n } else if (chunks.length === 0) {\n // No boundaries found and nothing remaining — shouldn't happen since we checked length > 0\n chunks.push(normalized);\n }\n\n // Split any oversized chunks at byte boundaries\n const result: string[] = [];\n for (const chunk of chunks) {\n if (byteLength(chunk) <= maxSize) {\n result.push(chunk);\n } else {\n result.push(...splitAtByteLimit(chunk, maxSize));\n }\n }\n\n return result;\n}\n\nexport function chunkByFixedSize(text: string, size: number): string[] {\n const normalized = text.replace(/\\r\\n/g, '\\n');\n\n if (normalized.length === 0) {\n return [''];\n }\n\n const bytes = new TextEncoder().encode(normalized);\n if (bytes.length <= size) {\n return [normalized];\n }\n\n const chunks: string[] = [];\n const decoder = new TextDecoder();\n let offset = 0;\n while (offset < bytes.length) {\n const end = Math.min(offset + size, bytes.length);\n // Avoid splitting in the middle of a multi-byte UTF-8 character\n let adjusted = end;\n if (adjusted < bytes.length) {\n while (adjusted > offset && (bytes[adjusted] & 0xc0) === 0x80) {\n adjusted--;\n }\n }\n chunks.push(decoder.decode(bytes.slice(offset, adjusted)));\n offset = adjusted;\n }\n\n return chunks;\n}\n\nfunction byteLength(s: string): number {\n return new TextEncoder().encode(s).length;\n}\n\nfunction splitAtByteLimit(text: string, maxSize: number): string[] {\n const bytes = new TextEncoder().encode(text);\n const decoder = new TextDecoder();\n const parts: string[] = [];\n let offset = 0;\n while (offset < bytes.length) {\n let end = Math.min(offset + maxSize, bytes.length);\n // Avoid splitting multi-byte characters\n if (end < bytes.length) {\n while (end > offset && (bytes[end] & 0xc0) === 0x80) {\n end--;\n }\n }\n parts.push(decoder.decode(bytes.slice(offset, end)));\n offset = end;\n }\n return parts;\n}\n","import { hkdf } from '@noble/hashes/hkdf';\nimport { sha256 } from '@noble/hashes/sha256';\nimport { scrypt } from '@noble/hashes/scrypt';\nimport type { ScryptParams } from './types.js';\nimport { DEFAULT_SCRYPT_PARAMS } from './types.js';\nimport { zeroize } from './crypto-utils.js';\n\nconst ENC_INFO = new TextEncoder().encode('mdenc-v1-enc');\nconst HDR_INFO = new TextEncoder().encode('mdenc-v1-hdr');\nconst NONCE_INFO = new TextEncoder().encode('mdenc-v1-nonce');\n\nexport function normalizePassword(password: string): Uint8Array {\n const normalized = password.normalize('NFKC');\n return new TextEncoder().encode(normalized);\n}\n\nexport function deriveMasterKey(\n password: string,\n salt: Uint8Array,\n params: ScryptParams = DEFAULT_SCRYPT_PARAMS,\n): Uint8Array {\n const passwordBytes = normalizePassword(password);\n try {\n return scrypt(passwordBytes, salt, {\n N: params.N,\n r: params.r,\n p: params.p,\n dkLen: 32,\n });\n } finally {\n zeroize(passwordBytes);\n }\n}\n\nexport function deriveKeys(masterKey: Uint8Array): { encKey: Uint8Array; headerKey: Uint8Array; nonceKey: Uint8Array } {\n const encKey = hkdf(sha256, masterKey, undefined, ENC_INFO, 32);\n const headerKey = hkdf(sha256, masterKey, undefined, HDR_INFO, 32);\n const nonceKey = hkdf(sha256, masterKey, undefined, NONCE_INFO, 32);\n return { encKey, headerKey, nonceKey };\n}\n","export interface ScryptParams {\n N: number; // CPU/memory cost (default 16384 = 2^14, ~16 MiB with r=8)\n r: number; // block size (default 8)\n p: number; // parallelism (default 1)\n}\n\nexport const DEFAULT_SCRYPT_PARAMS: ScryptParams = {\n N: 16384,\n r: 8,\n p: 1,\n};\n\nexport const SCRYPT_BOUNDS = {\n N: { min: 1024, max: 1048576 }, // 2^10 – 2^20\n r: { min: 1, max: 64 },\n p: { min: 1, max: 16 },\n} as const;\n\nexport interface MdencHeader {\n version: 'v1';\n salt: Uint8Array; // 16 bytes\n fileId: Uint8Array; // 16 bytes\n scrypt: ScryptParams;\n}\n\nexport interface MdencChunk {\n payload: Uint8Array; // nonce || ciphertext || tag\n}\n\nexport interface MdencFile {\n header: MdencHeader;\n headerLine: string;\n headerHmac: Uint8Array;\n chunks: MdencChunk[];\n sealHmac: Uint8Array; // file-level HMAC\n}\n\nexport enum ChunkingStrategy {\n Paragraph = 'paragraph',\n FixedSize = 'fixed-size',\n}\n\nexport interface EncryptOptions {\n chunking?: ChunkingStrategy;\n maxChunkSize?: number; // bytes, default 65536 (64 KiB)\n fixedChunkSize?: number; // bytes, for fixed-size chunking\n scrypt?: ScryptParams;\n previousFile?: string; // previous encrypted file content for ciphertext reuse\n}\n\nexport interface DecryptOptions {\n // Reserved for future options\n}\n","export function constantTimeEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) {\n diff |= a[i] ^ b[i];\n }\n return diff === 0;\n}\n\nexport function zeroize(...arrays: Uint8Array[]): void {\n for (const arr of arrays) {\n arr.fill(0);\n }\n}\n","import { xchacha20poly1305 } from '@noble/ciphers/chacha';\nimport { hmac } from '@noble/hashes/hmac';\nimport { sha256 } from '@noble/hashes/sha256';\n\nconst NONCE_LENGTH = 24;\n\nexport function buildAAD(fileId: Uint8Array): Uint8Array {\n const fileIdHex = bytesToHex(fileId);\n const aadString = `mdenc:v1\\n${fileIdHex}`;\n return new TextEncoder().encode(aadString);\n}\n\nexport function deriveNonce(nonceKey: Uint8Array, plaintext: Uint8Array): Uint8Array {\n const full = hmac(sha256, nonceKey, plaintext);\n return full.slice(0, NONCE_LENGTH);\n}\n\nexport function encryptChunk(\n encKey: Uint8Array,\n nonceKey: Uint8Array,\n plaintext: Uint8Array,\n fileId: Uint8Array,\n): Uint8Array {\n const nonce = deriveNonce(nonceKey, plaintext);\n const aad = buildAAD(fileId);\n const cipher = xchacha20poly1305(encKey, nonce, aad);\n const ciphertext = cipher.encrypt(plaintext);\n // Output: nonce || ciphertext || tag (tag is appended by noble)\n const result = new Uint8Array(NONCE_LENGTH + ciphertext.length);\n result.set(nonce, 0);\n result.set(ciphertext, NONCE_LENGTH);\n return result;\n}\n\nexport function decryptChunk(\n encKey: Uint8Array,\n payload: Uint8Array,\n fileId: Uint8Array,\n): Uint8Array {\n if (payload.length < NONCE_LENGTH + 16) {\n throw new Error('Chunk payload too short');\n }\n const nonce = payload.slice(0, NONCE_LENGTH);\n const ciphertext = payload.slice(NONCE_LENGTH);\n const aad = buildAAD(fileId);\n const cipher = xchacha20poly1305(encKey, nonce, aad);\n try {\n return cipher.decrypt(ciphertext);\n } catch {\n throw new Error('Chunk authentication failed');\n }\n}\n\nfunction bytesToHex(bytes: Uint8Array): string {\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += bytes[i].toString(16).padStart(2, '0');\n }\n return hex;\n}\n","import { hmac } from '@noble/hashes/hmac';\nimport { sha256 } from '@noble/hashes/sha256';\nimport { randomBytes } from '@noble/ciphers/webcrypto';\nimport type { MdencHeader, ScryptParams } from './types.js';\nimport { SCRYPT_BOUNDS } from './types.js';\nimport { constantTimeEqual } from './crypto-utils.js';\n\nexport function generateSalt(): Uint8Array {\n return randomBytes(16);\n}\n\nexport function generateFileId(): Uint8Array {\n return randomBytes(16);\n}\n\nexport function serializeHeader(header: MdencHeader): string {\n const saltB64 = toBase64(header.salt);\n const fileIdB64 = toBase64(header.fileId);\n const { N, r, p } = header.scrypt;\n return `mdenc:v1 salt_b64=${saltB64} file_id_b64=${fileIdB64} scrypt=N=${N},r=${r},p=${p}`;\n}\n\nexport function parseHeader(line: string): MdencHeader {\n if (!line.startsWith('mdenc:v1 ')) {\n throw new Error('Invalid header: missing mdenc:v1 prefix');\n }\n\n const saltMatch = line.match(/salt_b64=([A-Za-z0-9+/=]+)/);\n if (!saltMatch) throw new Error('Invalid header: missing salt_b64');\n const salt = fromBase64(saltMatch[1]);\n if (salt.length !== 16) throw new Error('Invalid header: salt must be 16 bytes');\n\n const fileIdMatch = line.match(/file_id_b64=([A-Za-z0-9+/=]+)/);\n if (!fileIdMatch) throw new Error('Invalid header: missing file_id_b64');\n const fileId = fromBase64(fileIdMatch[1]);\n if (fileId.length !== 16) throw new Error('Invalid header: file_id must be 16 bytes');\n\n const scryptMatch = line.match(/scrypt=N=(\\d+),r=(\\d+),p=(\\d+)/);\n if (!scryptMatch) throw new Error('Invalid header: missing scrypt parameters');\n const scryptParams: ScryptParams = {\n N: parseInt(scryptMatch[1], 10),\n r: parseInt(scryptMatch[2], 10),\n p: parseInt(scryptMatch[3], 10),\n };\n\n validateScryptParams(scryptParams);\n\n return { version: 'v1', salt, fileId, scrypt: scryptParams };\n}\n\nexport function validateScryptParams(params: ScryptParams): void {\n const { N, r, p } = SCRYPT_BOUNDS;\n if (params.N < N.min || params.N > N.max) {\n throw new Error(`Invalid scrypt N: ${params.N} (must be ${N.min}–${N.max})`);\n }\n if ((params.N & (params.N - 1)) !== 0) {\n throw new Error(`Invalid scrypt N: ${params.N} (must be a power of 2)`);\n }\n if (params.r < r.min || params.r > r.max) {\n throw new Error(`Invalid scrypt r: ${params.r} (must be ${r.min}–${r.max})`);\n }\n if (params.p < p.min || params.p > p.max) {\n throw new Error(`Invalid scrypt p: ${params.p} (must be ${p.min}–${p.max})`);\n }\n}\n\nexport function authenticateHeader(headerKey: Uint8Array, headerLine: string): Uint8Array {\n const headerBytes = new TextEncoder().encode(headerLine);\n return hmac(sha256, headerKey, headerBytes);\n}\n\nexport function verifyHeader(\n headerKey: Uint8Array,\n headerLine: string,\n hmacBytes: Uint8Array,\n): boolean {\n const computed = authenticateHeader(headerKey, headerLine);\n return constantTimeEqual(computed, hmacBytes);\n}\n\nexport function toBase64(bytes: Uint8Array): string {\n return Buffer.from(bytes).toString('base64');\n}\n\nexport function fromBase64(b64: string): Uint8Array {\n return new Uint8Array(Buffer.from(b64, 'base64'));\n}\n","import { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nconst PASSWORD_FILE = '.mdenc-password';\n\n/**\n * Resolve password for non-interactive use (git hooks).\n * Checks MDENC_PASSWORD env var, then .mdenc-password file.\n * Returns null if neither is available — never prompts on TTY.\n */\nexport function resolvePassword(repoRoot: string): string | null {\n const envPassword = process.env['MDENC_PASSWORD'];\n if (envPassword) return envPassword;\n\n try {\n const content = readFileSync(join(repoRoot, PASSWORD_FILE), 'utf-8').trim();\n if (content.length > 0) return content;\n } catch {\n // File doesn't exist or unreadable\n }\n\n return null;\n}\n","import { execFileSync } from 'node:child_process';\nimport { readdirSync, statSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\n\nconst SKIP_DIRS = new Set(['.git', 'node_modules', '.hg', '.svn']);\nconst MARKER_FILE = '.mdenc.conf';\n\nexport function findGitRoot(): string {\n try {\n return execFileSync('git', ['rev-parse', '--show-toplevel'], {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n } catch {\n throw new Error('Not a git repository');\n }\n}\n\nexport function getHooksDir(): string {\n try {\n const gitDir = execFileSync('git', ['rev-parse', '--git-path', 'hooks'], {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n return resolve(gitDir);\n } catch {\n throw new Error('Could not determine git hooks directory');\n }\n}\n\nexport function findMarkedDirs(repoRoot: string): string[] {\n const results: string[] = [];\n walkForMarker(repoRoot, results);\n return results;\n}\n\nfunction walkForMarker(dir: string, results: string[]): void {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return;\n }\n\n if (entries.includes(MARKER_FILE)) {\n results.push(dir);\n }\n\n for (const entry of entries) {\n if (SKIP_DIRS.has(entry) || entry.startsWith('.')) continue;\n const full = join(dir, entry);\n try {\n if (statSync(full).isDirectory()) {\n walkForMarker(full, results);\n }\n } catch {\n // Skip inaccessible entries\n }\n }\n}\n\nexport function getMdFilesInDir(dir: string): string[] {\n try {\n return readdirSync(dir).filter(\n f => f.endsWith('.md') && statSync(join(dir, f)).isFile(),\n );\n } catch {\n return [];\n }\n}\n\nexport function getMdencFilesInDir(dir: string): string[] {\n try {\n return readdirSync(dir).filter(\n f => f.endsWith('.mdenc') && statSync(join(dir, f)).isFile(),\n );\n } catch {\n return [];\n }\n}\n\nexport function gitAdd(repoRoot: string, files: string[]): void {\n if (files.length === 0) return;\n execFileSync('git', ['add', '--', ...files], {\n cwd: repoRoot,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n}\n\nexport function gitRmCached(repoRoot: string, files: string[]): void {\n if (files.length === 0) return;\n execFileSync('git', ['rm', '--cached', '--ignore-unmatch', '--', ...files], {\n cwd: repoRoot,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n}\n\nexport function isFileStaged(repoRoot: string, file: string): boolean {\n try {\n const output = execFileSync(\n 'git',\n ['diff', '--cached', '--name-only', '--', file],\n { cwd: repoRoot, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] },\n );\n return output.trim().length > 0;\n } catch {\n return false;\n }\n}\n\nexport function isFileTracked(repoRoot: string, file: string): boolean {\n try {\n execFileSync('git', ['ls-files', '--error-unmatch', '--', file], {\n cwd: repoRoot,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return true;\n } catch {\n return false;\n }\n}\n"],"mappings":"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","names":["readFileSync","statSync","join","hmac","sha256","sha256","hmac","sha256","hmac","sha256","hmac","sha256","join","statSync","join","readFileSync"]}
|
package/dist/hooks-7DUHI6MG.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
decryptAll,
|
|
4
|
-
postCheckoutHook,
|
|
5
|
-
postMergeHook,
|
|
6
|
-
postRewriteHook,
|
|
7
|
-
preCommitHook
|
|
8
|
-
} from "./chunk-DQSJGHST.js";
|
|
9
|
-
export {
|
|
10
|
-
decryptAll,
|
|
11
|
-
postCheckoutHook,
|
|
12
|
-
postMergeHook,
|
|
13
|
-
postRewriteHook,
|
|
14
|
-
preCommitHook
|
|
15
|
-
};
|
|
16
|
-
//# sourceMappingURL=hooks-7DUHI6MG.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|