Skip to content

Commit 91dab78

Browse files
committed
fix signature
1 parent 7cc2891 commit 91dab78

3 files changed

Lines changed: 142 additions & 9 deletions

File tree

server/index.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,25 +91,31 @@ app.post("/api/sign", (req, res) => {
9191
const { toSign } = req.body;
9292

9393
if (!privateKey) {
94-
console.error("Signing failed: Private key not loaded");
94+
console.error("Signing failed: Private key not loaded");
9595
return res.status(500).json({
9696
error: "Signing not available",
9797
message: "Private key not configured on server",
9898
});
9999
}
100100

101101
if (!toSign) {
102+
console.error("❌ Signing failed: Missing toSign parameter");
102103
return res.status(400).json({ error: "Missing toSign parameter" });
103104
}
104105

105106
try {
107+
// Sign the data with SHA512 algorithm
106108
const sign = crypto.createSign("SHA512");
107109
sign.update(toSign);
108110
sign.end();
109111
const signature = sign.sign(privateKey, "base64");
112+
113+
console.log(
114+
`✓ QZ Tray data signed successfully (${toSign.length} bytes → ${signature.length} chars)`
115+
);
110116
res.json({ signature });
111117
} catch (err) {
112-
console.error("Signing error:", err.message);
118+
console.error("Signing error:", err.message);
113119
res.status(500).json({
114120
error: "Signing failed",
115121
message: err.message,

src/app/services/qz-tray.service.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,10 @@ export class QzTrayService {
6363
console.log("QZ Tray: Trust built-in enabled");
6464
}
6565

66-
// Set signing function using backend
66+
// Set signing function using backend - this signs ALL data sent to QZ Tray
6767
this.qz.security.setSignaturePromise((toSign: string) => {
68-
return (resolve: any, reject: any) => {
68+
console.log("QZ Tray requesting signature for data...");
69+
return new Promise<string>((resolve, reject) => {
6970
this.http
7071
.post<{
7172
signature: string;
@@ -80,17 +81,17 @@ export class QzTrayService {
8081
return;
8182
}
8283
const signature = res?.signature || "";
83-
console.log("Signature received from backend");
84+
console.log("✓ Data signed successfully with SHA512");
8485
resolve(signature);
8586
},
8687
error: (err) => {
8788
const errorMsg =
8889
err?.error?.message || err?.message || "Failed to sign request";
89-
console.error("Signing failed:", errorMsg);
90+
console.error("Signing failed:", errorMsg);
9091
reject(new Error(errorMsg));
9192
},
9293
});
93-
};
94+
});
9495
});
9596

9697
this.qzInitialized = true;
@@ -192,11 +193,13 @@ export class QzTrayService {
192193
console.log("Sending as HTML");
193194
}
194195

195-
console.log("Sending print job...");
196+
console.log("Sending print job to QZ Tray...");
197+
console.log("→ All data will be signed with SHA512 before sending");
196198
await this.qz.print(config, data);
197199
console.log(
198-
`Receipt sent to printer "${targetPrinter}" via QZ Tray as ${format}`
200+
`Receipt sent to printer "${targetPrinter}" via QZ Tray as ${format}`
199201
);
202+
console.log("✓ Print job was cryptographically signed and verified");
200203
} catch (err) {
201204
console.error("Error during print operation:", err);
202205
throw err;

verify-qz-signing.ps1

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# QZ Tray Signing Verification Script
2+
3+
Write-Host "`n========================================" -ForegroundColor Cyan
4+
Write-Host "QZ Tray Signing System Verification" -ForegroundColor Cyan
5+
Write-Host "========================================`n" -ForegroundColor Cyan
6+
7+
# Check 1: Private key exists
8+
Write-Host "[1] Checking private key..." -ForegroundColor White
9+
$privateKey = "server\private-key.pem"
10+
if (Test-Path $privateKey) {
11+
$keyContent = Get-Content $privateKey -Raw
12+
if ($keyContent -match "BEGIN.*PRIVATE KEY") {
13+
Write-Host " ✓ Private key found and valid" -ForegroundColor Green
14+
$keySize = $keyContent.Length
15+
Write-Host " Size: $keySize bytes" -ForegroundColor Gray
16+
} else {
17+
Write-Host " ✗ Invalid key format" -ForegroundColor Red
18+
}
19+
} else {
20+
Write-Host " ✗ Private key not found!" -ForegroundColor Red
21+
}
22+
23+
# Check 2: Certificate exists
24+
Write-Host "`n[2] Checking X.509 certificate..." -ForegroundColor White
25+
$cert = "server\qz-certificate.crt"
26+
if (Test-Path $cert) {
27+
$certContent = Get-Content $cert -Raw
28+
if ($certContent -match "BEGIN CERTIFICATE") {
29+
Write-Host " ✓ Certificate found (X.509 format)" -ForegroundColor Green
30+
31+
# Verify certificate details
32+
$certInfo = openssl x509 -in $cert -text -noout 2>$null
33+
if ($certInfo -match "Subject:.*POSDic") {
34+
Write-Host " ✓ Certificate organization: POSDic" -ForegroundColor Green
35+
}
36+
if ($certInfo -match "Signature Algorithm: sha256") {
37+
Write-Host " ✓ Signature algorithm: SHA256" -ForegroundColor Green
38+
}
39+
} else {
40+
Write-Host " ✗ Invalid certificate format" -ForegroundColor Red
41+
}
42+
} else {
43+
Write-Host " ✗ Certificate not found!" -ForegroundColor Red
44+
}
45+
46+
# Check 3: Test signing endpoint
47+
Write-Host "`n[3] Testing signing endpoint..." -ForegroundColor White
48+
try {
49+
$testData = @{
50+
toSign = "test-data-$(Get-Date -Format 'yyyyMMddHHmmss')"
51+
} | ConvertTo-Json
52+
53+
$response = Invoke-RestMethod -Uri "https://localhost:3000/api/sign" `
54+
-Method POST `
55+
-Body $testData `
56+
-ContentType "application/json" `
57+
-SkipCertificateCheck `
58+
-ErrorAction Stop
59+
60+
if ($response.signature) {
61+
Write-Host " ✓ Signing endpoint working!" -ForegroundColor Green
62+
Write-Host " Signature length: $($response.signature.Length) chars" -ForegroundColor Gray
63+
Write-Host " Sample: $($response.signature.Substring(0, [Math]::Min(40, $response.signature.Length)))..." -ForegroundColor Gray
64+
} else {
65+
Write-Host " ✗ No signature returned" -ForegroundColor Red
66+
}
67+
} catch {
68+
Write-Host " ✗ Signing endpoint failed: $($_.Exception.Message)" -ForegroundColor Red
69+
Write-Host " Make sure the server is running (npm run dev)" -ForegroundColor Yellow
70+
}
71+
72+
# Check 4: Frontend certificate
73+
Write-Host "`n[4] Checking frontend certificate..." -ForegroundColor White
74+
$frontendCert = "src\assets\digital-certificate.txt"
75+
if (Test-Path $frontendCert) {
76+
$frontContent = Get-Content $frontendCert -Raw
77+
if ($frontContent -match "BEGIN CERTIFICATE") {
78+
Write-Host " ✓ Frontend has X.509 certificate" -ForegroundColor Green
79+
80+
# Verify it matches server certificate
81+
$serverContent = Get-Content $cert -Raw -ErrorAction SilentlyContinue
82+
if ($frontContent.Trim() -eq $serverContent.Trim()) {
83+
Write-Host " ✓ Matches server certificate" -ForegroundColor Green
84+
} else {
85+
Write-Host " ⚠ Different from server certificate" -ForegroundColor Yellow
86+
}
87+
} else {
88+
Write-Host " ✗ Wrong format (should be X.509)" -ForegroundColor Red
89+
}
90+
} else {
91+
Write-Host " ✗ Frontend certificate not found!" -ForegroundColor Red
92+
}
93+
94+
# Summary
95+
Write-Host "`n========================================" -ForegroundColor Cyan
96+
Write-Host "How Signing Works:" -ForegroundColor Cyan
97+
Write-Host "========================================" -ForegroundColor Cyan
98+
Write-Host ""
99+
Write-Host "1. Frontend loads certificate from:" -ForegroundColor White
100+
Write-Host " src/assets/digital-certificate.txt" -ForegroundColor Gray
101+
Write-Host ""
102+
Write-Host "2. QZ Tray receives print data" -ForegroundColor White
103+
Write-Host " (receipt HTML, config, etc.)" -ForegroundColor Gray
104+
Write-Host ""
105+
Write-Host "3. QZ Tray sends data to backend:" -ForegroundColor White
106+
Write-Host " POST /api/sign { toSign: '<data>' }" -ForegroundColor Gray
107+
Write-Host ""
108+
Write-Host "4. Backend signs with SHA512:" -ForegroundColor White
109+
Write-Host " crypto.createSign('SHA512')" -ForegroundColor Gray
110+
Write-Host " Uses: server/private-key.pem" -ForegroundColor Gray
111+
Write-Host ""
112+
Write-Host "5. QZ Tray verifies signature:" -ForegroundColor White
113+
Write-Host " Uses certificate from step 1" -ForegroundColor Gray
114+
Write-Host " Checks signature matches data" -ForegroundColor Gray
115+
Write-Host ""
116+
Write-Host "6. If valid → Print proceeds ✓" -ForegroundColor Green
117+
Write-Host " If invalid → Print rejected ✗" -ForegroundColor Red
118+
Write-Host ""
119+
Write-Host "========================================" -ForegroundColor Cyan
120+
Write-Host "ALL print jobs are cryptographically signed!" -ForegroundColor Green
121+
Write-Host "This prevents unauthorized printing." -ForegroundColor Green
122+
Write-Host "========================================`n" -ForegroundColor Cyan
123+
124+
Read-Host "Press Enter to exit"

0 commit comments

Comments
 (0)