Created
April 21, 2024 19:12
-
-
Save andy0130tw/17776eb909d1b40439ece1a3a650194d to your computer and use it in GitHub Desktop.
Decrypt Meshtastic packets from MQTT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as crypto from 'node:crypto' | |
import { loadProtobufs } from './pbs.js' | |
const pbroot = await loadProtobufs() | |
const Data = pbroot.lookupType('meshtastic.Data') | |
// Usage: decryptPacket( | |
// Buffer.from('1PG7OiApB1nwvP+rz05pAQ==', 'base64'), | |
// {from, id, encrypted}) | |
export function decryptPacket(psk, packet) { | |
const packetId = packet.id | |
const fromNodeId = packet.from | |
const ciphertext = packet.encrypted | |
// guard against overflows | |
if (typeof packetId !== 'number' || | |
typeof fromNodeId !== 'number') | |
throw new TypeError('id/from should be in numbers') | |
const iv = new ArrayBuffer(16) | |
const ivView = new DataView(iv) | |
ivView.setUint32(0, packetId, true) | |
ivView.setUint32(8, fromNodeId, true) | |
const algo = psk.length === 32 ? 'aes-256-ctr' : 'aes-128-ctr' | |
const decipher = crypto.createDecipheriv(algo, psk, iv) | |
let plaintext = decipher.update(ciphertext) | |
plaintext = Buffer.concat([plaintext, decipher.final()]) | |
try { | |
return Data.decode(plaintext) | |
} catch (err) { // i.e. input is incorrect | |
return null | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import protobuf from 'protobufjs' | |
/** @type {protobuf.Root} */ | |
let root | |
export async function loadProtobufs() { | |
if (root == null) { | |
let defaultResolve = protobuf.util.path.resolve | |
protobuf.Root.prototype.resolvePath = function(p, ip, an) { | |
return defaultResolve('protobufs/xxx', ip, an) | |
} | |
try { | |
root = await protobuf.load('meshtastic/mqtt.proto') | |
} finally { | |
protobuf.Root.prototype.resolvePath = defaultResolve | |
} | |
} | |
return root | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment