little-printer-claim-code
Advanced tools
Comparing version 0.0.2 to 1.0.0
declare const devices: { | ||
claimCode: string; | ||
device: number; | ||
deviceXor: number; | ||
secret: number; | ||
@@ -5,0 +5,0 @@ }[]; |
@@ -6,3 +6,3 @@ "use strict"; | ||
claimCode: '64z0-0000-0000-0000', | ||
device: 0x000000, | ||
deviceXor: 0x000000, | ||
secret: 0x0000000000, | ||
@@ -12,3 +12,3 @@ }, | ||
claimCode: 'kzgz-zzzz-zzzz-zzzz', | ||
device: 0xffffff, | ||
deviceXor: 0xffffff, | ||
secret: 0xffffffffff, | ||
@@ -18,3 +18,3 @@ }, | ||
claimCode: 'vky0-0000-000h-0001', | ||
device: 0x000001, | ||
deviceXor: 0x000001, | ||
secret: 0x0000000001, | ||
@@ -24,3 +24,3 @@ }, | ||
claimCode: 'c1zp-g2ec-sqqh-28t5', | ||
device: 0x012345, | ||
deviceXor: 0x012345, | ||
secret: 0x6789abcdef, | ||
@@ -30,3 +30,3 @@ }, | ||
claimCode: 'd2y7-dv9z-4rz9-7bk3', | ||
device: 0x93aa43, | ||
deviceXor: 0x93aa43, | ||
secret: 0x766d3f263e, | ||
@@ -33,0 +33,0 @@ }, |
@@ -6,21 +6,27 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var big_integer_1 = __importDefault(require("big-integer")); | ||
var bigintToBuf_1 = __importDefault(require("../bigintToBuf")); | ||
var fixtures = [ | ||
{ value: big_integer_1.default(0), expected: [0, 0, 0, 0, 0, 0, 0, 0] }, | ||
{ value: big_integer_1.default(1), expected: [1, 0, 0, 0, 0, 0, 0, 0] }, | ||
{ value: big_integer_1.default(0xffffffff), expected: [255, 255, 255, 255, 0, 0, 0, 0] }, | ||
{ | ||
value: big_integer_1.default('ffffffffffffffff', 16), | ||
expected: [255, 255, 255, 255, 255, 255, 255, 255], | ||
}, | ||
{ | ||
value: big_integer_1.default('fffffffffffffff0', 16), | ||
expected: [240, 255, 255, 255, 255, 255, 255, 255], | ||
}, | ||
]; | ||
describe('bigintToBuf', function () { | ||
it('works', function () { | ||
var fixtures = [ | ||
{ value: BigInt(0), expected: [0, 0, 0, 0, 0, 0, 0, 0] }, | ||
{ value: BigInt(1), expected: [1, 0, 0, 0, 0, 0, 0, 0] }, | ||
{ value: BigInt(0xffffffff), expected: [255, 255, 255, 255, 0, 0, 0, 0] }, | ||
{ | ||
value: BigInt('0xffffffffffffffff'), | ||
expected: [255, 255, 255, 255, 255, 255, 255, 255], | ||
}, | ||
{ | ||
value: BigInt('0xfffffffffffffff0'), | ||
expected: [240, 255, 255, 255, 255, 255, 255, 255], | ||
}, | ||
]; | ||
describe('fixtures', function () { | ||
var _loop_1 = function (fixture) { | ||
it("fixture: 0x" + fixture.value.toString(16), function () { | ||
expect(bigintToBuf_1.default(fixture.value)).toEqual(Buffer.from(fixture.expected)); | ||
}); | ||
}; | ||
for (var _i = 0, fixtures_1 = fixtures; _i < fixtures_1.length; _i++) { | ||
var fixture = fixtures_1[_i]; | ||
expect(bigintToBuf_1.default(fixture.value)).toEqual(Buffer.from(fixture.expected)); | ||
_loop_1(fixture); | ||
} | ||
@@ -27,0 +33,0 @@ }); |
@@ -6,3 +6,5 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var big_integer_1 = __importDefault(require("big-integer")); | ||
var encode_1 = __importDefault(require("../encode")); | ||
var bitshuffle_1 = require("../bitshuffle"); | ||
var devices_1 = __importDefault(require("./__data__/devices")); | ||
@@ -12,4 +14,4 @@ describe('encode', function () { | ||
devices_1.default.forEach(function (fixture) { | ||
it("encodes 0x" + fixture.device.toString(16) + "/0x" + fixture.secret.toString(16), function () { | ||
var result = encode_1.default(fixture.device, fixture.secret); | ||
it("encodes 0x" + fixture.deviceXor.toString(16) + "/0x" + fixture.secret.toString(16), function () { | ||
var result = encode_1.default(big_integer_1.default(fixture.deviceXor), big_integer_1.default(fixture.secret)); | ||
expect(result).toEqual(fixture.claimCode); | ||
@@ -19,11 +21,40 @@ }); | ||
}); | ||
it('succeeds on values from the real world', function () { | ||
var deviceAddress = '000d6f000273c164'; | ||
// only the last 24 bits of the device address are used | ||
var deviceAddressInt = parseInt(deviceAddress, 16) & 0xffffff; | ||
// secret only known to printer and claim code | ||
var secret = 0xeb1ba696a0; | ||
expect(encode_1.default(deviceAddressInt, secret)).toEqual('n5ry-p6x6-kth7-7hc4'); | ||
describe('real world', function () { | ||
// sample from sirius. note, this uses the xor, not the address | ||
it('000d6f000273c164 / 0xeb1ba696a0 -> n5ry-p6x6-kth7-7hc4', function () { | ||
var xor = big_integer_1.default('000d6f000273c164', 16); | ||
var secret = big_integer_1.default('eb1ba696a0', 16); | ||
expect(encode_1.default(xor, secret)).toEqual('n5ry-p6x6-kth7-7hc4'); | ||
}); | ||
// existing printer | ||
it('11cc0f6aaeb07dad / 0x0375898b6e -> jwm0-6xd9-jeqd-p7x2', function () { | ||
var deviceAddress = big_integer_1.default('11cc0f6aaeb07dad', 16); | ||
var xor = bitshuffle_1.hardwareXorFromDeviceAddress(deviceAddress); | ||
var secret = big_integer_1.default('0375898b6e', 16); | ||
expect(encode_1.default(xor, secret)).toEqual('jwm0-6xd9-jeqd-p7x2'); | ||
}); | ||
// newly generated from sirius, just for this test | ||
it('sirius: 7fb391d95451aa97 / 0x2e9133ec35 -> 9462-x49m-xhtz-fm86', function () { | ||
var deviceAddress = big_integer_1.default('7fb391d95451aa97', 16); | ||
var xor = bitshuffle_1.hardwareXorFromDeviceAddress(deviceAddress); | ||
var secret = big_integer_1.default('2e9133ec35', 16); | ||
expect(encode_1.default(xor, secret)).toEqual('9462-x49m-xhtz-fm86'); | ||
}); | ||
// also newly generated from sirius, just for this test | ||
it('sirius: 46dbd1efebe85023 (known xor: 0x4160f2) / 0xbd38b46918 -> 3ddc-tf5n-e4d4-2r7k', function () { | ||
var deviceAddress = big_integer_1.default('46dbd1efebe85023', 16); | ||
var xor = bitshuffle_1.hardwareXorFromDeviceAddress(deviceAddress); | ||
var secret = big_integer_1.default('bd38b46918', 16); | ||
expect(xor).toEqual(big_integer_1.default('4160f2', 16)); | ||
expect(encode_1.default(xor, secret)).toEqual('3ddc-tf5n-e4d4-2r7k'); | ||
}); | ||
// generated by us, in /bin/generate-printer.sh | ||
it('sirius: bcd4fef9a78fc29f / 0x155f1e57ec -> 34t1-bqry-bzpd-odc1', function () { | ||
var deviceAddress = big_integer_1.default('bcd4fef9a78fc29f', 16); | ||
var xor = bitshuffle_1.hardwareXorFromDeviceAddress(deviceAddress); | ||
var secret = big_integer_1.default('155f1e57ec', 16); | ||
expect(encode_1.default(xor, secret)).toEqual('34t1-bqry-bzpd-odc1'); | ||
}); | ||
}); | ||
}); | ||
//# sourceMappingURL=encode.js.map |
@@ -6,2 +6,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var big_integer_1 = __importDefault(require("big-integer")); | ||
var unpack_1 = __importDefault(require("../unpack")); | ||
@@ -14,4 +15,4 @@ var devices_1 = __importDefault(require("./__data__/devices")); | ||
var result = unpack_1.default(fixture.claimCode); | ||
expect(result.device).toEqual(fixture.device); | ||
expect(result.secret).toEqual(fixture.secret); | ||
expect(result.deviceXor).toEqual(big_integer_1.default(fixture.deviceXor)); | ||
expect(result.secret).toEqual(big_integer_1.default(fixture.secret)); | ||
}); | ||
@@ -18,0 +19,0 @@ }); |
/// <reference types="node" /> | ||
declare const bigintToBuf: (bigint: BigInt) => Buffer; | ||
import { BigInteger } from 'big-integer'; | ||
declare const bigintToBuf: (bigint: BigInteger) => Buffer; | ||
export default bigintToBuf; | ||
//# sourceMappingURL=bigintToBuf.d.ts.map |
@@ -9,5 +9,9 @@ "use strict"; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var big_integer_1 = __importDefault(require("big-integer")); | ||
var bigintToBuf = function (bigint) { | ||
var hex = BigInt(bigint).toString(16); | ||
var hex = big_integer_1.default(bigint).toString(16); | ||
if (hex.length % 2) { | ||
@@ -14,0 +18,0 @@ hex = '0' + hex; |
@@ -1,4 +0,4 @@ | ||
import { DecodeResult } from '.'; | ||
declare const decode: (claimCode: string) => DecodeResult; | ||
import { ClaimCode, DecodeResult } from '.'; | ||
declare const decode: (claimCode: ClaimCode) => DecodeResult; | ||
export default decode; | ||
//# sourceMappingURL=decode.d.ts.map |
@@ -7,2 +7,3 @@ "use strict"; | ||
var crypto_1 = __importDefault(require("crypto")); | ||
var big_integer_1 = __importDefault(require("big-integer")); | ||
var bigintToBuf_1 = __importDefault(require("./bigintToBuf")); | ||
@@ -61,3 +62,3 @@ var crc16_1 = __importDefault(require("./crc16")); | ||
// Generate our own CRC from the raw_value, and confirm it matches the extracted crc | ||
var packable = BigInt(unpacked.value) & BigInt('0xffffffffffffffff'); | ||
var packable = big_integer_1.default(unpacked.value).and(big_integer_1.default('ffffffffffffffff', 16)); | ||
var dataForCrc = bigintToBuf_1.default(packable); | ||
@@ -69,6 +70,6 @@ var serverCrc = crc16_1.default(dataForCrc); | ||
// Pack the 40-bit number as a LE long long, and then truncate back to 5 bytes | ||
var packedSecret = bigintToBuf_1.default(BigInt(unpacked.secret)).slice(0, 5); | ||
var packedSecret = bigintToBuf_1.default(big_integer_1.default(unpacked.secret)).slice(0, 5); | ||
var key = generateLinkKey(packedSecret); | ||
return { | ||
device: unpacked.device, | ||
deviceXor: unpacked.deviceXor, | ||
key: key, | ||
@@ -75,0 +76,0 @@ }; |
@@ -1,3 +0,5 @@ | ||
declare const encode: (deviceArgument: number, secretArgument: number) => string; | ||
import { BigInteger } from 'big-integer'; | ||
import { ClaimCode } from '.'; | ||
declare const encode: (deviceArgument: BigInteger, secretArgument: BigInteger) => ClaimCode; | ||
export default encode; | ||
//# sourceMappingURL=encode.d.ts.map |
@@ -6,2 +6,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var big_integer_1 = __importDefault(require("big-integer")); | ||
var crc16_1 = __importDefault(require("./crc16")); | ||
@@ -44,14 +45,14 @@ var bigintToBuf_1 = __importDefault(require("./bigintToBuf")); | ||
var encode = function (deviceArgument, secretArgument) { | ||
var device = BigInt(deviceArgument) & BigInt(0xffffff); | ||
var secret = BigInt(secretArgument) & BigInt(0xffffffffff); | ||
var value = device | (secret << BigInt(24)); | ||
var device = deviceArgument.and(big_integer_1.default(0xffffff)); | ||
var secret = secretArgument.and(big_integer_1.default(0xffffffffff)); | ||
var value = device.or(secret.shiftLeft(big_integer_1.default(24))); | ||
var crc = crc16_1.default(bigintToBuf_1.default(value), 0xffff); | ||
var cc = BigInt(value) | (BigInt(crc) << BigInt(64)); | ||
var cc = big_integer_1.default(value).or(big_integer_1.default(crc).shiftLeft(big_integer_1.default(64))); | ||
var text = ''; | ||
var i = 16; | ||
while (i > 0) { | ||
var index = Number(cc & BigInt(0x1f)); | ||
var index = Number(cc.and(big_integer_1.default(0x1f))); | ||
var char = CC_ENCODE_LIST[index]; | ||
text = char + text; | ||
cc = cc >> BigInt(5); | ||
cc = cc.shiftRight(big_integer_1.default(5)); | ||
// insert `-` every 4 characters | ||
@@ -58,0 +59,0 @@ if (i % 4 == 1 && i != 1) { |
/// <reference types="node" /> | ||
import { BigInteger } from 'big-integer'; | ||
import decode from './decode'; | ||
@@ -7,12 +8,12 @@ import encode from './encode'; | ||
export declare type DecodeResult = { | ||
device: number; | ||
deviceXor: BigInteger; | ||
key: Buffer; | ||
}; | ||
export declare type UnpackResult = { | ||
device: number; | ||
secret: number; | ||
deviceXor: BigInteger; | ||
secret: BigInteger; | ||
crc: number; | ||
value: BigInt; | ||
value: BigInteger; | ||
}; | ||
export { decode, encode, unpack }; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -6,2 +6,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.unpack = exports.encode = exports.decode = void 0; | ||
var decode_1 = __importDefault(require("./decode")); | ||
@@ -8,0 +9,0 @@ exports.decode = decode_1.default; |
@@ -1,4 +0,4 @@ | ||
import { UnpackResult } from '.'; | ||
declare const unpack: (claimCode: string) => UnpackResult; | ||
import { ClaimCode, UnpackResult } from '.'; | ||
declare const unpack: (claimCode: ClaimCode) => UnpackResult; | ||
export default unpack; | ||
//# sourceMappingURL=unpack.d.ts.map |
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var big_integer_1 = __importDefault(require("big-integer")); | ||
// This dictionary maps base32 digits to five-bit values. | ||
@@ -52,3 +56,3 @@ // | ||
} | ||
var value = BigInt(0); | ||
var value = big_integer_1.default(0); | ||
for (var i = 0; i < clean.length; i++) { | ||
@@ -59,5 +63,5 @@ var char = clean[i].toUpperCase(); | ||
// value += CLAIMCODE_BASE32_DICT[c] * (32 ** (15 - i)) | ||
var code = BigInt(CLAIMCODE_BASE32_DICT[char]); | ||
var mult = BigInt(Math.pow(32, (15 - i))); | ||
value += code * mult; | ||
var code = big_integer_1.default(CLAIMCODE_BASE32_DICT[char]); | ||
var mult = big_integer_1.default(Math.pow(32, (15 - i))); | ||
value = value.add(code.multiply(mult)); | ||
} | ||
@@ -69,10 +73,10 @@ else { | ||
// 24 bit hardware address xor | ||
var device = value & BigInt(0xffffff); | ||
var deviceXor = value.and(big_integer_1.default(0xffffff)); | ||
// 40 bit secret | ||
var secret = (value >> BigInt(24)) & BigInt(0xffffffffff); | ||
var secret = value.shiftRight(big_integer_1.default(24)).and(big_integer_1.default(0xffffffffff)); | ||
// 16 bit crc | ||
var crc = value >> BigInt(64); | ||
var crc = value.shiftRight(big_integer_1.default(64)); | ||
return { | ||
device: Number(device), | ||
secret: Number(secret), | ||
deviceXor: deviceXor, | ||
secret: secret, | ||
crc: Number(crc), | ||
@@ -79,0 +83,0 @@ value: value, |
{ | ||
"name": "little-printer-claim-code", | ||
"version": "0.0.2", | ||
"version": "1.0.0", | ||
"description": "helper utility to generate (and process) claim codes for a Berg Little Printer", | ||
@@ -20,5 +20,5 @@ "main": "dist/index.js", | ||
"scripts": { | ||
"build": "tsc", | ||
"dist": "tsc", | ||
"postversion": "git push && git push --tags", | ||
"prepublish": "yarn build", | ||
"prepublish": "yarn dist", | ||
"lint": "eslint . --cache --ext js,jsx,ts,tsx,md", | ||
@@ -28,2 +28,3 @@ "test": "yarn lint && yarn jest" | ||
"dependencies": { | ||
"big-integer": "^1.6.48", | ||
"crc": "^3.8.0" | ||
@@ -36,9 +37,9 @@ }, | ||
"@typescript-eslint/parser": "^2.28.0", | ||
"eslint": "^6.8.0", | ||
"eslint": "^7.0.0", | ||
"eslint-plugin-markdown": "^2.0.0-alpha.0", | ||
"jest": "^25.3.0", | ||
"jest": "^26.0.1", | ||
"prettier": "^2.0.4", | ||
"ts-jest": "^25.4.0", | ||
"ts-jest": "^26.0.0", | ||
"typescript": "^3.8.3" | ||
} | ||
} |
@@ -17,12 +17,10 @@ # little-printer-claim-code | ||
// generate a device address - from MAC address, or randomly, whatever | ||
const deviceAddress = '000d6f000273c164'; | ||
const deviceAddress = bigInt('46dbd1efebe85023', 16); | ||
const xor = hardwareXorFromDeviceAddress(deviceAddress); | ||
// only the last 24 bits of the device address are used | ||
const deviceAddressInt = parseInt(deviceAddress, 16) & 0xffffff; | ||
// secret only known to printer and claim code, randomly generated | ||
const secret = bigInt('bd38b46918', 16); | ||
// secret only known to printer and claim code, randomly generate | ||
const secret = 0xeb1ba696a0; | ||
console.log(encode(deviceAddressInt, secret)); | ||
// → 'n5ry-p6x6-kth7-7hc4' | ||
console.log(encode(xor, secret)); | ||
// → '3ddc-tf5n-e4d4-2r7k' | ||
``` | ||
@@ -39,5 +37,5 @@ | ||
// → { | ||
// device: 74565, | ||
// secret: 444691369455, | ||
// crc: 22655, | ||
// deviceXor: 74565n, | ||
// secret: 444691369455n, | ||
// crc: 22655n, | ||
// value: 417918447673048574272325n | ||
@@ -57,3 +55,3 @@ // } | ||
// → { | ||
// device: 74565, | ||
// deviceXor: 74565n, | ||
// key: <Buffer d5 0b 90 4f 43 7c 1d 2e 87 c3 10 57 49 40 9e 3d> | ||
@@ -68,9 +66,9 @@ // } | ||
```sh | ||
./bin/generate-claim-code.sh | ||
./bin/generate-printer.sh | ||
// → { | ||
// device: '121745933cb16b91', | ||
// secret: 876353015208, | ||
// claimCode: '5rpd-r2oo-spnc-2v00' | ||
// } | ||
// → | ||
// address: 5f297a46f118187 | ||
// secret: da156dc11d | ||
// xor: 11541520 | ||
// claim code: 7p6x-n5ce-r4fv-070h | ||
``` | ||
@@ -77,0 +75,0 @@ |
const devices = [ | ||
{ | ||
claimCode: '64z0-0000-0000-0000', | ||
device: 0x000000, | ||
deviceXor: 0x000000, | ||
secret: 0x0000000000, | ||
@@ -9,3 +9,3 @@ }, | ||
claimCode: 'kzgz-zzzz-zzzz-zzzz', | ||
device: 0xffffff, | ||
deviceXor: 0xffffff, | ||
secret: 0xffffffffff, | ||
@@ -15,3 +15,3 @@ }, | ||
claimCode: 'vky0-0000-000h-0001', | ||
device: 0x000001, | ||
deviceXor: 0x000001, | ||
secret: 0x0000000001, | ||
@@ -21,3 +21,3 @@ }, | ||
claimCode: 'c1zp-g2ec-sqqh-28t5', | ||
device: 0x012345, | ||
deviceXor: 0x012345, | ||
secret: 0x6789abcdef, | ||
@@ -27,3 +27,3 @@ }, | ||
claimCode: 'd2y7-dv9z-4rz9-7bk3', | ||
device: 0x93aa43, | ||
deviceXor: 0x93aa43, | ||
secret: 0x766d3f263e, | ||
@@ -30,0 +30,0 @@ }, |
@@ -0,23 +1,28 @@ | ||
import bigInt from 'big-integer'; | ||
import bigintToBuf from '../bigintToBuf'; | ||
const fixtures = [ | ||
{ value: bigInt(0), expected: [0, 0, 0, 0, 0, 0, 0, 0] }, | ||
{ value: bigInt(1), expected: [1, 0, 0, 0, 0, 0, 0, 0] }, | ||
{ value: bigInt(0xffffffff), expected: [255, 255, 255, 255, 0, 0, 0, 0] }, | ||
{ | ||
value: bigInt('ffffffffffffffff', 16), | ||
expected: [255, 255, 255, 255, 255, 255, 255, 255], | ||
}, | ||
{ | ||
value: bigInt('fffffffffffffff0', 16), | ||
expected: [240, 255, 255, 255, 255, 255, 255, 255], | ||
}, | ||
]; | ||
describe('bigintToBuf', () => { | ||
it('works', () => { | ||
const fixtures = [ | ||
{ value: BigInt(0), expected: [0, 0, 0, 0, 0, 0, 0, 0] }, | ||
{ value: BigInt(1), expected: [1, 0, 0, 0, 0, 0, 0, 0] }, | ||
{ value: BigInt(0xffffffff), expected: [255, 255, 255, 255, 0, 0, 0, 0] }, | ||
{ | ||
value: BigInt('0xffffffffffffffff'), | ||
expected: [255, 255, 255, 255, 255, 255, 255, 255], | ||
}, | ||
{ | ||
value: BigInt('0xfffffffffffffff0'), | ||
expected: [240, 255, 255, 255, 255, 255, 255, 255], | ||
}, | ||
]; | ||
describe('fixtures', () => { | ||
for (const fixture of fixtures) { | ||
expect(bigintToBuf(fixture.value)).toEqual(Buffer.from(fixture.expected)); | ||
it(`fixture: 0x${fixture.value.toString(16)}`, () => { | ||
expect(bigintToBuf(fixture.value)).toEqual( | ||
Buffer.from(fixture.expected) | ||
); | ||
}); | ||
} | ||
}); | ||
}); |
@@ -0,2 +1,5 @@ | ||
import bigInt from 'big-integer'; | ||
import encode from '../encode'; | ||
import { hardwareXorFromDeviceAddress } from '../bitshuffle'; | ||
import fixtures from './__data__/devices'; | ||
@@ -7,6 +10,9 @@ | ||
fixtures.forEach((fixture) => { | ||
it(`encodes 0x${fixture.device.toString(16)}/0x${fixture.secret.toString( | ||
it(`encodes 0x${fixture.deviceXor.toString( | ||
16 | ||
)}`, () => { | ||
const result = encode(fixture.device, fixture.secret); | ||
)}/0x${fixture.secret.toString(16)}`, () => { | ||
const result = encode( | ||
bigInt(fixture.deviceXor), | ||
bigInt(fixture.secret) | ||
); | ||
@@ -18,13 +24,48 @@ expect(result).toEqual(fixture.claimCode); | ||
it('succeeds on values from the real world', () => { | ||
const deviceAddress = '000d6f000273c164'; | ||
describe('real world', () => { | ||
// sample from sirius. note, this uses the xor, not the address | ||
it('000d6f000273c164 / 0xeb1ba696a0 -> n5ry-p6x6-kth7-7hc4', () => { | ||
const xor = bigInt('000d6f000273c164', 16); | ||
const secret = bigInt('eb1ba696a0', 16); | ||
// only the last 24 bits of the device address are used | ||
const deviceAddressInt = parseInt(deviceAddress, 16) & 0xffffff; | ||
expect(encode(xor, secret)).toEqual('n5ry-p6x6-kth7-7hc4'); | ||
}); | ||
// secret only known to printer and claim code | ||
const secret = 0xeb1ba696a0; | ||
// existing printer | ||
it('11cc0f6aaeb07dad / 0x0375898b6e -> jwm0-6xd9-jeqd-p7x2', () => { | ||
const deviceAddress = bigInt('11cc0f6aaeb07dad', 16); | ||
const xor = hardwareXorFromDeviceAddress(deviceAddress); | ||
const secret = bigInt('0375898b6e', 16); | ||
expect(encode(deviceAddressInt, secret)).toEqual('n5ry-p6x6-kth7-7hc4'); | ||
expect(encode(xor, secret)).toEqual('jwm0-6xd9-jeqd-p7x2'); | ||
}); | ||
// newly generated from sirius, just for this test | ||
it('sirius: 7fb391d95451aa97 / 0x2e9133ec35 -> 9462-x49m-xhtz-fm86', () => { | ||
const deviceAddress = bigInt('7fb391d95451aa97', 16); | ||
const xor = hardwareXorFromDeviceAddress(deviceAddress); | ||
const secret = bigInt('2e9133ec35', 16); | ||
expect(encode(xor, secret)).toEqual('9462-x49m-xhtz-fm86'); | ||
}); | ||
// also newly generated from sirius, just for this test | ||
it('sirius: 46dbd1efebe85023 (known xor: 0x4160f2) / 0xbd38b46918 -> 3ddc-tf5n-e4d4-2r7k', () => { | ||
const deviceAddress = bigInt('46dbd1efebe85023', 16); | ||
const xor = hardwareXorFromDeviceAddress(deviceAddress); | ||
const secret = bigInt('bd38b46918', 16); | ||
expect(xor).toEqual(bigInt('4160f2', 16)); | ||
expect(encode(xor, secret)).toEqual('3ddc-tf5n-e4d4-2r7k'); | ||
}); | ||
// generated by us, in /bin/generate-printer.sh | ||
it('sirius: bcd4fef9a78fc29f / 0x155f1e57ec -> 34t1-bqry-bzpd-odc1', () => { | ||
const deviceAddress = bigInt('bcd4fef9a78fc29f', 16); | ||
const xor = hardwareXorFromDeviceAddress(deviceAddress); | ||
const secret = bigInt('155f1e57ec', 16); | ||
expect(encode(xor, secret)).toEqual('34t1-bqry-bzpd-odc1'); | ||
}); | ||
}); | ||
}); |
@@ -0,1 +1,3 @@ | ||
import bigInt from 'big-integer'; | ||
import unpack from '../unpack'; | ||
@@ -10,4 +12,4 @@ import fixtures from './__data__/devices'; | ||
expect(result.device).toEqual(fixture.device); | ||
expect(result.secret).toEqual(fixture.secret); | ||
expect(result.deviceXor).toEqual(bigInt(fixture.deviceXor)); | ||
expect(result.secret).toEqual(bigInt(fixture.secret)); | ||
}); | ||
@@ -14,0 +16,0 @@ }); |
@@ -1,3 +0,5 @@ | ||
const bigintToBuf = (bigint: BigInt): Buffer => { | ||
let hex = BigInt(bigint).toString(16); | ||
import bigInt, { BigInteger } from 'big-integer'; | ||
const bigintToBuf = (bigint: BigInteger): Buffer => { | ||
let hex = bigInt(bigint).toString(16); | ||
if (hex.length % 2) { | ||
@@ -4,0 +6,0 @@ hex = '0' + hex; |
import crypto from 'crypto'; | ||
import bigInt from 'big-integer'; | ||
@@ -71,3 +72,3 @@ import { ClaimCode, DecodeResult } from '.'; | ||
// Generate our own CRC from the raw_value, and confirm it matches the extracted crc | ||
const packable = BigInt(unpacked.value) & BigInt('0xffffffffffffffff'); | ||
const packable = bigInt(unpacked.value).and(bigInt('ffffffffffffffff', 16)); | ||
const dataForCrc = bigintToBuf(packable); | ||
@@ -81,7 +82,7 @@ const serverCrc = crc16(dataForCrc); | ||
// Pack the 40-bit number as a LE long long, and then truncate back to 5 bytes | ||
const packedSecret = bigintToBuf(BigInt(unpacked.secret)).slice(0, 5); | ||
const packedSecret = bigintToBuf(bigInt(unpacked.secret)).slice(0, 5); | ||
const key = generateLinkKey(packedSecret); | ||
return { | ||
device: unpacked.device, | ||
deviceXor: unpacked.deviceXor, | ||
key, | ||
@@ -88,0 +89,0 @@ }; |
@@ -0,1 +1,3 @@ | ||
import bigInt, { BigInteger } from 'big-integer'; | ||
import crc16 from './crc16'; | ||
@@ -41,10 +43,13 @@ | ||
const encode = (deviceArgument: number, secretArgument: number): ClaimCode => { | ||
const device = BigInt(deviceArgument) & BigInt(0xffffff); | ||
const secret = BigInt(secretArgument) & BigInt(0xffffffffff); | ||
const encode = ( | ||
deviceArgument: BigInteger, | ||
secretArgument: BigInteger | ||
): ClaimCode => { | ||
const device = deviceArgument.and(bigInt(0xffffff)); | ||
const secret = secretArgument.and(bigInt(0xffffffffff)); | ||
const value = device | (secret << BigInt(24)); | ||
const value = device.or(secret.shiftLeft(bigInt(24))); | ||
const crc = crc16(bigintToBuf(value), 0xffff); | ||
let cc = BigInt(value) | (BigInt(crc) << BigInt(64)); | ||
let cc = bigInt(value).or(bigInt(crc).shiftLeft(bigInt(64))); | ||
let text = ''; | ||
@@ -54,6 +59,6 @@ let i = 16; | ||
while (i > 0) { | ||
const index = Number(cc & BigInt(0x1f)); | ||
const index = Number(cc.and(bigInt(0x1f))); | ||
const char = CC_ENCODE_LIST[index]; | ||
text = char + text; | ||
cc = cc >> BigInt(5); | ||
cc = cc.shiftRight(bigInt(5)); | ||
@@ -60,0 +65,0 @@ // insert `-` every 4 characters |
@@ -0,1 +1,3 @@ | ||
import { BigInteger } from 'big-integer'; | ||
import decode from './decode'; | ||
@@ -8,3 +10,3 @@ import encode from './encode'; | ||
export type DecodeResult = { | ||
device: number; | ||
deviceXor: BigInteger; | ||
key: Buffer; | ||
@@ -14,8 +16,8 @@ }; | ||
export type UnpackResult = { | ||
device: number; | ||
secret: number; | ||
deviceXor: BigInteger; | ||
secret: BigInteger; | ||
crc: number; | ||
value: BigInt; | ||
value: BigInteger; | ||
}; | ||
export { decode, encode, unpack }; |
@@ -0,1 +1,3 @@ | ||
import bigInt from 'big-integer'; | ||
import { ClaimCode, UnpackResult } from '.'; | ||
@@ -56,3 +58,3 @@ | ||
let value = BigInt(0); | ||
let value = bigInt(0); | ||
@@ -65,5 +67,5 @@ for (let i = 0; i < clean.length; i++) { | ||
// value += CLAIMCODE_BASE32_DICT[c] * (32 ** (15 - i)) | ||
const code = BigInt(CLAIMCODE_BASE32_DICT[char]); | ||
const mult = BigInt(32 ** (15 - i)); | ||
value += code * mult; | ||
const code = bigInt(CLAIMCODE_BASE32_DICT[char]); | ||
const mult = bigInt(32 ** (15 - i)); | ||
value = value.add(code.multiply(mult)); | ||
} else { | ||
@@ -75,11 +77,11 @@ throw new Error(`${char} is not a valid character`); | ||
// 24 bit hardware address xor | ||
const device = value & BigInt(0xffffff); | ||
const deviceXor = value.and(bigInt(0xffffff)); | ||
// 40 bit secret | ||
const secret = (value >> BigInt(24)) & BigInt(0xffffffffff); | ||
const secret = value.shiftRight(bigInt(24)).and(bigInt(0xffffffffff)); | ||
// 16 bit crc | ||
const crc = value >> BigInt(64); | ||
const crc = value.shiftRight(bigInt(64)); | ||
return { | ||
device: Number(device), | ||
secret: Number(secret), | ||
deviceXor, | ||
secret, | ||
crc: Number(crc), | ||
@@ -86,0 +88,0 @@ value: value, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
72464
77
1592
0
2
81
+ Addedbig-integer@^1.6.48
+ Addedbig-integer@1.6.52(transitive)