qa360 1.0.4 → 1.1.1
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/commands/history.js +1 -1
- package/dist/commands/pack.js +1 -1
- package/dist/commands/run.d.ts +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +1 -1
- package/dist/commands/secrets.js +1 -1
- package/dist/commands/serve.js +1 -1
- package/dist/commands/verify.js +1 -1
- package/dist/core/adapters/gitleaks-secrets.d.ts +115 -0
- package/dist/core/adapters/gitleaks-secrets.d.ts.map +1 -0
- package/dist/core/adapters/gitleaks-secrets.js +410 -0
- package/dist/core/adapters/k6-perf.d.ts +86 -0
- package/dist/core/adapters/k6-perf.d.ts.map +1 -0
- package/dist/core/adapters/k6-perf.js +398 -0
- package/dist/core/adapters/osv-deps.d.ts +124 -0
- package/dist/core/adapters/osv-deps.d.ts.map +1 -0
- package/dist/core/adapters/osv-deps.js +372 -0
- package/dist/core/adapters/playwright-api.d.ts +82 -0
- package/dist/core/adapters/playwright-api.d.ts.map +1 -0
- package/dist/core/adapters/playwright-api.js +252 -0
- package/dist/core/adapters/playwright-ui.d.ts +115 -0
- package/dist/core/adapters/playwright-ui.d.ts.map +1 -0
- package/dist/core/adapters/playwright-ui.js +346 -0
- package/dist/core/adapters/semgrep-sast.d.ts +100 -0
- package/dist/core/adapters/semgrep-sast.d.ts.map +1 -0
- package/dist/core/adapters/semgrep-sast.js +322 -0
- package/dist/core/adapters/zap-dast.d.ts +134 -0
- package/dist/core/adapters/zap-dast.d.ts.map +1 -0
- package/dist/core/adapters/zap-dast.js +424 -0
- package/dist/core/hooks/compose.d.ts +62 -0
- package/dist/core/hooks/compose.d.ts.map +1 -0
- package/dist/core/hooks/compose.js +225 -0
- package/dist/core/hooks/runner.d.ts +69 -0
- package/dist/core/hooks/runner.d.ts.map +1 -0
- package/dist/core/hooks/runner.js +303 -0
- package/dist/core/index.d.ts +74 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +39 -0
- package/dist/core/pack/migrator.d.ts +52 -0
- package/dist/core/pack/migrator.d.ts.map +1 -0
- package/dist/core/pack/migrator.js +304 -0
- package/dist/core/pack/validator.d.ts +43 -0
- package/dist/core/pack/validator.d.ts.map +1 -0
- package/dist/core/pack/validator.js +292 -0
- package/dist/core/proof/bundle.d.ts +138 -0
- package/dist/core/proof/bundle.d.ts.map +1 -0
- package/dist/core/proof/bundle.js +160 -0
- package/dist/core/proof/canonicalize.d.ts +48 -0
- package/dist/core/proof/canonicalize.d.ts.map +1 -0
- package/dist/core/proof/canonicalize.js +105 -0
- package/dist/core/proof/index.d.ts +14 -0
- package/dist/core/proof/index.d.ts.map +1 -0
- package/dist/core/proof/index.js +18 -0
- package/dist/core/proof/schema.d.ts +218 -0
- package/dist/core/proof/schema.d.ts.map +1 -0
- package/dist/core/proof/schema.js +263 -0
- package/dist/core/proof/signer.d.ts +112 -0
- package/dist/core/proof/signer.d.ts.map +1 -0
- package/dist/core/proof/signer.js +226 -0
- package/dist/core/proof/verifier.d.ts +98 -0
- package/dist/core/proof/verifier.d.ts.map +1 -0
- package/dist/core/proof/verifier.js +302 -0
- package/dist/core/runner/phase3-runner.d.ts +102 -0
- package/dist/core/runner/phase3-runner.d.ts.map +1 -0
- package/dist/core/runner/phase3-runner.js +471 -0
- package/dist/core/secrets/crypto.d.ts +76 -0
- package/dist/core/secrets/crypto.d.ts.map +1 -0
- package/dist/core/secrets/crypto.js +225 -0
- package/dist/core/secrets/manager.d.ts +77 -0
- package/dist/core/secrets/manager.d.ts.map +1 -0
- package/dist/core/secrets/manager.js +219 -0
- package/dist/core/security/redaction-patterns-extended.d.ts +28 -0
- package/dist/core/security/redaction-patterns-extended.d.ts.map +1 -0
- package/dist/core/security/redaction-patterns-extended.js +247 -0
- package/dist/core/security/redactor.d.ts +72 -0
- package/dist/core/security/redactor.d.ts.map +1 -0
- package/dist/core/security/redactor.js +279 -0
- package/dist/core/serve/diagnostics-collector.d.ts +33 -0
- package/dist/core/serve/diagnostics-collector.d.ts.map +1 -0
- package/dist/core/serve/diagnostics-collector.js +149 -0
- package/dist/core/serve/health-checker.d.ts +45 -0
- package/dist/core/serve/health-checker.d.ts.map +1 -0
- package/dist/core/serve/health-checker.js +219 -0
- package/dist/core/serve/index.d.ts +9 -0
- package/dist/core/serve/index.d.ts.map +1 -0
- package/dist/core/serve/index.js +8 -0
- package/dist/core/serve/metrics-collector.d.ts +25 -0
- package/dist/core/serve/metrics-collector.d.ts.map +1 -0
- package/dist/core/serve/metrics-collector.js +322 -0
- package/dist/core/serve/process-manager.d.ts +37 -0
- package/dist/core/serve/process-manager.d.ts.map +1 -0
- package/dist/core/serve/process-manager.js +213 -0
- package/dist/core/serve/server.d.ts +37 -0
- package/dist/core/serve/server.d.ts.map +1 -0
- package/dist/core/serve/server.js +191 -0
- package/dist/core/types/pack-v1.d.ts +162 -0
- package/dist/core/types/pack-v1.d.ts.map +1 -0
- package/dist/core/types/pack-v1.js +5 -0
- package/dist/core/types/trust-score.d.ts +70 -0
- package/dist/core/types/trust-score.d.ts.map +1 -0
- package/dist/core/types/trust-score.js +191 -0
- package/dist/core/vault/cas.d.ts +87 -0
- package/dist/core/vault/cas.d.ts.map +1 -0
- package/dist/core/vault/cas.js +255 -0
- package/dist/core/vault/index.d.ts +205 -0
- package/dist/core/vault/index.d.ts.map +1 -0
- package/dist/core/vault/index.js +631 -0
- package/package.json +13 -6
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ed25519 Signature Operations
|
|
3
|
+
*
|
|
4
|
+
* Provides key generation, signing, and verification using Ed25519.
|
|
5
|
+
* Uses tweetnacl for cryptographic operations.
|
|
6
|
+
*
|
|
7
|
+
* @see docs/rfc/proof-bundle-v1.md#5-signature-procedure
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Ed25519 key pair
|
|
11
|
+
*/
|
|
12
|
+
export interface KeyPair {
|
|
13
|
+
publicKey: Uint8Array;
|
|
14
|
+
secretKey: Uint8Array;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Key storage paths
|
|
18
|
+
*/
|
|
19
|
+
export interface KeyPaths {
|
|
20
|
+
privateKey: string;
|
|
21
|
+
publicKey: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get default key storage directory
|
|
25
|
+
*/
|
|
26
|
+
export declare function getKeyDirectory(): string;
|
|
27
|
+
/**
|
|
28
|
+
* Get key file paths
|
|
29
|
+
*/
|
|
30
|
+
export declare function getKeyPaths(): KeyPaths;
|
|
31
|
+
/**
|
|
32
|
+
* Generate new Ed25519 key pair
|
|
33
|
+
*
|
|
34
|
+
* @returns Key pair (public + secret)
|
|
35
|
+
*/
|
|
36
|
+
export declare function generateKeys(): KeyPair;
|
|
37
|
+
/**
|
|
38
|
+
* Save key pair to disk
|
|
39
|
+
*
|
|
40
|
+
* @param keyPair - Key pair to save
|
|
41
|
+
* @param paths - Optional custom paths (defaults to ~/.qa360/keys/)
|
|
42
|
+
*/
|
|
43
|
+
export declare function saveKeys(keyPair: KeyPair, paths?: KeyPaths): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Load key pair from disk
|
|
46
|
+
*
|
|
47
|
+
* @param paths - Optional custom paths (defaults to ~/.qa360/keys/)
|
|
48
|
+
* @returns Key pair
|
|
49
|
+
* @throws Error if keys don't exist
|
|
50
|
+
*/
|
|
51
|
+
export declare function loadKeys(paths?: KeyPaths): Promise<KeyPair>;
|
|
52
|
+
/**
|
|
53
|
+
* Check if keys exist
|
|
54
|
+
*
|
|
55
|
+
* @param paths - Optional custom paths
|
|
56
|
+
* @returns true if both keys exist
|
|
57
|
+
*/
|
|
58
|
+
export declare function keysExist(paths?: KeyPaths): Promise<boolean>;
|
|
59
|
+
/**
|
|
60
|
+
* Initialize keys (generate if they don't exist)
|
|
61
|
+
*
|
|
62
|
+
* @param paths - Optional custom paths
|
|
63
|
+
* @returns Key pair (existing or newly generated)
|
|
64
|
+
*/
|
|
65
|
+
export declare function initializeKeys(paths?: KeyPaths): Promise<KeyPair>;
|
|
66
|
+
/**
|
|
67
|
+
* Ensure proof keys exist (generate if missing)
|
|
68
|
+
*
|
|
69
|
+
* @param homeDir - QA360 home directory
|
|
70
|
+
* @returns Result with creation status, paths, and optional keys
|
|
71
|
+
*/
|
|
72
|
+
export declare function ensureProofKeys(homeDir: string): Promise<{
|
|
73
|
+
created: boolean;
|
|
74
|
+
paths: {
|
|
75
|
+
pub: string;
|
|
76
|
+
priv: string;
|
|
77
|
+
};
|
|
78
|
+
keys?: KeyPair;
|
|
79
|
+
}>;
|
|
80
|
+
/**
|
|
81
|
+
* Compute SHA-256 hash of data
|
|
82
|
+
*
|
|
83
|
+
* @param data - Data to hash (UTF-8 string)
|
|
84
|
+
* @returns SHA-256 hash as Buffer
|
|
85
|
+
*/
|
|
86
|
+
export declare function sha256(data: string): Buffer;
|
|
87
|
+
/**
|
|
88
|
+
* Sign data with Ed25519
|
|
89
|
+
*
|
|
90
|
+
* @param data - Data to sign (canonical JSON string)
|
|
91
|
+
* @param secretKey - Ed25519 secret key (64 bytes)
|
|
92
|
+
* @returns Base64-encoded signature (88 chars)
|
|
93
|
+
*/
|
|
94
|
+
export declare function sign(data: string, secretKey: Uint8Array): string;
|
|
95
|
+
/**
|
|
96
|
+
* Verify Ed25519 signature
|
|
97
|
+
*
|
|
98
|
+
* @param data - Original data (canonical JSON string)
|
|
99
|
+
* @param signatureB64 - Base64-encoded signature
|
|
100
|
+
* @param publicKey - Ed25519 public key (32 bytes)
|
|
101
|
+
* @returns true if signature is valid
|
|
102
|
+
*/
|
|
103
|
+
export declare function verify(data: string, signatureB64: string, publicKey: Uint8Array): boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Sign and verify roundtrip test
|
|
106
|
+
*
|
|
107
|
+
* @param data - Test data
|
|
108
|
+
* @param keyPair - Key pair to test
|
|
109
|
+
* @returns true if roundtrip succeeds
|
|
110
|
+
*/
|
|
111
|
+
export declare function testRoundtrip(data: string, keyPair: KeyPair): boolean;
|
|
112
|
+
//# sourceMappingURL=signer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../../../src/core/proof/signer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAgBH;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,UAAU,CAAC;IACtB,SAAS,EAAE,UAAU,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,QAAQ,CAMtC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAMtC;AAED;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBhF;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAcjE;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,KAAK,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAUlE;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,KAAK,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAQvE;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9D,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC,CAgED;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED;;;;;;GAMG;AACH,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,MAAM,CAShE;AAED;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAazF;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAGrE"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ed25519 Signature Operations
|
|
3
|
+
*
|
|
4
|
+
* Provides key generation, signing, and verification using Ed25519.
|
|
5
|
+
* Uses tweetnacl for cryptographic operations.
|
|
6
|
+
*
|
|
7
|
+
* @see docs/rfc/proof-bundle-v1.md#5-signature-procedure
|
|
8
|
+
*/
|
|
9
|
+
import * as naclModule from 'tweetnacl';
|
|
10
|
+
import { createHash } from 'crypto';
|
|
11
|
+
import { promises as fs } from 'fs';
|
|
12
|
+
import { join } from 'path';
|
|
13
|
+
import { homedir } from 'os';
|
|
14
|
+
// Handle both ESM and CJS imports
|
|
15
|
+
const nacl = naclModule.default || naclModule;
|
|
16
|
+
// Validate tweetnacl import
|
|
17
|
+
if (!nacl?.sign?.keyPair) {
|
|
18
|
+
throw new Error('tweetnacl not loaded correctly - sign.keyPair is undefined');
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get default key storage directory
|
|
22
|
+
*/
|
|
23
|
+
export function getKeyDirectory() {
|
|
24
|
+
return join(homedir(), '.qa360', 'keys');
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get key file paths
|
|
28
|
+
*/
|
|
29
|
+
export function getKeyPaths() {
|
|
30
|
+
const keyDir = getKeyDirectory();
|
|
31
|
+
return {
|
|
32
|
+
privateKey: join(keyDir, 'ed25519.key'),
|
|
33
|
+
publicKey: join(keyDir, 'ed25519.pub'),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Generate new Ed25519 key pair
|
|
38
|
+
*
|
|
39
|
+
* @returns Key pair (public + secret)
|
|
40
|
+
*/
|
|
41
|
+
export function generateKeys() {
|
|
42
|
+
const keyPair = nacl.sign.keyPair();
|
|
43
|
+
return {
|
|
44
|
+
publicKey: keyPair.publicKey,
|
|
45
|
+
secretKey: keyPair.secretKey,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Save key pair to disk
|
|
50
|
+
*
|
|
51
|
+
* @param keyPair - Key pair to save
|
|
52
|
+
* @param paths - Optional custom paths (defaults to ~/.qa360/keys/)
|
|
53
|
+
*/
|
|
54
|
+
export async function saveKeys(keyPair, paths) {
|
|
55
|
+
const keyPaths = paths || getKeyPaths();
|
|
56
|
+
const keyDir = getKeyDirectory();
|
|
57
|
+
// Create directory if it doesn't exist
|
|
58
|
+
await fs.mkdir(keyDir, { recursive: true, mode: 0o700 });
|
|
59
|
+
// Save private key (chmod 600)
|
|
60
|
+
await fs.writeFile(keyPaths.privateKey, Buffer.from(keyPair.secretKey).toString('base64'), { mode: 0o600 });
|
|
61
|
+
// Save public key (chmod 644)
|
|
62
|
+
await fs.writeFile(keyPaths.publicKey, Buffer.from(keyPair.publicKey).toString('base64'), { mode: 0o644 });
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Load key pair from disk
|
|
66
|
+
*
|
|
67
|
+
* @param paths - Optional custom paths (defaults to ~/.qa360/keys/)
|
|
68
|
+
* @returns Key pair
|
|
69
|
+
* @throws Error if keys don't exist
|
|
70
|
+
*/
|
|
71
|
+
export async function loadKeys(paths) {
|
|
72
|
+
const keyPaths = paths || getKeyPaths();
|
|
73
|
+
try {
|
|
74
|
+
const privateKeyB64 = await fs.readFile(keyPaths.privateKey, 'utf-8');
|
|
75
|
+
const publicKeyB64 = await fs.readFile(keyPaths.publicKey, 'utf-8');
|
|
76
|
+
return {
|
|
77
|
+
secretKey: new Uint8Array(Buffer.from(privateKeyB64.trim(), 'base64')),
|
|
78
|
+
publicKey: new Uint8Array(Buffer.from(publicKeyB64.trim(), 'base64')),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
throw new Error(`Failed to load keys: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Check if keys exist
|
|
87
|
+
*
|
|
88
|
+
* @param paths - Optional custom paths
|
|
89
|
+
* @returns true if both keys exist
|
|
90
|
+
*/
|
|
91
|
+
export async function keysExist(paths) {
|
|
92
|
+
const keyPaths = paths || getKeyPaths();
|
|
93
|
+
try {
|
|
94
|
+
await fs.access(keyPaths.privateKey);
|
|
95
|
+
await fs.access(keyPaths.publicKey);
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Initialize keys (generate if they don't exist)
|
|
104
|
+
*
|
|
105
|
+
* @param paths - Optional custom paths
|
|
106
|
+
* @returns Key pair (existing or newly generated)
|
|
107
|
+
*/
|
|
108
|
+
export async function initializeKeys(paths) {
|
|
109
|
+
if (await keysExist(paths)) {
|
|
110
|
+
return loadKeys(paths);
|
|
111
|
+
}
|
|
112
|
+
const keyPair = generateKeys();
|
|
113
|
+
await saveKeys(keyPair, paths);
|
|
114
|
+
return keyPair;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Ensure proof keys exist (generate if missing)
|
|
118
|
+
*
|
|
119
|
+
* @param homeDir - QA360 home directory
|
|
120
|
+
* @returns Result with creation status, paths, and optional keys
|
|
121
|
+
*/
|
|
122
|
+
export async function ensureProofKeys(homeDir) {
|
|
123
|
+
const keyDir = join(homeDir, 'keys');
|
|
124
|
+
const paths = {
|
|
125
|
+
pub: join(keyDir, 'ed25519.pub'),
|
|
126
|
+
priv: join(keyDir, 'ed25519.key'),
|
|
127
|
+
};
|
|
128
|
+
// Check if keys already exist
|
|
129
|
+
try {
|
|
130
|
+
await fs.access(paths.priv);
|
|
131
|
+
await fs.access(paths.pub);
|
|
132
|
+
// Keys exist, validate them
|
|
133
|
+
const privateKeyB64 = await fs.readFile(paths.priv, 'utf-8');
|
|
134
|
+
const publicKeyB64 = await fs.readFile(paths.pub, 'utf-8');
|
|
135
|
+
const secretKey = new Uint8Array(Buffer.from(privateKeyB64.trim(), 'base64'));
|
|
136
|
+
const publicKey = new Uint8Array(Buffer.from(publicKeyB64.trim(), 'base64'));
|
|
137
|
+
// Validate key sizes
|
|
138
|
+
if (publicKey.length !== 32) {
|
|
139
|
+
throw new Error(`Invalid public key size: ${publicKey.length} (expected 32)`);
|
|
140
|
+
}
|
|
141
|
+
if (secretKey.length !== 64) {
|
|
142
|
+
throw new Error(`Invalid secret key size: ${secretKey.length} (expected 64)`);
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
created: false,
|
|
146
|
+
paths,
|
|
147
|
+
keys: { publicKey, secretKey },
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// Keys don't exist or are invalid, generate new ones
|
|
152
|
+
await fs.mkdir(keyDir, { recursive: true, mode: 0o700 });
|
|
153
|
+
const keyPair = generateKeys();
|
|
154
|
+
// Validate generated keys
|
|
155
|
+
if (!keyPair.publicKey || keyPair.publicKey.length !== 32) {
|
|
156
|
+
throw new Error('Key generation failed: invalid public key');
|
|
157
|
+
}
|
|
158
|
+
if (!keyPair.secretKey || keyPair.secretKey.length !== 64) {
|
|
159
|
+
throw new Error('Key generation failed: invalid secret key');
|
|
160
|
+
}
|
|
161
|
+
// Save keys
|
|
162
|
+
await fs.writeFile(paths.priv, Buffer.from(keyPair.secretKey).toString('base64'), { mode: 0o600 });
|
|
163
|
+
await fs.writeFile(paths.pub, Buffer.from(keyPair.publicKey).toString('base64'), { mode: 0o644 });
|
|
164
|
+
return {
|
|
165
|
+
created: true,
|
|
166
|
+
paths,
|
|
167
|
+
keys: keyPair,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Compute SHA-256 hash of data
|
|
173
|
+
*
|
|
174
|
+
* @param data - Data to hash (UTF-8 string)
|
|
175
|
+
* @returns SHA-256 hash as Buffer
|
|
176
|
+
*/
|
|
177
|
+
export function sha256(data) {
|
|
178
|
+
return createHash('sha256').update(data, 'utf-8').digest();
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Sign data with Ed25519
|
|
182
|
+
*
|
|
183
|
+
* @param data - Data to sign (canonical JSON string)
|
|
184
|
+
* @param secretKey - Ed25519 secret key (64 bytes)
|
|
185
|
+
* @returns Base64-encoded signature (88 chars)
|
|
186
|
+
*/
|
|
187
|
+
export function sign(data, secretKey) {
|
|
188
|
+
// Hash the data first (sign the hash, not the raw data)
|
|
189
|
+
const hash = sha256(data);
|
|
190
|
+
// Sign the hash
|
|
191
|
+
const signature = nacl.sign.detached(hash, secretKey);
|
|
192
|
+
// Return base64-encoded signature
|
|
193
|
+
return Buffer.from(signature).toString('base64');
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Verify Ed25519 signature
|
|
197
|
+
*
|
|
198
|
+
* @param data - Original data (canonical JSON string)
|
|
199
|
+
* @param signatureB64 - Base64-encoded signature
|
|
200
|
+
* @param publicKey - Ed25519 public key (32 bytes)
|
|
201
|
+
* @returns true if signature is valid
|
|
202
|
+
*/
|
|
203
|
+
export function verify(data, signatureB64, publicKey) {
|
|
204
|
+
try {
|
|
205
|
+
// Hash the data
|
|
206
|
+
const hash = sha256(data);
|
|
207
|
+
// Decode signature
|
|
208
|
+
const signature = new Uint8Array(Buffer.from(signatureB64, 'base64'));
|
|
209
|
+
// Verify signature
|
|
210
|
+
return nacl.sign.detached.verify(hash, signature, publicKey);
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Sign and verify roundtrip test
|
|
218
|
+
*
|
|
219
|
+
* @param data - Test data
|
|
220
|
+
* @param keyPair - Key pair to test
|
|
221
|
+
* @returns true if roundtrip succeeds
|
|
222
|
+
*/
|
|
223
|
+
export function testRoundtrip(data, keyPair) {
|
|
224
|
+
const signature = sign(data, keyPair.secretKey);
|
|
225
|
+
return verify(data, signature, keyPair.publicKey);
|
|
226
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proof Bundle Verification
|
|
3
|
+
*
|
|
4
|
+
* Verifies cryptographic signatures and integrity of proof bundles.
|
|
5
|
+
*
|
|
6
|
+
* @see docs/rfc/proof-bundle-v1.md#6-verification-procedure
|
|
7
|
+
*/
|
|
8
|
+
import type { ProofBundle, Artifact } from './bundle.js';
|
|
9
|
+
/**
|
|
10
|
+
* Verification result
|
|
11
|
+
*/
|
|
12
|
+
export interface VerificationResult {
|
|
13
|
+
valid: boolean;
|
|
14
|
+
code: VerificationCode;
|
|
15
|
+
message: string;
|
|
16
|
+
details?: VerificationDetails;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Verification error codes (matches RFC)
|
|
20
|
+
*/
|
|
21
|
+
export declare enum VerificationCode {
|
|
22
|
+
PROOF_OK = 0,
|
|
23
|
+
PROOF_INVALID_SIG = 1,
|
|
24
|
+
PROOF_INVALID_SCHEMA = 2,
|
|
25
|
+
PROOF_ARTIFACT_MISMATCH = 3,
|
|
26
|
+
PROOF_MISSING_KEY = 4,
|
|
27
|
+
PROOF_MALFORMED = 5
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Verification details
|
|
31
|
+
*/
|
|
32
|
+
export interface VerificationDetails {
|
|
33
|
+
signerId?: string;
|
|
34
|
+
hash?: string;
|
|
35
|
+
artifactsVerified?: number;
|
|
36
|
+
artifactsTotal?: number;
|
|
37
|
+
trustScore?: number;
|
|
38
|
+
runId?: string;
|
|
39
|
+
startedAt?: string;
|
|
40
|
+
finishedAt?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Artifact verification options
|
|
44
|
+
*/
|
|
45
|
+
export interface ArtifactVerificationOptions {
|
|
46
|
+
basePath?: string;
|
|
47
|
+
skipMissing?: boolean;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Verify proof bundle signature
|
|
51
|
+
*
|
|
52
|
+
* @param bundle - Proof bundle to verify
|
|
53
|
+
* @param publicKey - Optional public key (loads from ~/.qa360/keys if not provided)
|
|
54
|
+
* @returns Verification result
|
|
55
|
+
*/
|
|
56
|
+
export declare function verifyProofBundle(bundle: ProofBundle, publicKey?: Uint8Array): Promise<VerificationResult>;
|
|
57
|
+
/**
|
|
58
|
+
* Verify artifact integrity
|
|
59
|
+
*
|
|
60
|
+
* @param artifact - Artifact metadata
|
|
61
|
+
* @param filePath - Path to artifact file
|
|
62
|
+
* @returns true if hash matches
|
|
63
|
+
*/
|
|
64
|
+
export declare function verifyArtifact(artifact: Artifact, filePath: string): Promise<boolean>;
|
|
65
|
+
/**
|
|
66
|
+
* Verify all artifacts in proof bundle
|
|
67
|
+
*
|
|
68
|
+
* @param bundle - Proof bundle
|
|
69
|
+
* @param options - Verification options
|
|
70
|
+
* @returns Verification result with artifact details
|
|
71
|
+
*/
|
|
72
|
+
export declare function verifyArtifacts(bundle: ProofBundle, options?: ArtifactVerificationOptions): Promise<VerificationResult>;
|
|
73
|
+
/**
|
|
74
|
+
* Verify proof bundle and artifacts (complete verification)
|
|
75
|
+
*
|
|
76
|
+
* @param bundle - Proof bundle
|
|
77
|
+
* @param options - Artifact verification options
|
|
78
|
+
* @param publicKey - Optional public key
|
|
79
|
+
* @returns Complete verification result
|
|
80
|
+
*/
|
|
81
|
+
export declare function verifyComplete(bundle: ProofBundle, options?: ArtifactVerificationOptions, publicKey?: Uint8Array): Promise<VerificationResult>;
|
|
82
|
+
/**
|
|
83
|
+
* Load and verify proof bundle from file
|
|
84
|
+
*
|
|
85
|
+
* @param filePath - Path to proof bundle JSON file
|
|
86
|
+
* @param options - Artifact verification options
|
|
87
|
+
* @param publicKey - Optional public key
|
|
88
|
+
* @returns Verification result
|
|
89
|
+
*/
|
|
90
|
+
export declare function verifyProofFile(filePath: string, options?: ArtifactVerificationOptions, publicKey?: Uint8Array): Promise<VerificationResult>;
|
|
91
|
+
/**
|
|
92
|
+
* Verify Phase3 proof format (simplified)
|
|
93
|
+
*
|
|
94
|
+
* @param filePath - Path to Phase3 proof JSON
|
|
95
|
+
* @returns Verification result
|
|
96
|
+
*/
|
|
97
|
+
export declare function verifyPhase3Proof(filePath: string): Promise<VerificationResult>;
|
|
98
|
+
//# sourceMappingURL=verifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifier.d.ts","sourceRoot":"","sources":["../../../src/core/proof/verifier.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B;AAED;;GAEG;AACH,oBAAY,gBAAgB;IAC1B,QAAQ,IAAI;IACZ,iBAAiB,IAAI;IACrB,oBAAoB,IAAI;IACxB,uBAAuB,IAAI;IAC3B,iBAAiB,IAAI;IACrB,eAAe,IAAI;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,WAAW,EACnB,SAAS,CAAC,EAAE,UAAU,GACrB,OAAO,CAAC,kBAAkB,CAAC,CAmF7B;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAS3F;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC,kBAAkB,CAAC,CAkD7B;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,2BAAgC,EACzC,SAAS,CAAC,EAAE,UAAU,GACrB,OAAO,CAAC,kBAAkB,CAAC,CAyB7B;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,2BAAgC,EACzC,SAAS,CAAC,EAAE,UAAU,GACrB,OAAO,CAAC,kBAAkB,CAAC,CAY7B;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAmErF"}
|