-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathic.js
82 lines (72 loc) · 2.98 KB
/
ic.js
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
import { Buffer } from 'node:buffer';
import { ic as format } from './format.js';
import { crc, mmo } from './hash.js';
export const iclen = 16;
export const crclen = 2;
/**
* Validate the given Install Code (ic) by checking the CRC checksum.
*
* @param {Buffer} ic the Install Code to validate
* @returns {boolean} true if the Install Code is valid
*/
export function validate(ic) {
if (ic.length === iclen) {
throw new TypeError('Incomplete Install Code / missing CRC checksum');
} else if (ic.length !== (iclen + crclen)) {
throw new TypeError(`Invalid length of Install Code expected ${iclen} + ${crclen} CRC, got ${ic.length}`);
}
return crc(ic.subarray(0, iclen)).equals(ic.subarray(iclen));
}
/**
* Calculate the CRC checksum for the given Install Code (ic).
*
* @param {Buffer} ic the Install Code to calculate the CRC checksum for
* @param {boolean} [full=true] whether to return the full Install Code with the CRC checksum or just the CRC checksum
* @returns {Buffer} the CRC checksum for the Install Code (ic)
*/
export function checksum(ic, full = true) {
if (ic.length === (iclen + crclen)) {
return full ? ic : ic.subarray(iclen); // already contains a CRC checksum
} else if (ic.length !== iclen) {
throw new TypeError(`Invalid length of Install Code expected ${iclen} bytes, got ${ic.length}`);
}
return full ? Buffer.concat([ic, crc(ic)]) : crc(ic);
}
export { format };
/**
* Calculate the Link Key for the given Install Code (ic).
*
* As per specification of the ZigBee Certificate-Based Key Establishment (CBKE), the
* Link Key (lk) for a given Install Code (ic) is calculated by applying the
* Matyas-Meyer-Oseas (AES-MMO) hash function hash function to the Install Code.
*
* @param {Buffer} ic the Install Code to calculate the Link Key for
* @returns {Buffer} the Link Key for the Install Code (ic)
*/
export function link(ic) {
return mmo(checksum(ic));
}
import { moduleHandler, stdinMiddleware } from './utils.js';
export const command = {
command: 'ic <action> [install-code]',
desc: 'Install Code Utilities',
builder: yargs => stdinMiddleware(yargs
.positional('action', {
desc: 'Action to perform',
type: 'string',
choices: ['validate', 'checksum', 'format', 'link']
}), 'install-code', { desc: 'Install Code to process', alias: 'ic' })
.example('$0 ic validate 83fed3407a939723a5c639b26916d505c3b5', 'Validate the given Install Code')
.example('$0 ic checksum 83fed3407a939723a5c639b26916d505', 'Calculate the CRC checksum for the given Install Code')
.example('$0 ic format 83fed3407a939723a5c639b26916d505c3b5', 'Format the given Install Code')
.example('$0 ic link 83fed3407a939723a5c639b26916d505c3b5', 'Calculate the Link Key for the given Install Code')
.version(false)
.help(),
handler: moduleHandler(import.meta.url, 'action', 'ic', (out, argv) => {
if (argv.action === 'validate') {
console.log(out);
process.exit(out ? 0 : 1);
}
return out.toString('hex');
})
};