@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.
- package/dist/cli/agent-registry/config-merger.d.ts +28 -0
- package/dist/cli/agent-registry/config-merger.d.ts.map +1 -0
- package/dist/cli/agent-registry/config-merger.js +90 -0
- package/dist/cli/agent-registry/config-merger.js.map +1 -0
- package/dist/cli/agent-registry/detector.d.ts +7 -0
- package/dist/cli/agent-registry/detector.d.ts.map +1 -0
- package/dist/cli/agent-registry/detector.js +100 -0
- package/dist/cli/agent-registry/detector.js.map +1 -0
- package/dist/cli/agent-registry/index.d.ts +26 -0
- package/dist/cli/agent-registry/index.d.ts.map +1 -0
- package/dist/cli/agent-registry/index.js +77 -0
- package/dist/cli/agent-registry/index.js.map +1 -0
- package/dist/cli/agent-registry/path-validator.d.ts +11 -0
- package/dist/cli/agent-registry/path-validator.d.ts.map +1 -0
- package/dist/cli/agent-registry/path-validator.js +69 -0
- package/dist/cli/agent-registry/path-validator.js.map +1 -0
- package/dist/cli/agent-registry/registry.json +108 -0
- package/dist/cli/agent-registry/types.d.ts +29 -0
- package/dist/cli/agent-registry/types.d.ts.map +1 -0
- package/dist/cli/agent-registry/types.js +2 -0
- package/dist/cli/agent-registry/types.js.map +1 -0
- package/dist/cli/bootstrap-lock.d.ts +7 -0
- package/dist/cli/bootstrap-lock.d.ts.map +1 -0
- package/dist/cli/bootstrap-lock.js +62 -0
- package/dist/cli/bootstrap-lock.js.map +1 -0
- package/dist/cli/bootstrap.d.ts +23 -0
- package/dist/cli/bootstrap.d.ts.map +1 -0
- package/dist/cli/bootstrap.js +438 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cli/commands/config.d.ts +13 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +244 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/devices.d.ts +21 -0
- package/dist/cli/commands/devices.d.ts.map +1 -0
- package/dist/cli/commands/devices.js +229 -0
- package/dist/cli/commands/devices.js.map +1 -0
- package/dist/cli/commands/export.d.ts +12 -0
- package/dist/cli/commands/export.d.ts.map +1 -0
- package/dist/cli/commands/export.js +183 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/import.d.ts +26 -0
- package/dist/cli/commands/import.d.ts.map +1 -0
- package/dist/cli/commands/import.js +311 -0
- package/dist/cli/commands/import.js.map +1 -0
- package/dist/cli/commands/kb.d.ts +39 -0
- package/dist/cli/commands/kb.d.ts.map +1 -0
- package/dist/cli/commands/kb.js +138 -0
- package/dist/cli/commands/kb.js.map +1 -0
- package/dist/cli/commands/project.d.ts +6 -0
- package/dist/cli/commands/project.d.ts.map +1 -0
- package/dist/cli/commands/project.js +115 -0
- package/dist/cli/commands/project.js.map +1 -0
- package/dist/cli/commands/projects.d.ts +33 -0
- package/dist/cli/commands/projects.d.ts.map +1 -0
- package/dist/cli/commands/projects.js +189 -0
- package/dist/cli/commands/projects.js.map +1 -0
- package/dist/cli/commands/register.d.ts +8 -0
- package/dist/cli/commands/register.d.ts.map +1 -0
- package/dist/cli/commands/register.js +146 -0
- package/dist/cli/commands/register.js.map +1 -0
- package/dist/cli/commands/rotate-key.d.ts +16 -0
- package/dist/cli/commands/rotate-key.d.ts.map +1 -0
- package/dist/cli/commands/rotate-key.js +197 -0
- package/dist/cli/commands/rotate-key.js.map +1 -0
- package/dist/cli/commands/setup-sync.d.ts +2 -0
- package/dist/cli/commands/setup-sync.d.ts.map +1 -0
- package/dist/cli/commands/setup-sync.js +165 -0
- package/dist/cli/commands/setup-sync.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +12 -0
- package/dist/cli/commands/setup.d.ts.map +1 -0
- package/dist/cli/commands/setup.js +39 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/status.d.ts +5 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +96 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/uninstall.d.ts +4 -0
- package/dist/cli/commands/uninstall.d.ts.map +1 -0
- package/dist/cli/commands/uninstall.js +85 -0
- package/dist/cli/commands/uninstall.js.map +1 -0
- package/dist/cli/commands/unregister.d.ts +2 -0
- package/dist/cli/commands/unregister.d.ts.map +1 -0
- package/dist/cli/commands/unregister.js +46 -0
- package/dist/cli/commands/unregister.js.map +1 -0
- package/dist/cli/device-metadata.d.ts +15 -0
- package/dist/cli/device-metadata.d.ts.map +1 -0
- package/dist/cli/device-metadata.js +58 -0
- package/dist/cli/device-metadata.js.map +1 -0
- package/dist/cli/github.d.ts +38 -0
- package/dist/cli/github.d.ts.map +1 -0
- package/dist/cli/github.js +159 -0
- package/dist/cli/github.js.map +1 -0
- package/dist/cli/guide-hashes.json +13 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +226 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/mcp-server.d.ts +205 -0
- package/dist/cli/mcp-server.d.ts.map +1 -0
- package/dist/cli/mcp-server.js +366 -0
- package/dist/cli/mcp-server.js.map +1 -0
- package/dist/cli/tools/kb-delete.d.ts +10 -0
- package/dist/cli/tools/kb-delete.d.ts.map +1 -0
- package/dist/cli/tools/kb-delete.js +28 -0
- package/dist/cli/tools/kb-delete.js.map +1 -0
- package/dist/cli/tools/kb-ingest.d.ts +13 -0
- package/dist/cli/tools/kb-ingest.d.ts.map +1 -0
- package/dist/cli/tools/kb-ingest.js +72 -0
- package/dist/cli/tools/kb-ingest.js.map +1 -0
- package/dist/cli/tools/kb-list.d.ts +20 -0
- package/dist/cli/tools/kb-list.d.ts.map +1 -0
- package/dist/cli/tools/kb-list.js +24 -0
- package/dist/cli/tools/kb-list.js.map +1 -0
- package/dist/cli/tools/kb-query-shared.d.ts +27 -0
- package/dist/cli/tools/kb-query-shared.d.ts.map +1 -0
- package/dist/cli/tools/kb-query-shared.js +28 -0
- package/dist/cli/tools/kb-query-shared.js.map +1 -0
- package/dist/cli/tools/kb-query.d.ts +20 -0
- package/dist/cli/tools/kb-query.d.ts.map +1 -0
- package/dist/cli/tools/kb-query.js +109 -0
- package/dist/cli/tools/kb-query.js.map +1 -0
- package/dist/cli/tools/kb-summary.d.ts +29 -0
- package/dist/cli/tools/kb-summary.d.ts.map +1 -0
- package/dist/cli/tools/kb-summary.js +89 -0
- package/dist/cli/tools/kb-summary.js.map +1 -0
- package/dist/cli/tools/kb-sync-status.d.ts +7 -0
- package/dist/cli/tools/kb-sync-status.d.ts.map +1 -0
- package/dist/cli/tools/kb-sync-status.js +48 -0
- package/dist/cli/tools/kb-sync-status.js.map +1 -0
- package/dist/crypto/aad.d.ts +8 -0
- package/dist/crypto/aad.d.ts.map +1 -0
- package/dist/crypto/aad.js +11 -0
- package/dist/crypto/aad.js.map +1 -0
- package/dist/crypto/aead.d.ts +21 -0
- package/dist/crypto/aead.d.ts.map +1 -0
- package/dist/crypto/aead.js +43 -0
- package/dist/crypto/aead.js.map +1 -0
- package/dist/crypto/argon2.d.ts +11 -0
- package/dist/crypto/argon2.d.ts.map +1 -0
- package/dist/crypto/argon2.js +33 -0
- package/dist/crypto/argon2.js.map +1 -0
- package/dist/crypto/blob-id.d.ts +6 -0
- package/dist/crypto/blob-id.d.ts.map +1 -0
- package/dist/crypto/blob-id.js +33 -0
- package/dist/crypto/blob-id.js.map +1 -0
- package/dist/crypto/canonical-json.d.ts +6 -0
- package/dist/crypto/canonical-json.d.ts.map +1 -0
- package/dist/crypto/canonical-json.js +88 -0
- package/dist/crypto/canonical-json.js.map +1 -0
- package/dist/crypto/commitment.d.ts +12 -0
- package/dist/crypto/commitment.d.ts.map +1 -0
- package/dist/crypto/commitment.js +37 -0
- package/dist/crypto/commitment.js.map +1 -0
- package/dist/crypto/encryption-service.d.ts +19 -0
- package/dist/crypto/encryption-service.d.ts.map +1 -0
- package/dist/crypto/encryption-service.js +38 -0
- package/dist/crypto/encryption-service.js.map +1 -0
- package/dist/crypto/envelope-cbor.d.ts +37 -0
- package/dist/crypto/envelope-cbor.d.ts.map +1 -0
- package/dist/crypto/envelope-cbor.js +124 -0
- package/dist/crypto/envelope-cbor.js.map +1 -0
- package/dist/crypto/envelope.d.ts +34 -0
- package/dist/crypto/envelope.d.ts.map +1 -0
- package/dist/crypto/envelope.js +160 -0
- package/dist/crypto/envelope.js.map +1 -0
- package/dist/crypto/hkdf.d.ts +16 -0
- package/dist/crypto/hkdf.d.ts.map +1 -0
- package/dist/crypto/hkdf.js +33 -0
- package/dist/crypto/hkdf.js.map +1 -0
- package/dist/crypto/index.d.ts +15 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/index.js +15 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/crypto/invite.d.ts +31 -0
- package/dist/crypto/invite.d.ts.map +1 -0
- package/dist/crypto/invite.js +137 -0
- package/dist/crypto/invite.js.map +1 -0
- package/dist/crypto/keyring.d.ts +37 -0
- package/dist/crypto/keyring.d.ts.map +1 -0
- package/dist/crypto/keyring.js +219 -0
- package/dist/crypto/keyring.js.map +1 -0
- package/dist/crypto/known-keys.d.ts +34 -0
- package/dist/crypto/known-keys.d.ts.map +1 -0
- package/dist/crypto/known-keys.js +106 -0
- package/dist/crypto/known-keys.js.map +1 -0
- package/dist/crypto/project-keys.d.ts +26 -0
- package/dist/crypto/project-keys.d.ts.map +1 -0
- package/dist/crypto/project-keys.js +69 -0
- package/dist/crypto/project-keys.js.map +1 -0
- package/dist/crypto/secure-buffer.d.ts +31 -0
- package/dist/crypto/secure-buffer.d.ts.map +1 -0
- package/dist/crypto/secure-buffer.js +61 -0
- package/dist/crypto/secure-buffer.js.map +1 -0
- package/dist/crypto/ssh-agent.d.ts +16 -0
- package/dist/crypto/ssh-agent.d.ts.map +1 -0
- package/dist/crypto/ssh-agent.js +225 -0
- package/dist/crypto/ssh-agent.js.map +1 -0
- package/dist/crypto/ssh-keys.d.ts +19 -0
- package/dist/crypto/ssh-keys.d.ts.map +1 -0
- package/dist/crypto/ssh-keys.js +121 -0
- package/dist/crypto/ssh-keys.js.map +1 -0
- package/dist/crypto/tiers/enhanced.d.ts +25 -0
- package/dist/crypto/tiers/enhanced.d.ts.map +1 -0
- package/dist/crypto/tiers/enhanced.js +56 -0
- package/dist/crypto/tiers/enhanced.js.map +1 -0
- package/dist/crypto/tiers/maximum.d.ts +19 -0
- package/dist/crypto/tiers/maximum.d.ts.map +1 -0
- package/dist/crypto/tiers/maximum.js +25 -0
- package/dist/crypto/tiers/maximum.js.map +1 -0
- package/dist/crypto/tiers/standard.d.ts +27 -0
- package/dist/crypto/tiers/standard.d.ts.map +1 -0
- package/dist/crypto/tiers/standard.js +147 -0
- package/dist/crypto/tiers/standard.js.map +1 -0
- package/dist/crypto/types.d.ts +169 -0
- package/dist/crypto/types.d.ts.map +1 -0
- package/dist/crypto/types.js +11 -0
- package/dist/crypto/types.js.map +1 -0
- package/dist/pipeline/chunker.d.ts +27 -0
- package/dist/pipeline/chunker.d.ts.map +1 -0
- package/dist/pipeline/chunker.js +96 -0
- package/dist/pipeline/chunker.js.map +1 -0
- package/dist/pipeline/content-pipeline.d.ts +24 -0
- package/dist/pipeline/content-pipeline.d.ts.map +1 -0
- package/dist/pipeline/content-pipeline.js +49 -0
- package/dist/pipeline/content-pipeline.js.map +1 -0
- package/dist/pipeline/embedder.d.ts +49 -0
- package/dist/pipeline/embedder.d.ts.map +1 -0
- package/dist/pipeline/embedder.js +195 -0
- package/dist/pipeline/embedder.js.map +1 -0
- package/dist/pipeline/extract.d.ts +17 -0
- package/dist/pipeline/extract.d.ts.map +1 -0
- package/dist/pipeline/extract.js +70 -0
- package/dist/pipeline/extract.js.map +1 -0
- package/dist/pipeline/fetch.d.ts +26 -0
- package/dist/pipeline/fetch.d.ts.map +1 -0
- package/dist/pipeline/fetch.js +91 -0
- package/dist/pipeline/fetch.js.map +1 -0
- package/dist/pipeline/index.d.ts +10 -0
- package/dist/pipeline/index.d.ts.map +1 -0
- package/dist/pipeline/index.js +10 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/model-manager.d.ts +57 -0
- package/dist/pipeline/model-manager.d.ts.map +1 -0
- package/dist/pipeline/model-manager.js +234 -0
- package/dist/pipeline/model-manager.js.map +1 -0
- package/dist/pipeline/search.d.ts +37 -0
- package/dist/pipeline/search.d.ts.map +1 -0
- package/dist/pipeline/search.js +65 -0
- package/dist/pipeline/search.js.map +1 -0
- package/dist/pipeline/tokenizer.d.ts +29 -0
- package/dist/pipeline/tokenizer.d.ts.map +1 -0
- package/dist/pipeline/tokenizer.js +54 -0
- package/dist/pipeline/tokenizer.js.map +1 -0
- package/dist/pipeline/types.d.ts +86 -0
- package/dist/pipeline/types.d.ts.map +1 -0
- package/dist/pipeline/types.js +2 -0
- package/dist/pipeline/types.js.map +1 -0
- package/dist/pipeline/wordpiece-tokenizer.d.ts +60 -0
- package/dist/pipeline/wordpiece-tokenizer.d.ts.map +1 -0
- package/dist/pipeline/wordpiece-tokenizer.js +251 -0
- package/dist/pipeline/wordpiece-tokenizer.js.map +1 -0
- package/dist/storage/chunk-repo.d.ts +29 -0
- package/dist/storage/chunk-repo.d.ts.map +1 -0
- package/dist/storage/chunk-repo.js +115 -0
- package/dist/storage/chunk-repo.js.map +1 -0
- package/dist/storage/database-manager.d.ts +17 -0
- package/dist/storage/database-manager.d.ts.map +1 -0
- package/dist/storage/database-manager.js +100 -0
- package/dist/storage/database-manager.js.map +1 -0
- package/dist/storage/database.d.ts +10 -0
- package/dist/storage/database.d.ts.map +1 -0
- package/dist/storage/database.js +34 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/embedding-index.d.ts +22 -0
- package/dist/storage/embedding-index.d.ts.map +1 -0
- package/dist/storage/embedding-index.js +78 -0
- package/dist/storage/embedding-index.js.map +1 -0
- package/dist/storage/index.d.ts +10 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +10 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/kb-database.d.ts +11 -0
- package/dist/storage/kb-database.d.ts.map +1 -0
- package/dist/storage/kb-database.js +24 -0
- package/dist/storage/kb-database.js.map +1 -0
- package/dist/storage/schema.d.ts +6 -0
- package/dist/storage/schema.d.ts.map +1 -0
- package/dist/storage/schema.js +122 -0
- package/dist/storage/schema.js.map +1 -0
- package/dist/storage/source-repo.d.ts +20 -0
- package/dist/storage/source-repo.d.ts.map +1 -0
- package/dist/storage/source-repo.js +120 -0
- package/dist/storage/source-repo.js.map +1 -0
- package/dist/storage/sync-status-repo.d.ts +15 -0
- package/dist/storage/sync-status-repo.d.ts.map +1 -0
- package/dist/storage/sync-status-repo.js +40 -0
- package/dist/storage/sync-status-repo.js.map +1 -0
- package/dist/storage/types.d.ts +139 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +9 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/sync/canary.d.ts +14 -0
- package/dist/sync/canary.d.ts.map +1 -0
- package/dist/sync/canary.js +53 -0
- package/dist/sync/canary.js.map +1 -0
- package/dist/sync/full-sync.d.ts +16 -0
- package/dist/sync/full-sync.d.ts.map +1 -0
- package/dist/sync/full-sync.js +91 -0
- package/dist/sync/full-sync.js.map +1 -0
- package/dist/sync/http-client.d.ts +28 -0
- package/dist/sync/http-client.d.ts.map +1 -0
- package/dist/sync/http-client.js +90 -0
- package/dist/sync/http-client.js.map +1 -0
- package/dist/sync/incremental-sync.d.ts +17 -0
- package/dist/sync/incremental-sync.d.ts.map +1 -0
- package/dist/sync/incremental-sync.js +155 -0
- package/dist/sync/incremental-sync.js.map +1 -0
- package/dist/sync/index.d.ts +12 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +12 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/quota.d.ts +17 -0
- package/dist/sync/quota.d.ts.map +1 -0
- package/dist/sync/quota.js +48 -0
- package/dist/sync/quota.js.map +1 -0
- package/dist/sync/sequence.d.ts +21 -0
- package/dist/sync/sequence.d.ts.map +1 -0
- package/dist/sync/sequence.js +49 -0
- package/dist/sync/sequence.js.map +1 -0
- package/dist/sync/ssh-signer.d.ts +59 -0
- package/dist/sync/ssh-signer.d.ts.map +1 -0
- package/dist/sync/ssh-signer.js +241 -0
- package/dist/sync/ssh-signer.js.map +1 -0
- package/dist/sync/sync-service.d.ts +48 -0
- package/dist/sync/sync-service.d.ts.map +1 -0
- package/dist/sync/sync-service.js +116 -0
- package/dist/sync/sync-service.js.map +1 -0
- package/dist/sync/types.d.ts +106 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +2 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/sync/upload-queue.d.ts +40 -0
- package/dist/sync/upload-queue.d.ts.map +1 -0
- package/dist/sync/upload-queue.js +148 -0
- package/dist/sync/upload-queue.js.map +1 -0
- package/dist/sync/verification.d.ts +17 -0
- package/dist/sync/verification.d.ts.map +1 -0
- package/dist/sync/verification.js +25 -0
- package/dist/sync/verification.js.map +1 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +16 -0
- package/dist/vitest.config.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { hkdf } from '@noble/hashes/hkdf.js';
|
|
2
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
3
|
+
import { SecureBuffer } from './secure-buffer.js';
|
|
4
|
+
const DEFAULT_KEY_LENGTH = 32;
|
|
5
|
+
/**
|
|
6
|
+
* Derive a key using HKDF-SHA256 (Extract+Expand per RFC 5869).
|
|
7
|
+
* @param ikm - Input keying material
|
|
8
|
+
* @param info - Context/application-specific info string
|
|
9
|
+
* @param salt - Optional salt (defaults to empty Uint8Array)
|
|
10
|
+
* @param length - Output key length in bytes (default 32)
|
|
11
|
+
*/
|
|
12
|
+
export function deriveKey(ikm, info, salt, length) {
|
|
13
|
+
const infoBytes = new TextEncoder().encode(info);
|
|
14
|
+
return hkdf(sha256, ikm, salt ?? new Uint8Array(0), infoBytes, length ?? DEFAULT_KEY_LENGTH);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Derive the complete set of subkeys from a master key.
|
|
18
|
+
* Returns SecureBuffer-wrapped keys for:
|
|
19
|
+
* CEK (content), MEK (metadata), EEK (embedding), CKY (commit)
|
|
20
|
+
*/
|
|
21
|
+
export function deriveKeySet(masterKey, salt) {
|
|
22
|
+
const cekBytes = deriveKey(masterKey, 'chaoskb-content', salt);
|
|
23
|
+
const mekBytes = deriveKey(masterKey, 'chaoskb-metadata', salt);
|
|
24
|
+
const eekBytes = deriveKey(masterKey, 'chaoskb-embedding', salt);
|
|
25
|
+
const ckyBytes = deriveKey(masterKey, 'chaoskb-commit', salt);
|
|
26
|
+
return {
|
|
27
|
+
contentKey: SecureBuffer.from(Buffer.from(cekBytes)),
|
|
28
|
+
metadataKey: SecureBuffer.from(Buffer.from(mekBytes)),
|
|
29
|
+
embeddingKey: SecureBuffer.from(Buffer.from(eekBytes)),
|
|
30
|
+
commitKey: SecureBuffer.from(Buffer.from(ckyBytes)),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=hkdf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hkdf.js","sourceRoot":"","sources":["../../crypto/hkdf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAE9B;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CACvB,GAAe,EACf,IAAY,EACZ,IAAiB,EACjB,MAAe;IAEf,MAAM,SAAS,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjD,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,IAAI,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,IAAI,kBAAkB,CAAC,CAAC;AAC/F,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,SAAqB,EAAE,IAAiB;IACnE,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,EAAE,iBAAiB,EAAE,IAAI,CAAC,CAAC;IAC/D,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,EAAE,kBAAkB,EAAE,IAAI,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,EAAE,mBAAmB,EAAE,IAAI,CAAC,CAAC;IACjE,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,EAAE,gBAAgB,EAAE,IAAI,CAAC,CAAC;IAE9D,OAAO;QACL,UAAU,EAAE,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpD,WAAW,EAAE,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrD,YAAY,EAAE,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtD,SAAS,EAAE,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;KACpD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export { SecureBuffer } from './secure-buffer.js';
|
|
3
|
+
export { canonicalJson } from './canonical-json.js';
|
|
4
|
+
export { generateBlobId } from './blob-id.js';
|
|
5
|
+
export { aeadEncrypt, aeadDecrypt } from './aead.js';
|
|
6
|
+
export { deriveKey, deriveKeySet } from './hkdf.js';
|
|
7
|
+
export { deriveFromPassphrase as argon2Derive } from './argon2.js';
|
|
8
|
+
export { constructAAD } from './aad.js';
|
|
9
|
+
export { computeCommitment, verifyCommitment } from './commitment.js';
|
|
10
|
+
export { encryptPayload, decryptEnvelope } from './envelope.js';
|
|
11
|
+
export { parseSSHPublicKey, ed25519ToX25519PublicKey, ed25519ToX25519SecretKey } from './ssh-keys.js';
|
|
12
|
+
export { EncryptionService } from './encryption-service.js';
|
|
13
|
+
export { KeyringService } from './keyring.js';
|
|
14
|
+
export { createProjectKey, unwrapProjectKey } from './project-keys.js';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../crypto/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,oBAAoB,IAAI,YAAY,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACtG,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export { SecureBuffer } from './secure-buffer.js';
|
|
3
|
+
export { canonicalJson } from './canonical-json.js';
|
|
4
|
+
export { generateBlobId } from './blob-id.js';
|
|
5
|
+
export { aeadEncrypt, aeadDecrypt } from './aead.js';
|
|
6
|
+
export { deriveKey, deriveKeySet } from './hkdf.js';
|
|
7
|
+
export { deriveFromPassphrase as argon2Derive } from './argon2.js';
|
|
8
|
+
export { constructAAD } from './aad.js';
|
|
9
|
+
export { computeCommitment, verifyCommitment } from './commitment.js';
|
|
10
|
+
export { encryptPayload, decryptEnvelope } from './envelope.js';
|
|
11
|
+
export { parseSSHPublicKey, ed25519ToX25519PublicKey, ed25519ToX25519SecretKey } from './ssh-keys.js';
|
|
12
|
+
export { EncryptionService } from './encryption-service.js';
|
|
13
|
+
export { KeyringService } from './keyring.js';
|
|
14
|
+
export { createProjectKey, unwrapProjectKey } from './project-keys.js';
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../crypto/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,oBAAoB,IAAI,YAAY,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACtG,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { SSHKeyInfo } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create an encrypted invite blob for sharing a project key.
|
|
4
|
+
*
|
|
5
|
+
* Uses ephemeral X25519 ECDH + HKDF (with domain separation) + XChaCha20-Poly1305.
|
|
6
|
+
* The sender's and recipient's fingerprints and the project ID are bound into the
|
|
7
|
+
* HKDF info string to prevent cross-context key confusion.
|
|
8
|
+
*
|
|
9
|
+
* Output format: ephemeral_public_key(32) || nonce(24) || ciphertext || tag(16)
|
|
10
|
+
*/
|
|
11
|
+
export declare function createInviteBlob(projectKey: Uint8Array, projectId: string, senderKeyInfo: SSHKeyInfo, recipientKeyInfo: SSHKeyInfo): Uint8Array;
|
|
12
|
+
/**
|
|
13
|
+
* Open an encrypted invite blob to recover the project key.
|
|
14
|
+
*
|
|
15
|
+
* @param blob - The full invite blob (ephemeral_pk || nonce || ciphertext || tag)
|
|
16
|
+
* @param recipientEd25519Sk - The recipient's 64-byte Ed25519 secret key
|
|
17
|
+
* @param recipientKeyInfo - The recipient's SSH key info (for fingerprint)
|
|
18
|
+
* @param senderKeyInfo - The sender's SSH key info (for fingerprint)
|
|
19
|
+
* @param projectId - The project ID (for HKDF domain separation)
|
|
20
|
+
* @returns The raw project key bytes
|
|
21
|
+
*/
|
|
22
|
+
export declare function openInviteBlob(blob: Uint8Array, recipientEd25519Sk: Uint8Array, recipientKeyInfo: SSHKeyInfo, senderKeyInfo: SSHKeyInfo, projectId: string): Uint8Array;
|
|
23
|
+
/**
|
|
24
|
+
* Pad payload to a fixed size to prevent metadata leakage from blob sizes.
|
|
25
|
+
*/
|
|
26
|
+
export declare function padPayload(payload: Uint8Array, targetSize: number): Uint8Array;
|
|
27
|
+
/**
|
|
28
|
+
* Remove padding to recover the original payload.
|
|
29
|
+
*/
|
|
30
|
+
export declare function unpadPayload(padded: Uint8Array): Uint8Array;
|
|
31
|
+
//# sourceMappingURL=invite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invite.d.ts","sourceRoot":"","sources":["../../crypto/invite.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,UAAU,EACzB,gBAAgB,EAAE,UAAU,GAC3B,UAAU,CA4CZ;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,kBAAkB,EAAE,UAAU,EAC9B,gBAAgB,EAAE,UAAU,EAC5B,aAAa,EAAE,UAAU,EACzB,SAAS,EAAE,MAAM,GAChB,UAAU,CAgCZ;AAeD;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,UAAU,CAgB9E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,CAS3D"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
2
|
+
import sodium from 'sodium-native';
|
|
3
|
+
// sodium-native types are incomplete — these functions exist at runtime
|
|
4
|
+
const sodiumAny = sodium;
|
|
5
|
+
import { aeadEncrypt, aeadDecrypt } from './aead.js';
|
|
6
|
+
import { deriveKey } from './hkdf.js';
|
|
7
|
+
import { ed25519ToX25519PublicKey, ed25519ToX25519SecretKey } from './ssh-keys.js';
|
|
8
|
+
const PADDED_PAYLOAD_SIZE = 512;
|
|
9
|
+
/**
|
|
10
|
+
* Create an encrypted invite blob for sharing a project key.
|
|
11
|
+
*
|
|
12
|
+
* Uses ephemeral X25519 ECDH + HKDF (with domain separation) + XChaCha20-Poly1305.
|
|
13
|
+
* The sender's and recipient's fingerprints and the project ID are bound into the
|
|
14
|
+
* HKDF info string to prevent cross-context key confusion.
|
|
15
|
+
*
|
|
16
|
+
* Output format: ephemeral_public_key(32) || nonce(24) || ciphertext || tag(16)
|
|
17
|
+
*/
|
|
18
|
+
export function createInviteBlob(projectKey, projectId, senderKeyInfo, recipientKeyInfo) {
|
|
19
|
+
if (recipientKeyInfo.type !== 'ed25519') {
|
|
20
|
+
throw new Error('Invite crypto currently supports Ed25519 recipients only');
|
|
21
|
+
}
|
|
22
|
+
// Generate ephemeral X25519 key pair
|
|
23
|
+
const ephPk = Buffer.alloc(sodium.crypto_box_PUBLICKEYBYTES);
|
|
24
|
+
const ephSk = Buffer.alloc(sodium.crypto_box_SECRETKEYBYTES);
|
|
25
|
+
sodiumAny.crypto_box_keypair(ephPk, ephSk);
|
|
26
|
+
// Convert recipient Ed25519 public key to X25519
|
|
27
|
+
const recipientX25519Pk = ed25519ToX25519PublicKey(recipientKeyInfo.publicKeyBytes);
|
|
28
|
+
// ECDH: shared_secret = X25519(ephemeral_secret, recipient_x25519_public)
|
|
29
|
+
const sharedSecret = Buffer.alloc(sodiumAny.crypto_scalarmult_BYTES);
|
|
30
|
+
sodiumAny.crypto_scalarmult(sharedSecret, ephSk, Buffer.from(recipientX25519Pk));
|
|
31
|
+
// Derive encryption key with domain separation
|
|
32
|
+
const info = buildInviteHkdfInfo(senderKeyInfo.fingerprint, recipientKeyInfo.fingerprint, projectId);
|
|
33
|
+
const encryptionKey = deriveKey(new Uint8Array(sharedSecret), info);
|
|
34
|
+
// Pad and encrypt payload
|
|
35
|
+
const payload = JSON.stringify({
|
|
36
|
+
projectKey: Buffer.from(projectKey).toString('base64'),
|
|
37
|
+
projectId,
|
|
38
|
+
});
|
|
39
|
+
const padded = padPayload(new TextEncoder().encode(payload), PADDED_PAYLOAD_SIZE);
|
|
40
|
+
const emptyAAD = new Uint8Array(0);
|
|
41
|
+
const { nonce, ciphertext, tag } = aeadEncrypt(encryptionKey, padded, emptyAAD);
|
|
42
|
+
// Zero sensitive buffers
|
|
43
|
+
ephSk.fill(0);
|
|
44
|
+
sharedSecret.fill(0);
|
|
45
|
+
encryptionKey.fill(0);
|
|
46
|
+
// Output: ephemeral_pk(32) || nonce(24) || ciphertext || tag(16)
|
|
47
|
+
const result = new Uint8Array(ephPk.length + nonce.length + ciphertext.length + tag.length);
|
|
48
|
+
let offset = 0;
|
|
49
|
+
result.set(ephPk, offset);
|
|
50
|
+
offset += ephPk.length;
|
|
51
|
+
result.set(nonce, offset);
|
|
52
|
+
offset += nonce.length;
|
|
53
|
+
result.set(ciphertext, offset);
|
|
54
|
+
offset += ciphertext.length;
|
|
55
|
+
result.set(tag, offset);
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Open an encrypted invite blob to recover the project key.
|
|
60
|
+
*
|
|
61
|
+
* @param blob - The full invite blob (ephemeral_pk || nonce || ciphertext || tag)
|
|
62
|
+
* @param recipientEd25519Sk - The recipient's 64-byte Ed25519 secret key
|
|
63
|
+
* @param recipientKeyInfo - The recipient's SSH key info (for fingerprint)
|
|
64
|
+
* @param senderKeyInfo - The sender's SSH key info (for fingerprint)
|
|
65
|
+
* @param projectId - The project ID (for HKDF domain separation)
|
|
66
|
+
* @returns The raw project key bytes
|
|
67
|
+
*/
|
|
68
|
+
export function openInviteBlob(blob, recipientEd25519Sk, recipientKeyInfo, senderKeyInfo, projectId) {
|
|
69
|
+
// Parse the blob
|
|
70
|
+
let offset = 0;
|
|
71
|
+
const ephPk = blob.slice(offset, offset + 32);
|
|
72
|
+
offset += 32;
|
|
73
|
+
const nonce = blob.slice(offset, offset + 24);
|
|
74
|
+
offset += 24;
|
|
75
|
+
const tagStart = blob.length - 16;
|
|
76
|
+
const ciphertext = blob.slice(offset, tagStart);
|
|
77
|
+
const tag = blob.slice(tagStart);
|
|
78
|
+
// Convert recipient Ed25519 secret key to X25519
|
|
79
|
+
const recipientX25519Sk = ed25519ToX25519SecretKey(recipientEd25519Sk);
|
|
80
|
+
// ECDH: shared_secret = X25519(recipient_x25519_secret, ephemeral_public)
|
|
81
|
+
const sharedSecret = Buffer.alloc(sodiumAny.crypto_scalarmult_BYTES);
|
|
82
|
+
sodiumAny.crypto_scalarmult(sharedSecret, Buffer.from(recipientX25519Sk), Buffer.from(ephPk));
|
|
83
|
+
// Derive same encryption key
|
|
84
|
+
const info = buildInviteHkdfInfo(senderKeyInfo.fingerprint, recipientKeyInfo.fingerprint, projectId);
|
|
85
|
+
const encryptionKey = deriveKey(new Uint8Array(sharedSecret), info);
|
|
86
|
+
// Decrypt
|
|
87
|
+
const emptyAAD = new Uint8Array(0);
|
|
88
|
+
const padded = aeadDecrypt(encryptionKey, nonce, ciphertext, tag, emptyAAD);
|
|
89
|
+
// Zero sensitive buffers
|
|
90
|
+
sharedSecret.fill(0);
|
|
91
|
+
encryptionKey.fill(0);
|
|
92
|
+
// Unpad and extract project key
|
|
93
|
+
const payload = unpadPayload(padded);
|
|
94
|
+
const parsed = JSON.parse(new TextDecoder().decode(payload));
|
|
95
|
+
return Buffer.from(parsed.projectKey, 'base64');
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Build the HKDF info string with domain separation.
|
|
99
|
+
*
|
|
100
|
+
* Format: "chaoskb-invite-v1" || SHA256(senderFingerprint)(32) || SHA256(recipientFingerprint)(32) || SHA256(projectId)(32)
|
|
101
|
+
* Fixed-width encoding prevents ambiguity from variable-length fields.
|
|
102
|
+
*/
|
|
103
|
+
function buildInviteHkdfInfo(senderFingerprint, recipientFingerprint, projectId) {
|
|
104
|
+
const senderHash = createHash('sha256').update(senderFingerprint).digest('hex').slice(0, 64);
|
|
105
|
+
const recipientHash = createHash('sha256').update(recipientFingerprint).digest('hex').slice(0, 64);
|
|
106
|
+
const projectHash = createHash('sha256').update(projectId).digest('hex').slice(0, 64);
|
|
107
|
+
return `chaoskb-invite-v1${senderHash}${recipientHash}${projectHash}`;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Pad payload to a fixed size to prevent metadata leakage from blob sizes.
|
|
111
|
+
*/
|
|
112
|
+
export function padPayload(payload, targetSize) {
|
|
113
|
+
if (payload.length > targetSize - 4) {
|
|
114
|
+
throw new Error(`Payload too large to pad: ${payload.length} bytes (max ${targetSize - 4})`);
|
|
115
|
+
}
|
|
116
|
+
const padded = new Uint8Array(targetSize);
|
|
117
|
+
// First 4 bytes: big-endian payload length
|
|
118
|
+
const view = new DataView(padded.buffer);
|
|
119
|
+
view.setUint32(0, payload.length, false);
|
|
120
|
+
padded.set(payload, 4);
|
|
121
|
+
// Fill remainder with random bytes
|
|
122
|
+
const randomPadding = randomBytes(targetSize - 4 - payload.length);
|
|
123
|
+
padded.set(randomPadding, 4 + payload.length);
|
|
124
|
+
return padded;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Remove padding to recover the original payload.
|
|
128
|
+
*/
|
|
129
|
+
export function unpadPayload(padded) {
|
|
130
|
+
const view = new DataView(padded.buffer, padded.byteOffset, padded.byteLength);
|
|
131
|
+
const length = view.getUint32(0, false);
|
|
132
|
+
if (length > padded.length - 4) {
|
|
133
|
+
throw new Error('Invalid padding: declared length exceeds buffer');
|
|
134
|
+
}
|
|
135
|
+
return padded.slice(4, 4 + length);
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=invite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invite.js","sourceRoot":"","sources":["../../crypto/invite.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { IKeyringService, ISecureBuffer } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* OS keyring integration via shell commands.
|
|
4
|
+
* Uses execFile (not exec) to prevent shell injection.
|
|
5
|
+
*
|
|
6
|
+
* macOS: security add-generic-password / find-generic-password / delete-generic-password
|
|
7
|
+
* Linux: secret-tool store / lookup / clear
|
|
8
|
+
* Windows: cmdkey /add: / /list: / /delete:
|
|
9
|
+
*/
|
|
10
|
+
export declare class KeyringService implements IKeyringService {
|
|
11
|
+
private readonly platform;
|
|
12
|
+
constructor(platform?: NodeJS.Platform);
|
|
13
|
+
/**
|
|
14
|
+
* Store a secret in the OS keyring.
|
|
15
|
+
*/
|
|
16
|
+
store(service: string, account: string, secret: ISecureBuffer): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Retrieve a secret from the OS keyring.
|
|
19
|
+
* Returns null if not found.
|
|
20
|
+
*/
|
|
21
|
+
retrieve(service: string, account: string): Promise<ISecureBuffer | null>;
|
|
22
|
+
/**
|
|
23
|
+
* Delete a secret from the OS keyring.
|
|
24
|
+
* Returns true if deleted, false if not found.
|
|
25
|
+
*/
|
|
26
|
+
delete(service: string, account: string): Promise<boolean>;
|
|
27
|
+
private storeMacOS;
|
|
28
|
+
private retrieveMacOS;
|
|
29
|
+
private deleteMacOS;
|
|
30
|
+
private storeLinux;
|
|
31
|
+
private retrieveLinux;
|
|
32
|
+
private deleteLinux;
|
|
33
|
+
private storeWindows;
|
|
34
|
+
private retrieveWindows;
|
|
35
|
+
private deleteWindows;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=keyring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyring.d.ts","sourceRoot":"","sources":["../../crypto/keyring.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIjE;;;;;;;GAOG;AACH,qBAAa,cAAe,YAAW,eAAe;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;gBAE/B,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ;IAItC;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBnF;;;OAGG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAyB/E;;;OAGG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;YAuBlD,UAAU;YAqBV,aAAa;YAUb,WAAW;YAUX,UAAU;YAkBV,aAAa;YASb,WAAW;YAUX,YAAY;YAWZ,eAAe;YA4Cf,aAAa;CAI5B"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import { SecureBuffer } from './secure-buffer.js';
|
|
4
|
+
const execFileAsync = promisify(execFile);
|
|
5
|
+
/**
|
|
6
|
+
* OS keyring integration via shell commands.
|
|
7
|
+
* Uses execFile (not exec) to prevent shell injection.
|
|
8
|
+
*
|
|
9
|
+
* macOS: security add-generic-password / find-generic-password / delete-generic-password
|
|
10
|
+
* Linux: secret-tool store / lookup / clear
|
|
11
|
+
* Windows: cmdkey /add: / /list: / /delete:
|
|
12
|
+
*/
|
|
13
|
+
export class KeyringService {
|
|
14
|
+
platform;
|
|
15
|
+
constructor(platform) {
|
|
16
|
+
this.platform = platform ?? process.platform;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Store a secret in the OS keyring.
|
|
20
|
+
*/
|
|
21
|
+
async store(service, account, secret) {
|
|
22
|
+
const secretHex = secret.buffer.toString('hex');
|
|
23
|
+
try {
|
|
24
|
+
switch (this.platform) {
|
|
25
|
+
case 'darwin':
|
|
26
|
+
await this.storeMacOS(service, account, secretHex);
|
|
27
|
+
break;
|
|
28
|
+
case 'linux':
|
|
29
|
+
await this.storeLinux(service, account, secretHex);
|
|
30
|
+
break;
|
|
31
|
+
case 'win32':
|
|
32
|
+
await this.storeWindows(service, account, secretHex);
|
|
33
|
+
break;
|
|
34
|
+
default:
|
|
35
|
+
throw new Error(`Unsupported platform: ${this.platform}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
// We can't zero the hex string (JS strings are immutable),
|
|
40
|
+
// but we at least don't hold onto it.
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Retrieve a secret from the OS keyring.
|
|
45
|
+
* Returns null if not found.
|
|
46
|
+
*/
|
|
47
|
+
async retrieve(service, account) {
|
|
48
|
+
try {
|
|
49
|
+
let secretHex;
|
|
50
|
+
switch (this.platform) {
|
|
51
|
+
case 'darwin':
|
|
52
|
+
secretHex = await this.retrieveMacOS(service, account);
|
|
53
|
+
break;
|
|
54
|
+
case 'linux':
|
|
55
|
+
secretHex = await this.retrieveLinux(service, account);
|
|
56
|
+
break;
|
|
57
|
+
case 'win32':
|
|
58
|
+
secretHex = await this.retrieveWindows(service, account);
|
|
59
|
+
break;
|
|
60
|
+
default:
|
|
61
|
+
throw new Error(`Unsupported platform: ${this.platform}`);
|
|
62
|
+
}
|
|
63
|
+
const bytes = Buffer.from(secretHex.trim(), 'hex');
|
|
64
|
+
return SecureBuffer.from(bytes);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Delete a secret from the OS keyring.
|
|
72
|
+
* Returns true if deleted, false if not found.
|
|
73
|
+
*/
|
|
74
|
+
async delete(service, account) {
|
|
75
|
+
try {
|
|
76
|
+
switch (this.platform) {
|
|
77
|
+
case 'darwin':
|
|
78
|
+
await this.deleteMacOS(service, account);
|
|
79
|
+
break;
|
|
80
|
+
case 'linux':
|
|
81
|
+
await this.deleteLinux(service, account);
|
|
82
|
+
break;
|
|
83
|
+
case 'win32':
|
|
84
|
+
await this.deleteWindows(service, account);
|
|
85
|
+
break;
|
|
86
|
+
default:
|
|
87
|
+
throw new Error(`Unsupported platform: ${this.platform}`);
|
|
88
|
+
}
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// --- macOS ---
|
|
96
|
+
async storeMacOS(service, account, secret) {
|
|
97
|
+
// Delete existing entry first (update = delete + add)
|
|
98
|
+
try {
|
|
99
|
+
await execFileAsync('security', [
|
|
100
|
+
'delete-generic-password',
|
|
101
|
+
'-s', service,
|
|
102
|
+
'-a', account,
|
|
103
|
+
]);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// Ignore if not found
|
|
107
|
+
}
|
|
108
|
+
await execFileAsync('security', [
|
|
109
|
+
'add-generic-password',
|
|
110
|
+
'-s', service,
|
|
111
|
+
'-a', account,
|
|
112
|
+
'-w', secret,
|
|
113
|
+
'-U', // update if exists
|
|
114
|
+
]);
|
|
115
|
+
}
|
|
116
|
+
async retrieveMacOS(service, account) {
|
|
117
|
+
const { stdout } = await execFileAsync('security', [
|
|
118
|
+
'find-generic-password',
|
|
119
|
+
'-s', service,
|
|
120
|
+
'-a', account,
|
|
121
|
+
'-w', // output password only
|
|
122
|
+
]);
|
|
123
|
+
return stdout.trim();
|
|
124
|
+
}
|
|
125
|
+
async deleteMacOS(service, account) {
|
|
126
|
+
await execFileAsync('security', [
|
|
127
|
+
'delete-generic-password',
|
|
128
|
+
'-s', service,
|
|
129
|
+
'-a', account,
|
|
130
|
+
]);
|
|
131
|
+
}
|
|
132
|
+
// --- Linux ---
|
|
133
|
+
async storeLinux(service, account, secret) {
|
|
134
|
+
// secret-tool reads from stdin
|
|
135
|
+
const child = execFileAsync('secret-tool', [
|
|
136
|
+
'store',
|
|
137
|
+
'--label', `${service}/${account}`,
|
|
138
|
+
'service', service,
|
|
139
|
+
'account', account,
|
|
140
|
+
]);
|
|
141
|
+
// Write secret to stdin
|
|
142
|
+
if (child.child.stdin) {
|
|
143
|
+
child.child.stdin.write(secret);
|
|
144
|
+
child.child.stdin.end();
|
|
145
|
+
}
|
|
146
|
+
await child;
|
|
147
|
+
}
|
|
148
|
+
async retrieveLinux(service, account) {
|
|
149
|
+
const { stdout } = await execFileAsync('secret-tool', [
|
|
150
|
+
'lookup',
|
|
151
|
+
'service', service,
|
|
152
|
+
'account', account,
|
|
153
|
+
]);
|
|
154
|
+
return stdout;
|
|
155
|
+
}
|
|
156
|
+
async deleteLinux(service, account) {
|
|
157
|
+
await execFileAsync('secret-tool', [
|
|
158
|
+
'clear',
|
|
159
|
+
'service', service,
|
|
160
|
+
'account', account,
|
|
161
|
+
]);
|
|
162
|
+
}
|
|
163
|
+
// --- Windows ---
|
|
164
|
+
async storeWindows(service, account, secret) {
|
|
165
|
+
const target = `${service}/${account}`;
|
|
166
|
+
// Use PowerShell with .NET CredentialManager API (no external modules required)
|
|
167
|
+
const script = `
|
|
168
|
+
Add-Type -AssemblyName System.Runtime.InteropServices
|
|
169
|
+
$cred = New-Object System.Management.Automation.PSCredential('${account.replace(/'/g, "''")}', (ConvertTo-SecureString '${secret.replace(/'/g, "''")}' -AsPlainText -Force))
|
|
170
|
+
cmdkey /add:${target} /user:${account} /pass:${secret}
|
|
171
|
+
`.trim();
|
|
172
|
+
await execFileAsync('powershell', ['-NoProfile', '-Command', script]);
|
|
173
|
+
}
|
|
174
|
+
async retrieveWindows(service, account) {
|
|
175
|
+
const target = `${service}/${account}`;
|
|
176
|
+
// Use PowerShell with native .NET Credential API (no external modules needed)
|
|
177
|
+
const script = `
|
|
178
|
+
Add-Type @"
|
|
179
|
+
using System;
|
|
180
|
+
using System.Runtime.InteropServices;
|
|
181
|
+
public class CredentialHelper {
|
|
182
|
+
[DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
|
|
183
|
+
public static extern bool CredReadW(string target, int type, int flags, out IntPtr credential);
|
|
184
|
+
[DllImport("advapi32.dll")]
|
|
185
|
+
public static extern void CredFree(IntPtr credential);
|
|
186
|
+
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
|
|
187
|
+
public struct CREDENTIAL {
|
|
188
|
+
public int Flags; public int Type;
|
|
189
|
+
public string TargetName; public string Comment;
|
|
190
|
+
public long LastWritten; public int CredentialBlobSize;
|
|
191
|
+
public IntPtr CredentialBlob; public int Persist;
|
|
192
|
+
public int AttributeCount; public IntPtr Attributes;
|
|
193
|
+
public string TargetAlias; public string UserName;
|
|
194
|
+
}
|
|
195
|
+
public static string Read(string target) {
|
|
196
|
+
IntPtr ptr;
|
|
197
|
+
if (!CredReadW(target, 1, 0, out ptr)) return "";
|
|
198
|
+
var cred = (CREDENTIAL)Marshal.PtrToStructure(ptr, typeof(CREDENTIAL));
|
|
199
|
+
var secret = Marshal.PtrToStringUni(cred.CredentialBlob, cred.CredentialBlobSize / 2);
|
|
200
|
+
CredFree(ptr);
|
|
201
|
+
return secret;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
"@
|
|
205
|
+
[CredentialHelper]::Read('${target.replace(/'/g, "''")}')
|
|
206
|
+
`.trim();
|
|
207
|
+
const { stdout } = await execFileAsync('powershell', ['-NoProfile', '-Command', script]);
|
|
208
|
+
const result = stdout.trim();
|
|
209
|
+
if (!result) {
|
|
210
|
+
throw new Error(`Credential not found: ${target}`);
|
|
211
|
+
}
|
|
212
|
+
return result;
|
|
213
|
+
}
|
|
214
|
+
async deleteWindows(service, account) {
|
|
215
|
+
const target = `${service}/${account}`;
|
|
216
|
+
await execFileAsync('cmdkey', ['/delete:' + target]);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=keyring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyring.js","sourceRoot":"","sources":["../../crypto/keyring.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
interface PinnedKey {
|
|
2
|
+
fingerprint: string;
|
|
3
|
+
publicKey: string;
|
|
4
|
+
source: string;
|
|
5
|
+
firstSeen: string;
|
|
6
|
+
verifiedAt: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Pin a key for an identifier (e.g., "github:alice").
|
|
10
|
+
* Throws if the identifier is already pinned with a different fingerprint.
|
|
11
|
+
*/
|
|
12
|
+
export declare function pinKey(identifier: string, fingerprint: string, publicKey: string, source: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* Get a pinned key by identifier.
|
|
15
|
+
*/
|
|
16
|
+
export declare function getPinnedKey(identifier: string): PinnedKey | null;
|
|
17
|
+
/**
|
|
18
|
+
* Check a key against the pin store.
|
|
19
|
+
*/
|
|
20
|
+
export declare function checkKeyPin(identifier: string, fingerprint: string): 'match' | 'mismatch' | 'new';
|
|
21
|
+
/**
|
|
22
|
+
* Update a pinned key after verified rotation (e.g., new key confirmed on GitHub).
|
|
23
|
+
*/
|
|
24
|
+
export declare function updatePinnedKey(identifier: string, fingerprint: string, publicKey: string, source: string): void;
|
|
25
|
+
export declare class KeyMismatchError extends Error {
|
|
26
|
+
readonly identifier: string;
|
|
27
|
+
readonly pinnedFingerprint: string;
|
|
28
|
+
readonly newFingerprint: string;
|
|
29
|
+
readonly pinnedSource: string;
|
|
30
|
+
readonly newSource: string;
|
|
31
|
+
constructor(identifier: string, pinnedFingerprint: string, newFingerprint: string, pinnedSource: string, newSource: string);
|
|
32
|
+
}
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=known-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"known-keys.d.ts","sourceRoot":"","sources":["../../crypto/known-keys.ts"],"names":[],"mappings":"AAQA,UAAU,SAAS;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AA2BD;;;GAGG;AACH,wBAAgB,MAAM,CACpB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,IAAI,CA8BN;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAGjE;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,OAAO,GAAG,UAAU,GAAG,KAAK,CAO9B;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,IAAI,CAUN;AAED,qBAAa,gBAAiB,SAAQ,KAAK;aAEvB,UAAU,EAAE,MAAM;aAClB,iBAAiB,EAAE,MAAM;aACzB,cAAc,EAAE,MAAM;aACtB,YAAY,EAAE,MAAM;aACpB,SAAS,EAAE,MAAM;gBAJjB,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,MAAM,EACzB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM;CAUpC"}
|