UNPKG

wiegand-encoder

Version:

Encode and decode 26, 34, or 38 bit Wiegand protocol credentials

75 lines (74 loc) 3.1 kB
"use strict"; // // src/parity.ts // Created by Jesse Youngblood on 02/02/20 // Copyright (c) 2020 Jesse Youngblood. All rights reserved. // Object.defineProperty(exports, "__esModule", { value: true }); /** * Calculate left and right parity for a given credential * @param {string} contents - Wiegand credential * @throws * @returns {{left: number, right: number}} */ function calculate(contents) { if (typeof contents !== 'string' || contents.length < 2) { throw new Error(`Invalid message. Received: "${contents}"`); } if (contents.length % 2 === 1) { throw new Error(`Cannot calculate parity for message with an odd number of bits.`); } // Split the string in half const leftHalf = contents.substring(0, contents.length / 2); const rightHalf = contents.substring(contents.length / 2); // Calculate how many digits are '1' in each half of the string const leftBitCount = leftHalf.split('').filter(bit => bit === '1').length; const rightBitCount = rightHalf.split('').filter(bit => bit === '1').length; // If the left digit count is odd, set the left parity count to '1'. Otherwise, set it to '0'. let left = 0; if (leftBitCount % 2 === 1) { left = 1; } // If the right digit count is odd, set the right parity to '0'. Otherwise, set it to '1'. let right = 1; if (rightBitCount % 2 === 1) { right = 0; } return { left, right }; } /** * Confirm left and right parity bits. Throws an exception if they are not valid. * @param {string} message - a Wiegand credential message * @throws * @returns {boolean} */ function validate(message) { if (typeof message !== 'string' || message.length < 26) { throw new Error(`Invalid wiegand message. Received: "${message}"`); } // Pull out the declared right and left parity bits const declaredLeftParity = Number(message.substring(0, 1)); const declaredRightParity = Number(message.substring(message.length - 1)); // Calculate the parity bits based on the contents of the message const credential = message.substring(1, message.length - 1); const { left: calculatedLeftParity, right: calculatedRightParity } = calculate(credential); // Compare the declared parity bits to their calculated counterparts if (declaredLeftParity !== calculatedLeftParity) { throw new Error(`Left parity bit (${declaredLeftParity}) does not match calculated left parity bit (${calculatedLeftParity}) in: "${message}"`); } if (declaredRightParity !== calculatedRightParity) { throw new Error(`Right parity bit (${declaredRightParity}) does not match calculated right parity bit (${calculatedRightParity}) in: "${message}"`); } return true; } /** * Wrap a Wiegand credential in parity bits * @param {string} credential - Wiegand credential * @throws * @returns {string} - The credential wrapped in parity bits */ function wrap(contents) { const { left, right } = calculate(contents); return [left, contents, right].join(''); } exports.default = { calculate, validate, wrap };