@de-otio/chaoskb-client 0.2.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.
Files changed (355) hide show
  1. package/dist/cli/agent-registry/config-merger.d.ts +28 -0
  2. package/dist/cli/agent-registry/config-merger.d.ts.map +1 -0
  3. package/dist/cli/agent-registry/config-merger.js +90 -0
  4. package/dist/cli/agent-registry/config-merger.js.map +1 -0
  5. package/dist/cli/agent-registry/detector.d.ts +7 -0
  6. package/dist/cli/agent-registry/detector.d.ts.map +1 -0
  7. package/dist/cli/agent-registry/detector.js +100 -0
  8. package/dist/cli/agent-registry/detector.js.map +1 -0
  9. package/dist/cli/agent-registry/index.d.ts +26 -0
  10. package/dist/cli/agent-registry/index.d.ts.map +1 -0
  11. package/dist/cli/agent-registry/index.js +77 -0
  12. package/dist/cli/agent-registry/index.js.map +1 -0
  13. package/dist/cli/agent-registry/path-validator.d.ts +11 -0
  14. package/dist/cli/agent-registry/path-validator.d.ts.map +1 -0
  15. package/dist/cli/agent-registry/path-validator.js +69 -0
  16. package/dist/cli/agent-registry/path-validator.js.map +1 -0
  17. package/dist/cli/agent-registry/registry.json +108 -0
  18. package/dist/cli/agent-registry/types.d.ts +29 -0
  19. package/dist/cli/agent-registry/types.d.ts.map +1 -0
  20. package/dist/cli/agent-registry/types.js +2 -0
  21. package/dist/cli/agent-registry/types.js.map +1 -0
  22. package/dist/cli/bootstrap-lock.d.ts +7 -0
  23. package/dist/cli/bootstrap-lock.d.ts.map +1 -0
  24. package/dist/cli/bootstrap-lock.js +62 -0
  25. package/dist/cli/bootstrap-lock.js.map +1 -0
  26. package/dist/cli/bootstrap.d.ts +23 -0
  27. package/dist/cli/bootstrap.d.ts.map +1 -0
  28. package/dist/cli/bootstrap.js +438 -0
  29. package/dist/cli/bootstrap.js.map +1 -0
  30. package/dist/cli/commands/config.d.ts +13 -0
  31. package/dist/cli/commands/config.d.ts.map +1 -0
  32. package/dist/cli/commands/config.js +244 -0
  33. package/dist/cli/commands/config.js.map +1 -0
  34. package/dist/cli/commands/devices.d.ts +21 -0
  35. package/dist/cli/commands/devices.d.ts.map +1 -0
  36. package/dist/cli/commands/devices.js +229 -0
  37. package/dist/cli/commands/devices.js.map +1 -0
  38. package/dist/cli/commands/export.d.ts +12 -0
  39. package/dist/cli/commands/export.d.ts.map +1 -0
  40. package/dist/cli/commands/export.js +183 -0
  41. package/dist/cli/commands/export.js.map +1 -0
  42. package/dist/cli/commands/import.d.ts +26 -0
  43. package/dist/cli/commands/import.d.ts.map +1 -0
  44. package/dist/cli/commands/import.js +311 -0
  45. package/dist/cli/commands/import.js.map +1 -0
  46. package/dist/cli/commands/kb.d.ts +39 -0
  47. package/dist/cli/commands/kb.d.ts.map +1 -0
  48. package/dist/cli/commands/kb.js +138 -0
  49. package/dist/cli/commands/kb.js.map +1 -0
  50. package/dist/cli/commands/project.d.ts +6 -0
  51. package/dist/cli/commands/project.d.ts.map +1 -0
  52. package/dist/cli/commands/project.js +115 -0
  53. package/dist/cli/commands/project.js.map +1 -0
  54. package/dist/cli/commands/projects.d.ts +33 -0
  55. package/dist/cli/commands/projects.d.ts.map +1 -0
  56. package/dist/cli/commands/projects.js +189 -0
  57. package/dist/cli/commands/projects.js.map +1 -0
  58. package/dist/cli/commands/register.d.ts +8 -0
  59. package/dist/cli/commands/register.d.ts.map +1 -0
  60. package/dist/cli/commands/register.js +146 -0
  61. package/dist/cli/commands/register.js.map +1 -0
  62. package/dist/cli/commands/rotate-key.d.ts +16 -0
  63. package/dist/cli/commands/rotate-key.d.ts.map +1 -0
  64. package/dist/cli/commands/rotate-key.js +197 -0
  65. package/dist/cli/commands/rotate-key.js.map +1 -0
  66. package/dist/cli/commands/setup-sync.d.ts +2 -0
  67. package/dist/cli/commands/setup-sync.d.ts.map +1 -0
  68. package/dist/cli/commands/setup-sync.js +165 -0
  69. package/dist/cli/commands/setup-sync.js.map +1 -0
  70. package/dist/cli/commands/setup.d.ts +12 -0
  71. package/dist/cli/commands/setup.d.ts.map +1 -0
  72. package/dist/cli/commands/setup.js +39 -0
  73. package/dist/cli/commands/setup.js.map +1 -0
  74. package/dist/cli/commands/status.d.ts +5 -0
  75. package/dist/cli/commands/status.d.ts.map +1 -0
  76. package/dist/cli/commands/status.js +96 -0
  77. package/dist/cli/commands/status.js.map +1 -0
  78. package/dist/cli/commands/uninstall.d.ts +4 -0
  79. package/dist/cli/commands/uninstall.d.ts.map +1 -0
  80. package/dist/cli/commands/uninstall.js +85 -0
  81. package/dist/cli/commands/uninstall.js.map +1 -0
  82. package/dist/cli/commands/unregister.d.ts +2 -0
  83. package/dist/cli/commands/unregister.d.ts.map +1 -0
  84. package/dist/cli/commands/unregister.js +46 -0
  85. package/dist/cli/commands/unregister.js.map +1 -0
  86. package/dist/cli/device-metadata.d.ts +15 -0
  87. package/dist/cli/device-metadata.d.ts.map +1 -0
  88. package/dist/cli/device-metadata.js +58 -0
  89. package/dist/cli/device-metadata.js.map +1 -0
  90. package/dist/cli/github.d.ts +38 -0
  91. package/dist/cli/github.d.ts.map +1 -0
  92. package/dist/cli/github.js +159 -0
  93. package/dist/cli/github.js.map +1 -0
  94. package/dist/cli/guide-hashes.json +13 -0
  95. package/dist/cli/index.d.ts +3 -0
  96. package/dist/cli/index.d.ts.map +1 -0
  97. package/dist/cli/index.js +226 -0
  98. package/dist/cli/index.js.map +1 -0
  99. package/dist/cli/mcp-server.d.ts +205 -0
  100. package/dist/cli/mcp-server.d.ts.map +1 -0
  101. package/dist/cli/mcp-server.js +366 -0
  102. package/dist/cli/mcp-server.js.map +1 -0
  103. package/dist/cli/tools/kb-delete.d.ts +10 -0
  104. package/dist/cli/tools/kb-delete.d.ts.map +1 -0
  105. package/dist/cli/tools/kb-delete.js +28 -0
  106. package/dist/cli/tools/kb-delete.js.map +1 -0
  107. package/dist/cli/tools/kb-ingest.d.ts +13 -0
  108. package/dist/cli/tools/kb-ingest.d.ts.map +1 -0
  109. package/dist/cli/tools/kb-ingest.js +72 -0
  110. package/dist/cli/tools/kb-ingest.js.map +1 -0
  111. package/dist/cli/tools/kb-list.d.ts +20 -0
  112. package/dist/cli/tools/kb-list.d.ts.map +1 -0
  113. package/dist/cli/tools/kb-list.js +24 -0
  114. package/dist/cli/tools/kb-list.js.map +1 -0
  115. package/dist/cli/tools/kb-query-shared.d.ts +27 -0
  116. package/dist/cli/tools/kb-query-shared.d.ts.map +1 -0
  117. package/dist/cli/tools/kb-query-shared.js +28 -0
  118. package/dist/cli/tools/kb-query-shared.js.map +1 -0
  119. package/dist/cli/tools/kb-query.d.ts +20 -0
  120. package/dist/cli/tools/kb-query.d.ts.map +1 -0
  121. package/dist/cli/tools/kb-query.js +109 -0
  122. package/dist/cli/tools/kb-query.js.map +1 -0
  123. package/dist/cli/tools/kb-summary.d.ts +29 -0
  124. package/dist/cli/tools/kb-summary.d.ts.map +1 -0
  125. package/dist/cli/tools/kb-summary.js +89 -0
  126. package/dist/cli/tools/kb-summary.js.map +1 -0
  127. package/dist/cli/tools/kb-sync-status.d.ts +7 -0
  128. package/dist/cli/tools/kb-sync-status.d.ts.map +1 -0
  129. package/dist/cli/tools/kb-sync-status.js +48 -0
  130. package/dist/cli/tools/kb-sync-status.js.map +1 -0
  131. package/dist/crypto/aad.d.ts +8 -0
  132. package/dist/crypto/aad.d.ts.map +1 -0
  133. package/dist/crypto/aad.js +11 -0
  134. package/dist/crypto/aad.js.map +1 -0
  135. package/dist/crypto/aead.d.ts +21 -0
  136. package/dist/crypto/aead.d.ts.map +1 -0
  137. package/dist/crypto/aead.js +43 -0
  138. package/dist/crypto/aead.js.map +1 -0
  139. package/dist/crypto/argon2.d.ts +11 -0
  140. package/dist/crypto/argon2.d.ts.map +1 -0
  141. package/dist/crypto/argon2.js +33 -0
  142. package/dist/crypto/argon2.js.map +1 -0
  143. package/dist/crypto/blob-id.d.ts +6 -0
  144. package/dist/crypto/blob-id.d.ts.map +1 -0
  145. package/dist/crypto/blob-id.js +33 -0
  146. package/dist/crypto/blob-id.js.map +1 -0
  147. package/dist/crypto/canonical-json.d.ts +6 -0
  148. package/dist/crypto/canonical-json.d.ts.map +1 -0
  149. package/dist/crypto/canonical-json.js +88 -0
  150. package/dist/crypto/canonical-json.js.map +1 -0
  151. package/dist/crypto/commitment.d.ts +12 -0
  152. package/dist/crypto/commitment.d.ts.map +1 -0
  153. package/dist/crypto/commitment.js +37 -0
  154. package/dist/crypto/commitment.js.map +1 -0
  155. package/dist/crypto/encryption-service.d.ts +19 -0
  156. package/dist/crypto/encryption-service.d.ts.map +1 -0
  157. package/dist/crypto/encryption-service.js +38 -0
  158. package/dist/crypto/encryption-service.js.map +1 -0
  159. package/dist/crypto/envelope-cbor.d.ts +37 -0
  160. package/dist/crypto/envelope-cbor.d.ts.map +1 -0
  161. package/dist/crypto/envelope-cbor.js +124 -0
  162. package/dist/crypto/envelope-cbor.js.map +1 -0
  163. package/dist/crypto/envelope.d.ts +34 -0
  164. package/dist/crypto/envelope.d.ts.map +1 -0
  165. package/dist/crypto/envelope.js +160 -0
  166. package/dist/crypto/envelope.js.map +1 -0
  167. package/dist/crypto/hkdf.d.ts +16 -0
  168. package/dist/crypto/hkdf.d.ts.map +1 -0
  169. package/dist/crypto/hkdf.js +33 -0
  170. package/dist/crypto/hkdf.js.map +1 -0
  171. package/dist/crypto/index.d.ts +15 -0
  172. package/dist/crypto/index.d.ts.map +1 -0
  173. package/dist/crypto/index.js +15 -0
  174. package/dist/crypto/index.js.map +1 -0
  175. package/dist/crypto/invite.d.ts +31 -0
  176. package/dist/crypto/invite.d.ts.map +1 -0
  177. package/dist/crypto/invite.js +137 -0
  178. package/dist/crypto/invite.js.map +1 -0
  179. package/dist/crypto/keyring.d.ts +37 -0
  180. package/dist/crypto/keyring.d.ts.map +1 -0
  181. package/dist/crypto/keyring.js +219 -0
  182. package/dist/crypto/keyring.js.map +1 -0
  183. package/dist/crypto/known-keys.d.ts +34 -0
  184. package/dist/crypto/known-keys.d.ts.map +1 -0
  185. package/dist/crypto/known-keys.js +106 -0
  186. package/dist/crypto/known-keys.js.map +1 -0
  187. package/dist/crypto/project-keys.d.ts +26 -0
  188. package/dist/crypto/project-keys.d.ts.map +1 -0
  189. package/dist/crypto/project-keys.js +69 -0
  190. package/dist/crypto/project-keys.js.map +1 -0
  191. package/dist/crypto/secure-buffer.d.ts +31 -0
  192. package/dist/crypto/secure-buffer.d.ts.map +1 -0
  193. package/dist/crypto/secure-buffer.js +61 -0
  194. package/dist/crypto/secure-buffer.js.map +1 -0
  195. package/dist/crypto/ssh-agent.d.ts +16 -0
  196. package/dist/crypto/ssh-agent.d.ts.map +1 -0
  197. package/dist/crypto/ssh-agent.js +225 -0
  198. package/dist/crypto/ssh-agent.js.map +1 -0
  199. package/dist/crypto/ssh-keys.d.ts +19 -0
  200. package/dist/crypto/ssh-keys.d.ts.map +1 -0
  201. package/dist/crypto/ssh-keys.js +121 -0
  202. package/dist/crypto/ssh-keys.js.map +1 -0
  203. package/dist/crypto/tiers/enhanced.d.ts +25 -0
  204. package/dist/crypto/tiers/enhanced.d.ts.map +1 -0
  205. package/dist/crypto/tiers/enhanced.js +56 -0
  206. package/dist/crypto/tiers/enhanced.js.map +1 -0
  207. package/dist/crypto/tiers/maximum.d.ts +19 -0
  208. package/dist/crypto/tiers/maximum.d.ts.map +1 -0
  209. package/dist/crypto/tiers/maximum.js +25 -0
  210. package/dist/crypto/tiers/maximum.js.map +1 -0
  211. package/dist/crypto/tiers/standard.d.ts +27 -0
  212. package/dist/crypto/tiers/standard.d.ts.map +1 -0
  213. package/dist/crypto/tiers/standard.js +147 -0
  214. package/dist/crypto/tiers/standard.js.map +1 -0
  215. package/dist/crypto/types.d.ts +169 -0
  216. package/dist/crypto/types.d.ts.map +1 -0
  217. package/dist/crypto/types.js +11 -0
  218. package/dist/crypto/types.js.map +1 -0
  219. package/dist/pipeline/chunker.d.ts +27 -0
  220. package/dist/pipeline/chunker.d.ts.map +1 -0
  221. package/dist/pipeline/chunker.js +96 -0
  222. package/dist/pipeline/chunker.js.map +1 -0
  223. package/dist/pipeline/content-pipeline.d.ts +24 -0
  224. package/dist/pipeline/content-pipeline.d.ts.map +1 -0
  225. package/dist/pipeline/content-pipeline.js +49 -0
  226. package/dist/pipeline/content-pipeline.js.map +1 -0
  227. package/dist/pipeline/embedder.d.ts +49 -0
  228. package/dist/pipeline/embedder.d.ts.map +1 -0
  229. package/dist/pipeline/embedder.js +195 -0
  230. package/dist/pipeline/embedder.js.map +1 -0
  231. package/dist/pipeline/extract.d.ts +17 -0
  232. package/dist/pipeline/extract.d.ts.map +1 -0
  233. package/dist/pipeline/extract.js +70 -0
  234. package/dist/pipeline/extract.js.map +1 -0
  235. package/dist/pipeline/fetch.d.ts +26 -0
  236. package/dist/pipeline/fetch.d.ts.map +1 -0
  237. package/dist/pipeline/fetch.js +91 -0
  238. package/dist/pipeline/fetch.js.map +1 -0
  239. package/dist/pipeline/index.d.ts +10 -0
  240. package/dist/pipeline/index.d.ts.map +1 -0
  241. package/dist/pipeline/index.js +10 -0
  242. package/dist/pipeline/index.js.map +1 -0
  243. package/dist/pipeline/model-manager.d.ts +57 -0
  244. package/dist/pipeline/model-manager.d.ts.map +1 -0
  245. package/dist/pipeline/model-manager.js +234 -0
  246. package/dist/pipeline/model-manager.js.map +1 -0
  247. package/dist/pipeline/search.d.ts +37 -0
  248. package/dist/pipeline/search.d.ts.map +1 -0
  249. package/dist/pipeline/search.js +65 -0
  250. package/dist/pipeline/search.js.map +1 -0
  251. package/dist/pipeline/tokenizer.d.ts +29 -0
  252. package/dist/pipeline/tokenizer.d.ts.map +1 -0
  253. package/dist/pipeline/tokenizer.js +54 -0
  254. package/dist/pipeline/tokenizer.js.map +1 -0
  255. package/dist/pipeline/types.d.ts +86 -0
  256. package/dist/pipeline/types.d.ts.map +1 -0
  257. package/dist/pipeline/types.js +2 -0
  258. package/dist/pipeline/types.js.map +1 -0
  259. package/dist/pipeline/wordpiece-tokenizer.d.ts +60 -0
  260. package/dist/pipeline/wordpiece-tokenizer.d.ts.map +1 -0
  261. package/dist/pipeline/wordpiece-tokenizer.js +251 -0
  262. package/dist/pipeline/wordpiece-tokenizer.js.map +1 -0
  263. package/dist/storage/chunk-repo.d.ts +29 -0
  264. package/dist/storage/chunk-repo.d.ts.map +1 -0
  265. package/dist/storage/chunk-repo.js +115 -0
  266. package/dist/storage/chunk-repo.js.map +1 -0
  267. package/dist/storage/database-manager.d.ts +17 -0
  268. package/dist/storage/database-manager.d.ts.map +1 -0
  269. package/dist/storage/database-manager.js +100 -0
  270. package/dist/storage/database-manager.js.map +1 -0
  271. package/dist/storage/database.d.ts +10 -0
  272. package/dist/storage/database.d.ts.map +1 -0
  273. package/dist/storage/database.js +34 -0
  274. package/dist/storage/database.js.map +1 -0
  275. package/dist/storage/embedding-index.d.ts +22 -0
  276. package/dist/storage/embedding-index.d.ts.map +1 -0
  277. package/dist/storage/embedding-index.js +78 -0
  278. package/dist/storage/embedding-index.js.map +1 -0
  279. package/dist/storage/index.d.ts +10 -0
  280. package/dist/storage/index.d.ts.map +1 -0
  281. package/dist/storage/index.js +10 -0
  282. package/dist/storage/index.js.map +1 -0
  283. package/dist/storage/kb-database.d.ts +11 -0
  284. package/dist/storage/kb-database.d.ts.map +1 -0
  285. package/dist/storage/kb-database.js +24 -0
  286. package/dist/storage/kb-database.js.map +1 -0
  287. package/dist/storage/schema.d.ts +6 -0
  288. package/dist/storage/schema.d.ts.map +1 -0
  289. package/dist/storage/schema.js +122 -0
  290. package/dist/storage/schema.js.map +1 -0
  291. package/dist/storage/source-repo.d.ts +20 -0
  292. package/dist/storage/source-repo.d.ts.map +1 -0
  293. package/dist/storage/source-repo.js +120 -0
  294. package/dist/storage/source-repo.js.map +1 -0
  295. package/dist/storage/sync-status-repo.d.ts +15 -0
  296. package/dist/storage/sync-status-repo.d.ts.map +1 -0
  297. package/dist/storage/sync-status-repo.js +40 -0
  298. package/dist/storage/sync-status-repo.js.map +1 -0
  299. package/dist/storage/types.d.ts +139 -0
  300. package/dist/storage/types.d.ts.map +1 -0
  301. package/dist/storage/types.js +9 -0
  302. package/dist/storage/types.js.map +1 -0
  303. package/dist/sync/canary.d.ts +14 -0
  304. package/dist/sync/canary.d.ts.map +1 -0
  305. package/dist/sync/canary.js +53 -0
  306. package/dist/sync/canary.js.map +1 -0
  307. package/dist/sync/full-sync.d.ts +16 -0
  308. package/dist/sync/full-sync.d.ts.map +1 -0
  309. package/dist/sync/full-sync.js +91 -0
  310. package/dist/sync/full-sync.js.map +1 -0
  311. package/dist/sync/http-client.d.ts +28 -0
  312. package/dist/sync/http-client.d.ts.map +1 -0
  313. package/dist/sync/http-client.js +90 -0
  314. package/dist/sync/http-client.js.map +1 -0
  315. package/dist/sync/incremental-sync.d.ts +17 -0
  316. package/dist/sync/incremental-sync.d.ts.map +1 -0
  317. package/dist/sync/incremental-sync.js +155 -0
  318. package/dist/sync/incremental-sync.js.map +1 -0
  319. package/dist/sync/index.d.ts +12 -0
  320. package/dist/sync/index.d.ts.map +1 -0
  321. package/dist/sync/index.js +12 -0
  322. package/dist/sync/index.js.map +1 -0
  323. package/dist/sync/quota.d.ts +17 -0
  324. package/dist/sync/quota.d.ts.map +1 -0
  325. package/dist/sync/quota.js +48 -0
  326. package/dist/sync/quota.js.map +1 -0
  327. package/dist/sync/sequence.d.ts +21 -0
  328. package/dist/sync/sequence.d.ts.map +1 -0
  329. package/dist/sync/sequence.js +49 -0
  330. package/dist/sync/sequence.js.map +1 -0
  331. package/dist/sync/ssh-signer.d.ts +59 -0
  332. package/dist/sync/ssh-signer.d.ts.map +1 -0
  333. package/dist/sync/ssh-signer.js +241 -0
  334. package/dist/sync/ssh-signer.js.map +1 -0
  335. package/dist/sync/sync-service.d.ts +48 -0
  336. package/dist/sync/sync-service.d.ts.map +1 -0
  337. package/dist/sync/sync-service.js +116 -0
  338. package/dist/sync/sync-service.js.map +1 -0
  339. package/dist/sync/types.d.ts +106 -0
  340. package/dist/sync/types.d.ts.map +1 -0
  341. package/dist/sync/types.js +2 -0
  342. package/dist/sync/types.js.map +1 -0
  343. package/dist/sync/upload-queue.d.ts +40 -0
  344. package/dist/sync/upload-queue.d.ts.map +1 -0
  345. package/dist/sync/upload-queue.js +148 -0
  346. package/dist/sync/upload-queue.js.map +1 -0
  347. package/dist/sync/verification.d.ts +17 -0
  348. package/dist/sync/verification.d.ts.map +1 -0
  349. package/dist/sync/verification.js +25 -0
  350. package/dist/sync/verification.js.map +1 -0
  351. package/dist/vitest.config.d.ts +3 -0
  352. package/dist/vitest.config.d.ts.map +1 -0
  353. package/dist/vitest.config.js +16 -0
  354. package/dist/vitest.config.js.map +1 -0
  355. package/package.json +68 -0
