From 3f9008a18148839fe84f420e59b7cc6659078a6b Mon Sep 17 00:00:00 2001 From: Dominic Griesel Date: Tue, 3 Jan 2023 01:38:06 +0100 Subject: [PATCH] fix: trim surrounding whitespace from QR codes --- packages/core/src/security/QR.test.ts | 25 +++++++++++++++++++++++++ packages/core/src/security/QR.ts | 7 +++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/packages/core/src/security/QR.test.ts b/packages/core/src/security/QR.test.ts index 9c08cd9e6507..32a1a9051680 100644 --- a/packages/core/src/security/QR.test.ts +++ b/packages/core/src/security/QR.test.ts @@ -111,3 +111,28 @@ test("QR code parsing -> Example case: Acme Light Dimmer w/o SmartStart", (t) => productId: 0x0003, }); }); + +test("QR code parsing -> ignore surrounding whitespace", (t) => { + const result = parseQRCodeString( + " 900032782003515253545541424344453132333435212223242500100435301537022065520001000000300578 ", + ); + t.deepEqual(result, { + version: QRCodeVersion.S2, + securityClasses: [ + SecurityClass.S2_Unauthenticated, + SecurityClass.S2_Authenticated, + ], + requestedSecurityClasses: [ + SecurityClass.S2_Unauthenticated, + SecurityClass.S2_Authenticated, + ], + dsk: "51525-35455-41424-34445-31323-33435-21222-32425", + applicationVersion: "2.66", + genericDeviceClass: 0x11, + specificDeviceClass: 0x01, + installerIconType: 0x0601, + manufacturerId: 0xfff0, + productType: 0x0064, + productId: 0x0003, + }); +}); diff --git a/packages/core/src/security/QR.ts b/packages/core/src/security/QR.ts index 0e1998699d77..46d74cfaef70 100644 --- a/packages/core/src/security/QR.ts +++ b/packages/core/src/security/QR.ts @@ -219,6 +219,9 @@ function parseTLV(qr: string): { /** Parses a string that has been decoded from a Z-Wave (S2 or SmartStart) QR code */ export function parseQRCodeString(qr: string): QRProvisioningInformation { + // Trim off whitespace that might have been copied by accident + qr = qr.trim(); + // Validate the QR code if (!qr.startsWith("90")) fail("must start with 90"); if (qr.length < minQRCodeLength) fail("too short"); if (!onlyDigitsRegex.test(qr)) fail("contains invalid characters"); @@ -229,7 +232,7 @@ export function parseQRCodeString(qr: string): QRProvisioningInformation { const checksum = readUInt16(qr, 4); // The checksum covers the remaining data const hash = createHash("sha1"); - hash.update(Buffer.from(qr.substr(9), "ascii")); + hash.update(Buffer.from(qr.slice(9), "ascii")); const expectedChecksum = hash.digest().readUInt16BE(0); if (checksum !== expectedChecksum) fail("invalid checksum"); @@ -265,7 +268,7 @@ export function parseQRCodeString(qr: string): QRProvisioningInformation { const { entry: { type, ...data }, charsRead, - } = parseTLV(qr.substr(offset)); + } = parseTLV(qr.slice(offset)); offset += charsRead; if (type === ProvisioningInformationType.ProductId) {