Repository navigation
Expand file tree
/
Copy pathbackend-verifier.ts
More file actions
246 lines (208 loc) Β· 9.42 KB
/
Copy pathbackend-verifier.ts
File metadata and controls
246 lines (208 loc) Β· 9.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
// Backend verification test - verifies frontend-generated signatures
import { SigningService, CryptoUtils } from './packages/security/src/index';
import type { EnactDocument, Signature } from './packages/security/src/types';
console.log("π₯οΈ Backend Verification Test");
console.log("Verifying frontend-generated signatures...\n");
// This will be populated by the frontend test output
// Users should copy the frontendTestData from frontend-signer.ts output
let frontendTestData: any = null;
// For this demo, let's simulate the frontend data
// In real usage, this would come from the frontend test output
async function simulateFrontendData() {
// Import the frontend signing service to generate test data
const { SigningService: FrontendSigning, CryptoUtils: FrontendCrypto } =
await import('./packages/security-web/src/index');
const testTool: EnactDocument = {
name: "frontend-test/file-formatter",
description: "Formats code files using frontend-generated signature",
command: "npx prettier@3.3.3 --write '${file}' --config .prettierrc",
enact: "1.0.0",
version: "2.1.0",
from: "node:18-alpine",
timeout: "45s",
annotations: {
destructiveHint: true,
title: "Frontend File Formatter",
readOnlyHint: false,
idempotentHint: true
},
env: {
PRETTIER_CONFIG: {
description: "Prettier configuration file path",
required: false,
default: ".prettierrc"
},
NODE_ENV: {
description: "Node environment for execution",
required: true,
default: "production"
}
},
inputSchema: {
type: "object",
properties: {
file: {
type: "string",
description: "Path to file to format",
pattern: "\\.(js|ts|jsx|tsx|json|css|scss|md)$"
},
parser: {
type: "string",
enum: ["typescript", "babel", "json", "css", "markdown"],
description: "Parser to use for formatting",
default: "typescript"
}
},
required: ["file"]
},
tags: ["formatting", "code-quality", "prettier", "frontend"],
license: "MIT",
authors: [
{ name: "Frontend Dev Team", email: "frontend@enact.dev" },
{ name: "Security Team", email: "security@enact.dev" }
],
id: "frontend-tool-test-12345",
content: "Frontend-generated tool definition for cross-platform testing",
timestamp: Date.now(),
metadata: {
createdBy: "frontend-test",
platform: "browser",
testSuite: "cross-platform-verification",
signatureMethod: "frontend-web-crypto"
}
};
const keyPair = FrontendCrypto.generateKeyPair();
const enactSignature = FrontendSigning.signDocument(testTool, keyPair.privateKey, {
useEnactDefaults: true
});
const canonicalDocument = FrontendSigning.getCanonicalDocument(testTool, {
useEnactDefaults: true
});
return {
tool: testTool,
signature: enactSignature,
keyPair: keyPair,
canonicalDocument: canonicalDocument,
metadata: {
frontendPlatform: "browser/web-crypto",
signingOptions: { useEnactDefaults: true },
signedFields: Object.keys(canonicalDocument),
testTimestamp: new Date().toISOString()
}
};
}
async function runBackendVerification() {
console.log("π Generating frontend signature for testing...");
frontendTestData = await simulateFrontendData();
console.log("β
Frontend test data received:");
console.log(`Tool: ${frontendTestData.tool.name}`);
console.log(`Description: ${frontendTestData.tool.description}`);
console.log(`Frontend signature: ${frontendTestData.signature.signature.substring(0, 40)}...`);
console.log(`Frontend public key: ${frontendTestData.signature.publicKey.substring(0, 40)}...`);
console.log(`Signed fields: ${frontendTestData.metadata.signedFields.join(', ')}\n`);
// Test 1: Backend verification of frontend signature
console.log("π Test 1: Backend verifying frontend signature...");
const backendVerification = SigningService.verifyDocument(
frontendTestData.tool,
frontendTestData.signature,
{
useEnactDefaults: true
}
);
console.log(`Backend verification result: ${backendVerification ? 'β
VALID' : 'β INVALID'}`);
if (backendVerification) {
console.log("π SUCCESS! Backend successfully verified frontend signature!");
} else {
console.log("β FAILURE! Backend could not verify frontend signature!");
return;
}
// Test 2: Compare canonical documents
console.log("\nπ Test 2: Comparing canonical documents...");
const backendCanonical = SigningService.getCanonicalDocument(frontendTestData.tool, {
useEnactDefaults: true
});
const canonicalMatch = JSON.stringify(frontendTestData.canonicalDocument) ===
JSON.stringify(backendCanonical);
console.log(`Canonical documents match: ${canonicalMatch ? 'β
YES' : 'β NO'}`);
if (canonicalMatch) {
console.log("π SUCCESS! Frontend and backend produce identical canonical documents!");
} else {
console.log("β DIFFERENCE detected in canonical documents:");
console.log("Frontend canonical:", JSON.stringify(frontendTestData.canonicalDocument, null, 2));
console.log("Backend canonical:", JSON.stringify(backendCanonical, null, 2));
}
// Test 3: Backend signature of same document
console.log("\nπ Test 3: Backend signing same document...");
const backendSignature = SigningService.signDocument(
frontendTestData.tool,
frontendTestData.keyPair.privateKey,
{
useEnactDefaults: true
}
);
console.log(`Backend signature: ${backendSignature.signature.substring(0, 40)}...`);
console.log(`Frontend signature: ${frontendTestData.signature.signature.substring(0, 40)}...`);
const signaturesMatch = backendSignature.signature === frontendTestData.signature.signature;
console.log(`Signatures match: ${signaturesMatch ? 'β
YES' : 'β NO'}`);
if (signaturesMatch) {
console.log("π PERFECT! Frontend and backend produce identical signatures!");
} else {
console.log("βΉοΈ Different signatures (expected - they have different timestamps)");
}
// Test 4: Cross-verify both signatures
console.log("\nπ Test 4: Cross-verification test...");
const frontendVerifiesBackend = SigningService.verifyDocument(
frontendTestData.tool,
backendSignature,
{ useEnactDefaults: true }
);
const backendVerifiesFrontend = SigningService.verifyDocument(
frontendTestData.tool,
frontendTestData.signature,
{ useEnactDefaults: true }
);
console.log(`Backend verifies frontend signature: ${backendVerifiesFrontend ? 'β
YES' : 'β NO'}`);
console.log(`Backend verifies backend signature: ${frontendVerifiesBackend ? 'β
YES' : 'β NO'}`);
// Test 5: Key derivation consistency
console.log("\nπ Test 5: Key derivation consistency...");
const backendDerivedKey = CryptoUtils.getPublicKeyFromPrivate(frontendTestData.keyPair.privateKey);
const frontendPublicKey = frontendTestData.keyPair.publicKey;
const keysMatch = backendDerivedKey === frontendPublicKey;
console.log(`Derived public keys match: ${keysMatch ? 'β
YES' : 'β NO'}`);
console.log(`Backend derived: ${backendDerivedKey.substring(0, 40)}...`);
console.log(`Frontend public: ${frontendPublicKey.substring(0, 40)}...`);
// Test 6: Hash function consistency
console.log("\nπ Test 6: Hash function consistency...");
const testString = JSON.stringify(backendCanonical);
const backendHash = CryptoUtils.hash(testString);
// Import frontend crypto for comparison
const { CryptoUtils: FrontendCrypto } = await import('./packages/security-web/src/index');
const frontendHash = FrontendCrypto.hash(testString);
const hashesMatch = backendHash === frontendHash;
console.log(`Hash functions match: ${hashesMatch ? 'β
YES' : 'β NO'}`);
console.log(`Backend hash: ${backendHash.substring(0, 40)}...`);
console.log(`Frontend hash: ${frontendHash.substring(0, 40)}...`);
// Summary
console.log("\nπ Cross-Platform Compatibility Summary:");
console.log(`β
Backend verifies frontend signature: ${backendVerifiesFrontend ? 'PASS' : 'FAIL'}`);
console.log(`β
Canonical documents identical: ${canonicalMatch ? 'PASS' : 'FAIL'}`);
console.log(`β
Key derivation consistent: ${keysMatch ? 'PASS' : 'FAIL'}`);
console.log(`β
Hash functions consistent: ${hashesMatch ? 'PASS' : 'FAIL'}`);
console.log(`β
Cross-verification works: ${frontendVerifiesBackend && backendVerifiesFrontend ? 'PASS' : 'FAIL'}`);
const allTestsPass = backendVerifiesFrontend && canonicalMatch && keysMatch &&
hashesMatch && frontendVerifiesBackend;
console.log(`\nπ― Overall result: ${allTestsPass ? 'π ALL TESTS PASS' : 'β SOME TESTS FAILED'}`);
if (allTestsPass) {
console.log("\nπ Cross-platform compatibility CONFIRMED!");
console.log(" β
Frontend signatures verify on backend");
console.log(" β
Backend signatures verify on frontend");
console.log(" β
Canonical JSON generation is identical");
console.log(" β
Cryptographic functions are consistent");
console.log(" β
Enact Protocol field selection works across platforms");
console.log("\nπ Your security library is production-ready for cross-platform use!");
} else {
console.log("\nβ οΈ Some compatibility issues detected. Review the test results above.");
}
}
// Run the verification test
runBackendVerification().catch(console.error);