@@ -0,0 +1,106 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import * as os from 'node:os';
4
+ function getKnownKeysPath() {
5
+ return path.join(os.homedir(), '.chaoskb', 'known_keys.json');
6
+ }
7
+ /**
8
+ * Trust on First Use (TOFU) key pinning for invite recipients.
9
+ *
10
+ * When we first see a recipient's public key (from GitHub, GitLab, or direct),
11
+ * we pin it. On subsequent invites, we check if the key has changed.
12
+ * A key mismatch triggers a warning; a conflict with an independent source
13
+ * is a hard block.
14
+ */
15
+ function loadStore() {
16
+ try {
17
+ return JSON.parse(fs.readFileSync(getKnownKeysPath(), 'utf-8'));
18
+ }
19
+ catch {
20
+ return {};
21
+ }
22
+ }
23
+ function saveStore(store) {
24
+ const dir = path.dirname(getKnownKeysPath());
25
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
26
+ fs.writeFileSync(getKnownKeysPath(), JSON.stringify(store, null, 2), { mode: 0o600 });
27
+ }
28
+ /**
29
+ * Pin a key for an identifier (e.g., "github:alice").
30
+ * Throws if the identifier is already pinned with a different fingerprint.
31
+ */
32
+ export function pinKey(identifier, fingerprint, publicKey, source) {
33
+ const store = loadStore();
34
+ const existing = store[identifier];
35
+ if (existing && existing.fingerprint !== fingerprint) {
36
+ throw new KeyMismatchError(identifier, existing.fingerprint, fingerprint, existing.source, source);
37
+ }
38
+ if (existing && existing.fingerprint === fingerprint) {
39
+ // Same key — update verifiedAt
40
+ existing.verifiedAt = new Date().toISOString();
41
+ saveStore(store);
42
+ return;
43
+ }
44
+ // New key — pin it
45
+ store[identifier] = {
46
+ fingerprint,
47
+ publicKey,
48
+ source,
49
+ firstSeen: new Date().toISOString(),
50
+ verifiedAt: new Date().toISOString(),
51
+ };
52
+ saveStore(store);
53
+ }
54
+ /**
55
+ * Get a pinned key by identifier.
56
+ */
57
+ export function getPinnedKey(identifier) {
58
+ const store = loadStore();
59
+ return store[identifier] ?? null;
60
+ }
61
+ /**
62
+ * Check a key against the pin store.
63
+ */
64
+ export function checkKeyPin(identifier, fingerprint) {
65
+ const store = loadStore();
66
+ const existing = store[identifier];
67
+ if (!existing)
68
+ return 'new';
69
+ if (existing.fingerprint === fingerprint)
70
+ return 'match';
71
+ return 'mismatch';
72
+ }
73
+ /**
74
+ * Update a pinned key after verified rotation (e.g., new key confirmed on GitHub).
75
+ */
76
+ export function updatePinnedKey(identifier, fingerprint, publicKey, source) {
77
+ const store = loadStore();
78
+ store[identifier] = {
79
+ fingerprint,
80
+ publicKey,
81
+ source,
82
+ firstSeen: store[identifier]?.firstSeen ?? new Date().toISOString(),
83
+ verifiedAt: new Date().toISOString(),
84
+ };
85
+ saveStore(store);
86
+ }
87
+ export class KeyMismatchError extends Error {
88
+ identifier;
89
+ pinnedFingerprint;
90
+ newFingerprint;
91
+ pinnedSource;
92
+ newSource;
93
+ constructor(identifier, pinnedFingerprint, newFingerprint, pinnedSource, newSource) {
94
+ super(`Key mismatch for ${identifier}:\n` +
95
+ ` Pinned: ${pinnedFingerprint} (source: ${pinnedSource})\n` +
96
+ ` Received: ${newFingerprint} (source: ${newSource})\n` +
97
+ `This may indicate a compromised key source. The operation was blocked.`);
98
+ this.identifier = identifier;
99
+ this.pinnedFingerprint = pinnedFingerprint;
100
+ this.newFingerprint = newFingerprint;
101
+ this.pinnedSource = pinnedSource;
102
+ this.newSource = newSource;
103
+ this.name = 'KeyMismatchError';
104
+ }
105
+ }
106
+ //# sourceMappingURL=known-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"known-keys.js","sourceRoot":"","sources":["../../crypto/known-keys.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { ISecureBuffer } from './types.js';
2
+ /**
3
+ * Create a new random project key and wrap it with the personal master key.
4
+ *
5
+ * Uses HKDF to derive a wrapping key from the master key, then encrypts
6
+ * the project key with XChaCha20-Poly1305. AAD can include a project name
7
+ * for binding.
8
+ *
9
+ * @param personalMasterKey - The user's personal master key
10
+ * @param projectName - Optional project name for AAD binding
11
+ * @returns The project key (SecureBuffer) and the wrapped (encrypted) form
12
+ */
13
+ export declare function createProjectKey(personalMasterKey: ISecureBuffer, projectName?: string): {
14
+ projectKey: ISecureBuffer;
15
+ wrappedKey: Uint8Array;
16
+ };
17
+ /**
18
+ * Unwrap a project key using the personal master key.
19
+ *
20
+ * @param wrappedKey - The wrapped project key (nonce || ciphertext || tag)
21
+ * @param personalMasterKey - The user's personal master key
22
+ * @param projectName - Optional project name for AAD binding (must match what was used during wrapping)
23
+ * @returns The unwrapped project key as a SecureBuffer
24
+ */
25
+ export declare function unwrapProjectKey(wrappedKey: Uint8Array, personalMasterKey: ISecureBuffer, projectName?: string): ISecureBuffer;
26
+ //# sourceMappingURL=project-keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-keys.d.ts","sourceRoot":"","sources":["../../crypto/project-keys.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAKhD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,iBAAiB,EAAE,aAAa,EAChC,WAAW,CAAC,EAAE,MAAM,GACnB;IAAE,UAAU,EAAE,aAAa,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,CA8BvD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,UAAU,EACtB,iBAAiB,EAAE,aAAa,EAChC,WAAW,CAAC,EAAE,MAAM,GACnB,aAAa,CA+Bf"}
@@ -0,0 +1,69 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { aeadEncrypt, aeadDecrypt } from './aead.js';
3
+ import { deriveKey } from './hkdf.js';
4
+ import { SecureBuffer } from './secure-buffer.js';
5
+ const PROJECT_KEY_LENGTH = 32;
6
+ const WRAP_INFO = 'chaoskb-project-wrap';
7
+ /**
8
+ * Create a new random project key and wrap it with the personal master key.
9
+ *
10
+ * Uses HKDF to derive a wrapping key from the master key, then encrypts
11
+ * the project key with XChaCha20-Poly1305. AAD can include a project name
12
+ * for binding.
13
+ *
14
+ * @param personalMasterKey - The user's personal master key
15
+ * @param projectName - Optional project name for AAD binding
16
+ * @returns The project key (SecureBuffer) and the wrapped (encrypted) form
17
+ */
18
+ export function createProjectKey(personalMasterKey, projectName) {
19
+ // Generate random 32-byte project key
20
+ const projectKeyBytes = randomBytes(PROJECT_KEY_LENGTH);
21
+ // Derive a wrapping key via HKDF
22
+ const wrappingKey = deriveKey(new Uint8Array(personalMasterKey.buffer), WRAP_INFO);
23
+ // AAD: project name if available, otherwise empty
24
+ const aad = projectName
25
+ ? new TextEncoder().encode(projectName)
26
+ : new Uint8Array(0);
27
+ // Encrypt project key with XChaCha20-Poly1305
28
+ const { nonce, ciphertext, tag } = aeadEncrypt(wrappingKey, projectKeyBytes, aad);
29
+ // Zero wrapping key and plaintext project key bytes
30
+ wrappingKey.fill(0);
31
+ // Serialize: nonce(24) || ciphertext || tag(16)
32
+ const wrappedKey = new Uint8Array(nonce.length + ciphertext.length + tag.length);
33
+ wrappedKey.set(nonce, 0);
34
+ wrappedKey.set(ciphertext, nonce.length);
35
+ wrappedKey.set(tag, nonce.length + ciphertext.length);
36
+ const projectKey = SecureBuffer.from(projectKeyBytes);
37
+ return { projectKey, wrappedKey };
38
+ }
39
+ /**
40
+ * Unwrap a project key using the personal master key.
41
+ *
42
+ * @param wrappedKey - The wrapped project key (nonce || ciphertext || tag)
43
+ * @param personalMasterKey - The user's personal master key
44
+ * @param projectName - Optional project name for AAD binding (must match what was used during wrapping)
45
+ * @returns The unwrapped project key as a SecureBuffer
46
+ */
47
+ export function unwrapProjectKey(wrappedKey, personalMasterKey, projectName) {
48
+ const NONCE_SIZE = 24;
49
+ const TAG_SIZE = 16;
50
+ if (wrappedKey.length < NONCE_SIZE + TAG_SIZE + 1) {
51
+ throw new Error('Wrapped key is too short');
52
+ }
53
+ // Derive the same wrapping key
54
+ const wrappingKey = deriveKey(new Uint8Array(personalMasterKey.buffer), WRAP_INFO);
55
+ // Split wrapped key into nonce, ciphertext, tag
56
+ const nonce = wrappedKey.slice(0, NONCE_SIZE);
57
+ const ciphertext = wrappedKey.slice(NONCE_SIZE, wrappedKey.length - TAG_SIZE);
58
+ const tag = wrappedKey.slice(wrappedKey.length - TAG_SIZE);
59
+ // AAD: project name if available, otherwise empty
60
+ const aad = projectName
61
+ ? new TextEncoder().encode(projectName)
62
+ : new Uint8Array(0);
63
+ // Decrypt
64
+ const projectKeyBytes = aeadDecrypt(wrappingKey, nonce, ciphertext, tag, aad);
65
+ // Zero wrapping key
66
+ wrappingKey.fill(0);
67
+ return SecureBuffer.from(Buffer.from(projectKeyBytes));
68
+ }
69
+ //# sourceMappingURL=project-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-keys.js","sourceRoot":"","sources":["../../crypto/project-keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAC9B,MAAM,SAAS,GAAG,sBAAsB,CAAC;AAEzC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAC9B,iBAAgC,EAChC,WAAoB;IAEpB,sCAAsC;IACtC,MAAM,eAAe,GAAG,WAAW,CAAC,kBAAkB,CAAC,CAAC;IAExD,iCAAiC;IACjC,MAAM,WAAW,GAAG,SAAS,CAC3B,IAAI,UAAU,CAAC,iBAAiB,CAAC,MAAM,CAAC,EACxC,SAAS,CACV,CAAC;IAEF,kDAAkD;IAClD,MAAM,GAAG,GAAG,WAAW;QACrB,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC;QACvC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IAEtB,8CAA8C;IAC9C,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,WAAW,CAAC,WAAW,EAAE,eAAe,EAAE,GAAG,CAAC,CAAC;IAElF,oDAAoD;IACpD,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAEpB,gDAAgD;IAChD,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IACjF,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACzB,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACzC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAEtD,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAEtD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;AACpC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,UAAsB,EACtB,iBAAgC,EAChC,WAAoB;IAEpB,MAAM,UAAU,GAAG,EAAE,CAAC;IACtB,MAAM,QAAQ,GAAG,EAAE,CAAC;IAEpB,IAAI,UAAU,CAAC,MAAM,GAAG,UAAU,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9C,CAAC;IAED,+BAA+B;IAC/B,MAAM,WAAW,GAAG,SAAS,CAC3B,IAAI,UAAU,CAAC,iBAAiB,CAAC,MAAM,CAAC,EACxC,SAAS,CACV,CAAC;IAEF,gDAAgD;IAChD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,UAAU,EAAE,UAAU,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC;IAC9E,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC;IAE3D,kDAAkD;IAClD,MAAM,GAAG,GAAG,WAAW;QACrB,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC;QACvC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IAEtB,UAAU;IACV,MAAM,eAAe,GAAG,WAAW,CAAC,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAE9E,oBAAoB;IACpB,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAEpB,OAAO,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;AACzD,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { ISecureBuffer } from './types.js';
2
+ /**
3
+ * Memory-locked buffer for sensitive key material.
4
+ * Uses sodium_malloc (mlock'd pages) and sodium_memzero on dispose.
5
+ */
6
+ export declare class SecureBuffer implements ISecureBuffer {
7
+ private _buffer;
8
+ private _disposed;
9
+ private constructor();
10
+ /** Read the buffer contents. Throws if disposed. */
11
+ get buffer(): Buffer;
12
+ /** Byte length of the buffer. */
13
+ get length(): number;
14
+ /** Whether the buffer has been zeroed and disposed. */
15
+ get isDisposed(): boolean;
16
+ /**
17
+ * Zero the buffer contents and mark as disposed.
18
+ * Safe to call multiple times (idempotent).
19
+ */
20
+ dispose(): void;
21
+ /** Support `using` keyword (TC39 Explicit Resource Management). */
22
+ [Symbol.dispose](): void;
23
+ /**
24
+ * Copy data into a new SecureBuffer and zero the source.
25
+ * The source buffer is zeroed after copying regardless of type.
26
+ */
27
+ static from(data: Buffer | Uint8Array): SecureBuffer;
28
+ /** Allocate a new zeroed SecureBuffer of the given length. */
29
+ static alloc(length: number): SecureBuffer;
30
+ }
31
+ //# sourceMappingURL=secure-buffer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secure-buffer.d.ts","sourceRoot":"","sources":["../../crypto/secure-buffer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;GAGG;AACH,qBAAa,YAAa,YAAW,aAAa;IAChD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO;IAIP,oDAAoD;IACpD,IAAI,MAAM,IAAI,MAAM,CAKnB;IAED,iCAAiC;IACjC,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,uDAAuD;IACvD,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;;OAGG;IACH,OAAO,IAAI,IAAI;IAQf,mEAAmE;IACnE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI;IAIxB;;;OAGG;IACH,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,YAAY;IASpD,8DAA8D;IAC9D,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY;CAK3C"}
@@ -0,0 +1,61 @@
1
+ import sodium from 'sodium-native';
2
+ /**
3
+ * Memory-locked buffer for sensitive key material.
4
+ * Uses sodium_malloc (mlock'd pages) and sodium_memzero on dispose.
5
+ */
6
+ export class SecureBuffer {
7
+ _buffer;
8
+ _disposed = false;
9
+ constructor(length) {
10
+ this._buffer = sodium.sodium_malloc(length);
11
+ }
12
+ /** Read the buffer contents. Throws if disposed. */
13
+ get buffer() {
14
+ if (this._disposed) {
15
+ throw new Error('SecureBuffer has been disposed');
16
+ }
17
+ return this._buffer;
18
+ }
19
+ /** Byte length of the buffer. */
20
+ get length() {
21
+ return this._buffer.byteLength;
22
+ }
23
+ /** Whether the buffer has been zeroed and disposed. */
24
+ get isDisposed() {
25
+ return this._disposed;
26
+ }
27
+ /**
28
+ * Zero the buffer contents and mark as disposed.
29
+ * Safe to call multiple times (idempotent).
30
+ */
31
+ dispose() {
32
+ if (this._disposed) {
33
+ return;
34
+ }
35
+ sodium.sodium_memzero(this._buffer);
36
+ this._disposed = true;
37
+ }
38
+ /** Support `using` keyword (TC39 Explicit Resource Management). */
39
+ [Symbol.dispose]() {
40
+ this.dispose();
41
+ }
42
+ /**
43
+ * Copy data into a new SecureBuffer and zero the source.
44
+ * The source buffer is zeroed after copying regardless of type.
45
+ */
46
+ static from(data) {
47
+ const sb = new SecureBuffer(data.byteLength);
48
+ const buf = Buffer.isBuffer(data) ? data : Buffer.from(data.buffer, data.byteOffset, data.byteLength);
49
+ buf.copy(sb._buffer);
50
+ // Zero the source
51
+ sodium.sodium_memzero(buf);
52
+ return sb;
53
+ }
54
+ /** Allocate a new zeroed SecureBuffer of the given length. */
55
+ static alloc(length) {
56
+ const sb = new SecureBuffer(length);
57
+ sodium.sodium_memzero(sb._buffer);
58
+ return sb;
59
+ }
60
+ }
61
+ //# sourceMappingURL=secure-buffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secure-buffer.js","sourceRoot":"","sources":["../../crypto/secure-buffer.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,eAAe,CAAC;AAInC;;;GAGG;AACH,MAAM,OAAO,YAAY;IACf,OAAO,CAAS;IAChB,SAAS,GAAG,KAAK,CAAC;IAE1B,YAAoB,MAAc;QAChC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC;IAED,oDAAoD;IACpD,IAAI,MAAM;QACR,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,iCAAiC;IACjC,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;IACjC,CAAC;IAED,uDAAuD;IACvD,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED;;;OAGG;IACH,OAAO;QACL,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,OAAO;QACT,CAAC;QACD,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,mEAAmE;IACnE,CAAC,MAAM,CAAC,OAAO,CAAC;QACd,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,IAAI,CAAC,IAAyB;QACnC,MAAM,EAAE,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACtG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;QACrB,kBAAkB;QAClB,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;QAC3B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,8DAA8D;IAC9D,MAAM,CAAC,KAAK,CAAC,MAAc;QACzB,MAAM,EAAE,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;QAClC,OAAO,EAAE,CAAC;IACZ,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ import type { SSHKeyInfo } from './types.js';
2
+ /**
3
+ * List all keys available in the SSH agent.
4
+ */
5
+ export declare function listSSHAgentKeys(): Promise<SSHKeyInfo[]>;
6
+ /**
7
+ * Sign data using a key available in the SSH agent.
8
+ * Returns the raw signature bytes (Ed25519: 64 bytes, RSA: variable).
9
+ */
10
+ export declare function signWithSSHAgent(data: Uint8Array, publicKeyBlob: Uint8Array): Promise<Uint8Array>;
11
+ /**
12
+ * Sign data using a private key file directly.
13
+ * Supports OpenSSH private key format.
14
+ */
15
+ export declare function signWithKeyFile(data: Uint8Array, keyPath: string, passphrase?: string): Promise<Uint8Array>;
16
+ //# sourceMappingURL=ssh-agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-agent.d.ts","sourceRoot":"","sources":["../../crypto/ssh-agent.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,YAAY,CAAC;AA4GzD;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CA8E9D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,UAAU,EAChB,aAAa,EAAE,UAAU,GACxB,OAAO,CAAC,UAAU,CAAC,CAoCrB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,CAAC,CAuBrB"}
@@ -0,0 +1,225 @@
1
+ import * as net from 'node:net';
2
+ import * as fs from 'node:fs';
3
+ import * as crypto from 'node:crypto';
4
+ // SSH agent protocol constants
5
+ const SSH2_AGENTC_REQUEST_IDENTITIES = 11;
6
+ const SSH2_AGENT_IDENTITIES_ANSWER = 12;
7
+ const SSH_AGENTC_SIGN_REQUEST = 13;
8
+ const SSH_AGENT_SIGN_RESPONSE = 14;
9
+ const SSH_AGENT_FAILURE = 5;
10
+ // Signature flags
11
+ const SSH_AGENT_FLAG_ED25519 = 0; // no special flags for ed25519
12
+ /**
13
+ * Connect to the SSH agent and send a message, returning the response.
14
+ */
15
+ function agentRequest(message) {
16
+ return new Promise((resolve, reject) => {
17
+ const socketPath = process.env['SSH_AUTH_SOCK'];
18
+ if (!socketPath) {
19
+ reject(new Error('SSH_AUTH_SOCK environment variable is not set'));
20
+ return;
21
+ }
22
+ const client = net.createConnection(socketPath);
23
+ const chunks = [];
24
+ let expectedLength = -1;
25
+ client.on('connect', () => {
26
+ // Send message with 4-byte length prefix
27
+ const lengthPrefix = Buffer.alloc(4);
28
+ lengthPrefix.writeUInt32BE(message.length, 0);
29
+ client.write(Buffer.concat([lengthPrefix, message]));
30
+ });
31
+ client.on('data', (data) => {
32
+ chunks.push(data);
33
+ const combined = Buffer.concat(chunks);
34
+ // Read the response length from the first 4 bytes
35
+ if (expectedLength === -1 && combined.length >= 4) {
36
+ expectedLength = combined.readUInt32BE(0);
37
+ }
38
+ // Check if we have the full response
39
+ if (expectedLength !== -1 && combined.length >= expectedLength + 4) {
40
+ client.end();
41
+ resolve(combined.subarray(4, 4 + expectedLength));
42
+ }
43
+ });
44
+ client.on('error', (err) => {
45
+ reject(new Error(`SSH agent connection error: ${err.message}`));
46
+ });
47
+ client.on('end', () => {
48
+ const combined = Buffer.concat(chunks);
49
+ if (combined.length >= 4) {
50
+ const len = combined.readUInt32BE(0);
51
+ resolve(combined.subarray(4, 4 + len));
52
+ }
53
+ else {
54
+ reject(new Error('SSH agent returned empty response'));
55
+ }
56
+ });
57
+ // Timeout after 10 seconds
58
+ client.setTimeout(10_000, () => {
59
+ client.destroy();
60
+ reject(new Error('SSH agent connection timed out'));
61
+ });
62
+ });
63
+ }
64
+ /**
65
+ * Write a string (length-prefixed bytes) into a buffer at an offset.
66
+ * Returns new offset.
67
+ */
68
+ function writeString(buf, data, offset) {
69
+ buf.writeUInt32BE(data.length, offset);
70
+ offset += 4;
71
+ Buffer.from(data).copy(buf, offset);
72
+ return offset + data.length;
73
+ }
74
+ /**
75
+ * Read a length-prefixed string from a buffer at offset.
76
+ * Returns [data, newOffset].
77
+ */
78
+ function readString(buf, offset) {
79
+ if (offset + 4 > buf.length) {
80
+ throw new Error('Unexpected end of SSH agent response reading string length');
81
+ }
82
+ const len = buf.readUInt32BE(offset);
83
+ offset += 4;
84
+ if (offset + len > buf.length) {
85
+ throw new Error('Unexpected end of SSH agent response reading string data');
86
+ }
87
+ return [buf.subarray(offset, offset + len), offset + len];
88
+ }
89
+ /**
90
+ * Determine SSH key type from a type string.
91
+ */
92
+ function parseKeyType(typeStr) {
93
+ if (typeStr === 'ssh-ed25519')
94
+ return 'ed25519';
95
+ if (typeStr === 'ssh-rsa')
96
+ return 'rsa';
97
+ return null;
98
+ }
99
+ /**
100
+ * List all keys available in the SSH agent.
101
+ */
102
+ export async function listSSHAgentKeys() {
103
+ const request = Buffer.alloc(1);
104
+ request[0] = SSH2_AGENTC_REQUEST_IDENTITIES;
105
+ const response = await agentRequest(request);
106
+ if (response[0] === SSH_AGENT_FAILURE) {
107
+ throw new Error('SSH agent returned failure');
108
+ }
109
+ if (response[0] !== SSH2_AGENT_IDENTITIES_ANSWER) {
110
+ throw new Error(`Unexpected SSH agent response type: ${response[0]}`);
111
+ }
112
+ let offset = 1;
113
+ if (offset + 4 > response.length) {
114
+ throw new Error('Truncated identities response');
115
+ }
116
+ const numKeys = response.readUInt32BE(offset);
117
+ offset += 4;
118
+ const keys = [];
119
+ for (let i = 0; i < numKeys; i++) {
120
+ // Read key blob
121
+ const [keyBlob, afterBlob] = readString(response, offset);
122
+ offset = afterBlob;
123
+ // Read comment
124
+ const [commentBuf, afterComment] = readString(response, offset);
125
+ offset = afterComment;
126
+ const comment = commentBuf.toString('utf-8');
127
+ // Parse key blob to get type and public key
128
+ let blobOffset = 0;
129
+ const [typeField, afterType] = readString(keyBlob, blobOffset);
130
+ blobOffset = afterType;
131
+ const typeStr = typeField.toString('ascii');
132
+ const keyType = parseKeyType(typeStr);
133
+ if (!keyType) {
134
+ continue; // skip unsupported key types
135
+ }
136
+ let publicKeyBytes;
137
+ if (keyType === 'ed25519') {
138
+ const [pubkey] = readString(keyBlob, blobOffset);
139
+ publicKeyBytes = new Uint8Array(pubkey);
140
+ }
141
+ else {
142
+ // RSA: exponent + modulus
143
+ const [exponent, afterExp] = readString(keyBlob, blobOffset);
144
+ const [modulus] = readString(keyBlob, afterExp);
145
+ const result = Buffer.alloc(4 + exponent.length + 4 + modulus.length);
146
+ let pos = 0;
147
+ result.writeUInt32BE(exponent.length, pos);
148
+ pos += 4;
149
+ exponent.copy(result, pos);
150
+ pos += exponent.length;
151
+ result.writeUInt32BE(modulus.length, pos);
152
+ pos += 4;
153
+ modulus.copy(result, pos);
154
+ publicKeyBytes = new Uint8Array(result);
155
+ }
156
+ // Compute fingerprint
157
+ const hash = crypto.createHash('sha256').update(keyBlob).digest();
158
+ const fingerprint = 'SHA256:' + hash.toString('base64').replace(/=+$/, '');
159
+ keys.push({
160
+ type: keyType,
161
+ publicKeyBytes,
162
+ fingerprint,
163
+ ...(comment ? { comment } : {}),
164
+ });
165
+ }
166
+ return keys;
167
+ }
168
+ /**
169
+ * Sign data using a key available in the SSH agent.
170
+ * Returns the raw signature bytes (Ed25519: 64 bytes, RSA: variable).
171
+ */
172
+ export async function signWithSSHAgent(data, publicKeyBlob) {
173
+ // Build the sign request
174
+ // Format: byte SSH_AGENTC_SIGN_REQUEST, string key_blob, string data, uint32 flags
175
+ const totalLen = 1 + 4 + publicKeyBlob.length + 4 + data.length + 4;
176
+ const request = Buffer.alloc(totalLen);
177
+ let offset = 0;
178
+ request[offset] = SSH_AGENTC_SIGN_REQUEST;
179
+ offset += 1;
180
+ offset = writeString(request, publicKeyBlob, offset);
181
+ offset = writeString(request, data, offset);
182
+ // Flags (0 for default)
183
+ request.writeUInt32BE(SSH_AGENT_FLAG_ED25519, offset);
184
+ const response = await agentRequest(request);
185
+ if (response[0] === SSH_AGENT_FAILURE) {
186
+ throw new Error('SSH agent refused to sign (key not found or agent denied request)');
187
+ }
188
+ if (response[0] !== SSH_AGENT_SIGN_RESPONSE) {
189
+ throw new Error(`Unexpected SSH agent response type: ${response[0]}`);
190
+ }
191
+ // Parse signature: string signature_blob
192
+ const [sigBlob] = readString(response, 1);
193
+ // Signature blob format: string sig_type, string sig_data
194
+ let sigOffset = 0;
195
+ const [, afterSigType] = readString(sigBlob, sigOffset);
196
+ sigOffset = afterSigType;
197
+ const [sigData] = readString(sigBlob, sigOffset);
198
+ return new Uint8Array(sigData);
199
+ }
200
+ /**
201
+ * Sign data using a private key file directly.
202
+ * Supports OpenSSH private key format.
203
+ */
204
+ export async function signWithKeyFile(data, keyPath, passphrase) {
205
+ const keyContent = fs.readFileSync(keyPath, 'utf-8');
206
+ const privateKey = crypto.createPrivateKey({
207
+ key: keyContent,
208
+ format: 'pem',
209
+ ...(passphrase ? { passphrase } : {}),
210
+ });
211
+ const keyType = privateKey.asymmetricKeyType;
212
+ if (keyType === 'ed25519') {
213
+ const sign = crypto.sign(null, Buffer.from(data), privateKey);
214
+ return new Uint8Array(sign);
215
+ }
216
+ else if (keyType === 'rsa') {
217
+ const sign = crypto.sign('sha256', Buffer.from(data), {
218
+ key: privateKey,
219
+ padding: crypto.constants.RSA_PKCS1_PADDING,
220
+ });
221
+ return new Uint8Array(sign);
222
+ }
223
+ throw new Error(`Unsupported key type: ${keyType}`);
224
+ }
225
+ //# sourceMappingURL=ssh-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-agent.js","sourceRoot":"","sources":["../../crypto/ssh-agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { SSHKeyInfo } from './types.js';
2
+ /**
3
+ * Parse an OpenSSH public key from authorized_keys / .pub file format.
4
+ * Supports ssh-ed25519 and ssh-rsa key types.
5
+ *
6
+ * Format: <key-type> <base64-blob> [comment]
7
+ */
8
+ export declare function parseSSHPublicKey(keyString: string): SSHKeyInfo;
9
+ /**
10
+ * Convert an Ed25519 public key to X25519 (Curve25519) public key.
11
+ * Uses sodium crypto_sign_ed25519_pk_to_curve25519.
12
+ */
13
+ export declare function ed25519ToX25519PublicKey(ed25519PublicKey: Uint8Array): Uint8Array;
14
+ /**
15
+ * Convert an Ed25519 secret key to X25519 (Curve25519) secret key.
16
+ * Uses sodium crypto_sign_ed25519_sk_to_curve25519.
17
+ */
18
+ export declare function ed25519ToX25519SecretKey(ed25519SecretKey: Uint8Array): Uint8Array;
19
+ //# sourceMappingURL=ssh-keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-keys.d.ts","sourceRoot":"","sources":["../../crypto/ssh-keys.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,YAAY,CAAC;AAEzD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAqC/D;AAkED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,gBAAgB,EAAE,UAAU,GAAG,UAAU,CAKjF;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,gBAAgB,EAAE,UAAU,GAAG,UAAU,CAKjF"}