node.js USB (hid) Barcode Scanner read Buffer - node.js

i'm using node.js, to read data from a Barcode Scanner. So that is my code:
var HID = require('node-hid');
var usb = require('usb');
// Honeywell Scanner
var vid = 0xc2e;
var pid = 0xbe1;
var d = new HID.HID(vid, pid);
d.on("data", function (data) {
console.log(data);
});
d.on("error", function (error) {
console.log(error);
d.close();
});
My Problem is, that i get a Buffer that looks like < Buffer 00 00 00 00 00 00 00 00 >. After scanning a barcode (for example a barcode with the id 12) the console returns something like that
<Buffer 00 00 53 00 00 00 00 00>
<Buffer 00 00 00 00 00 00 00 00>
<Buffer 00 00 53 00 00 00 00 00>
<Buffer 00 00 00 00 00 00 00 00>
<Buffer 00 00 1e 00 00 00 00 00>
<Buffer 00 00 1f 00 00 00 00 00>
How can i convert this Buffer output into a readable string? In that case it would be a 12.
Thanks for your help!

I think what you want to do is to decode your data buffer.
To decode a buffer, you simply use the built-in .toString() method, passing in the character encoding to decode to:
data.toString('hex'); //<-- Decodes to hexadecimal
data.toString('base64'); //<-- Decodes to base64
If you don't pass anything to toString, utf8 will be the default.
EDIT
If you'd like to know which character encodings are currently supported by Node (other than hex, base64 and utf8), visit the official docs.

Related

node-ffi OUT parameter with type of Struct Pointer cannot receive back values from DLL call

C Data Structure:
typedef struct dpfpdd_dev_info {
unsigned int size;
char name[MAX_DEVICE_NAME_LENGTH];
DPFPDD_HW_DESCR descr;
DPFPDD_HW_ID id;
DPFPDD_HW_VERSION ver;
DPFPDD_HW_MODALITY modality;
DPFPDD_HW_TECHNOLOGY technology;
} DPFPDD_DEV_INFO;
typedef struct dpfpdd_hw_descr {
char vendor_name[MAX_STR_LENGTH];
char product_name[MAX_STR_LENGTH];
char serial_num[MAX_STR_LENGTH];
} DPFPDD_HW_DESCR;
typedef struct dpfpdd_hw_id {
unsigned short vendor_id;
unsigned short product_id;
} DPFPDD_HW_ID;
typedef struct dpfpdd_hw_version {
DPFPDD_VER_INFO hw_ver;
DPFPDD_VER_INFO fw_ver;
unsigned short bcd_rev;
} DPFPDD_HW_VERSION;
typedef struct dpfpdd_ver_info {
int major;
int minor;
int maintenance;
} DPFPDD_VER_INFO;
typedef unsigned int DPFPDD_HW_MODALITY;
typedef unsigned int DPFPDD_HW_TECHNOLOGY;
Emulated JS code of the C code above:
const ref = require('ref');
const StructType = require('ref-struct');
const FixedBuffer = require('./FixedBuffer'); // from https://gist.github.com/TooTallNate/80ac2d94b950216a2705
const DPFPDD_DEV_INFO = StructType({
size: ref.types.uint,
name: FixedBuffer(MAX_DEVICE_NAME_LENGTH, 'utf-8'),
descr: DPFPDD_HW_DESCR,
id: DPFPDD_HW_ID,
ver: DPFPDD_HW_VERSION,
modality: DPFPDD_HW_MODALITY,
technology: DPFPDD_HW_TECHNOLOGY
});
const DPFPDD_HW_DESCR = StructType({
vendor_name: FixedBuffer(MAX_STR_LENGTH, 'utf-8'),
product_name: FixedBuffer(MAX_STR_LENGTH, 'utf-8'),
serial_num: FixedBuffer(MAX_STR_LENGTH, 'utf-8')
});
const DPFPDD_HW_ID = StructType({
vendor_id: ref.types.ushort,
product_id: ref.types.ushort
});
const DPFPDD_HW_VERSION = StructType({
hw_ver: DPFPDD_VER_INFO,
fw_ver: DPFPDD_VER_INFO,
bcd_rev: ref.types.ushort
});
const DPFPDD_VER_INFO = StructType({
major: ref.types.int,
minor: ref.types.int,
maintenance: ref.types.int
});
const DPFPDD_HW_MODALITY = ref.types.uint;
const DPFPDD_HW_TECHNOLOGY = ref.types.uint;
DLL API:
int DPAPICALL dpfpdd_query_devices (unsigned int *dev_cnt, DPFPDD_DEV_INFO *dev_infos)
node-ffi code of the DLL API above:
const lib = ffi.Library('theDLL'), {
'dpfpdd_init': [ 'int', [] ],
'dpfpdd_query_devices': [ 'int', [ ref.refType('uint'), ref.refType(DPFPDD_DEV_INFO) ] ]
});
ffi function invocation in node:
lib.dpfpdd_init();
let deviceEntries = ref.alloc('uint');
let deviceInfo = ref.alloc(DPFPDD_DEV_INFO);
lib.dpfpdd_query_devices(deviceEntries, deviceInfo);
console.log(deviceInfo.deref());
The console log would return something like this:
{ size: 0,
name: <Buffer#0x019572AC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... >,
descr: { vendor_name: <Buffer#0x019576AC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... >,
product_name: <Buffer#0x0195772C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... >,
serial_num: <Buffer#0x019577AC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... >,
'ref.buffer': <Buffer#0x019576AC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... > },
id: { vendor_id: 0,
product_id: 0,
'ref.buffer': <Buffer#0x0195782C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00> },
ver: { hw_ver: { major: 0,
minor: 0,
maintenance: 0,
'ref.buffer': <Buffer#0x01957830 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00> },
fw_ver: { major: 0,
minor: 0,
maintenance: 0,
'ref.buffer': <Buffer#0x0195783C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00> },
bcd_rev: 0,
'ref.buffer': <Buffer#0x01957830 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00> },
modality: 0,
technology: 0,
'ref.buffer': <Buffer#0x019572A8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... > }
From all the Buffer type logs it seems like I'm receiving back no values at all from my OUT StructType parameter. I have no Idea why this is happening. I'm very new to using node-ffi and node-ref. I managed to get to communicate to another USB device but data structures are much simpler, no nested struct and array types. But this one I cannot get to work. Anyone enlighten me to what with what I'm doing wrong?

Parsing ByteBuffer in node?

I have data from an api that has returned like this:
var body = data;
data is equal to:
ByteBuffer {
buffer:
<Buffer 09 62 61 1f 04 01 00 10 01 11 61 99 5d 05 01 00 10 01>,
offset: 0,
markedOffset: -1,
limit: 18,
littleEndian: true,
noAssert: false
}
I've tried passing different functions to it to try to get the data from it. (I'm expecting at least 2 IDs.) Here is what I have tried so far and their results:
var message = body.readUint32(); // 526475785
var message = body.readCString(); // [blank]
var message = body.readUint8(); // 16
var message = body.readUint64(); // Long { low: -1721691903, high: 66909, unsigned: true }
I also tried:
var message = new ByteBuffer(8 + 8 + 4 + Buffer.byteLength(body.buffer) + 1, ByteBuffer.LITTLE_ENDIAN);
which returned:
ByteBuffer {
buffer:
<Buffer 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00>,
offset: 0,
markedOffset: -1,
limit: 39,
littleEndian: true,
noAssert: false
}
I also tried passing just 'body' in but that didn't work at all. Should I be parsing this differently? What exactly should I change to get the data? Thank you
You have to flip the bytebuffer first to make the ByteBuffer ready for read operations.
After the buffer is ready for read operations, use readIString to read the whole buffer as a string, you can use other operations such as readInt32 if you are expecting the buffer to be of other values than a string (I'm assuming a string since it is coming from an API).
body.flip().readIString();
A link to the ByteBuffer docs:
https://github.com/dcodeIO/bytebuffer.js/wiki/API

Error 0x6700 in securechannel.processSecurity(apdu)

I want to generate gp secure channel 01. my trace is:
Send: 80 50 00 00 08 00 00 00 00 00 00 00 00
Recv: 00 00 00 00 00 00 00 00 00 00 FF 02 00 02 0E 5A 8F F4 57 DD 35 5C 49 A6 8B 15 E9 A5 9000
so I have :
Card challenge= 00 02 0E 5A 8F F4 57 DD
Host challenge=00 00 00 00 00 00 00 00
according SPC01: image
Derivation data== 8F F4 57 DD 00 00 00 00 00 02 0E 5A 00 00 00 00
IV=0000000000000000
c_ENC: 404142434445464748494A4B4C4D4E4F
according this image and 3Des online
session s_ENC= C72F032C8BAD55D4D2579295CCF0A6CA
now :
hot-auth_data = card challenge + host challenge + pad
host-auth= 00020E5A8FF457DD00000000000000008000000000000000
s_ENC=C72F032C8BAD55D4D2579295CCF0A6CA
IV=0000000000000000
===========
result= 93CC77E144488A031BFFCCC62EB3B5C233A485F8255FE90E
Host cryptogram= 33A485F8255FE90E
but when I send :
848200000833A485F8255FE90E
I have error 0x6700 in method SDInstruction in line
short len = sc.processSecurity(apdu);
public void process(APDU apdu) throws ISOException {
if (selectingApplet()) {
return;
}
byte[] buffer = apdu.getBuffer();
switch (buffer[ISO7816.OFFSET_INS]) {
case ISO7816.INS_SELECT:
select();
return;
case INS_INIT_UPDATE:
case INS_EXT_AUTH:
SDInstruction(apdu);
break;
}
}
private void SDInstruction(APDU apdu)
{
byte[] buf = apdu.getBuffer();
byte cla = buf[ISO7816.OFFSET_CLA];
byte ins = buf[ISO7816.OFFSET_INS];
apdu.setIncomingAndReceive();
if(ins == INS_INIT_UPDATE)
sc = GPSystem.getSecureChannel();
short len = sc.processSecurity(apdu);
apdu.setOutgoing();
apdu.setOutgoingLength(len);
apdu.sendBytes(ISO7816.OFFSET_CDATA, (short) len);
}
Your card is using SCP02 and not SCP01.
Given the response to the INITIALIZE UPDATE command:
00 00 00 00 00 00 00 00 00 00 FF 02 00 02 0E 5A 8F F4 57 DD 35 5C 49 A6 8B 15 E9 A5 9000
The highlighted part is the "Key Information" which contains:
"Key Version Number" -- in your trace 0xFF
"Secure Channel Protocol Identifier" -- in your trace it is 0x02 indicating SCP02
See the Global Platform Card Specification for further reference (sections describing the INITIALIZE UPDATE command).
So you need to establish the secure channel with the card according to the SCP02.
Some additional (random) notes:
be sure to check the "i" secure channel parameter encoded inside the "Card Recognition Data" (tag '64') as well
you might want to look at the method GlobalPlatform.openSecureChannel() and the inner class GlobalPlatform.SCP0102Wrapper in the GlobalPlatformPro tool source code
Good luck!
According to the GlobalPlatform specification, the EXTERNAL AUTHENTICATE command has to include the host cryptogram as well as the MAC. Both are 8 bytes long, hence, your command should be 16 bytes in total.
If you want to implement the generation of this MAC value yourself, you can follow the description in the GlobalPlatform spec. But I suggest you to make use of available open source implementation. For example: GPJ is a Java implementation of the GlobalPlatform specification and has all commands that you need. You can take a look at the class GlobalPlatformService, where you will find the implementation of the secure channel protocol. GPDroid (github.com/mobilesec/secure-element-gpdroid) is a wrapper for this project on Android.

How do I decod node-hid data buffer from a&d scale

I have an A&D scale that I monitoring input from using node-hid. I am successfully reading the input, but I can't figure out how to decode the binary data. Any help is appreciated.
This is the code I am using:
var HID = require('node-hid');
var devices = HID.devices();
var device = new HID.HID('USB_0dbc_0005_14400000');
device.on("data", function(data){
console.log(data);
});
And this is what gets spat out when the scale is at zero.
<Buffer 00 00 53 00 00 00 00 00>
<Buffer 00 00 00 00 00 00 00 00>
<Buffer 00 00 57 00 00 00 00 00>
<Buffer 00 00 00 00 00 00 00 00>
<Buffer 00 00 62 00 00 00 00 00>
<Buffer 00 00 00 00 00 00 00 00>
<Buffer 00 00 62 00 00 00 00 00>
<Buffer 00 00 00 00 00 00 00 00>
<Buffer 00 00 62 00 00 00 00 00>
<Buffer 00 00 00 00 00 00 00 00>
<Buffer 00 00 62 00 00 00 00 00>
<Buffer 00 00 00 00 00 00 00 00>
<Buffer 00 00 62 00 00 00 00 00>
<Buffer 00 00 00 00 00 00 00 00>
<Buffer 00 00 63 00 00 00 00 00>
<Buffer 00 00 00 00 00 00 00 00>
<Buffer 00 00 62 00 00 00 00 00>
<Buffer 00 00 00 00 00 00 00 00>
<Buffer 00 00 62 00 00 00 00 00>
<Buffer 00 00 00 00 00 00 00 00>
<Buffer 00 00 58 00 00 00 00 00>
<Buffer 00 00 00 00 00 00 00 00>
<Buffer 00 00 53 00 00 00 00 00>
<Buffer 00 00 00 00 00 00 00 00>
I ended up just writing the buffer up on my whiteboard and thinking freely. I found some patterns in the data and wrote code for decoding and parsing the scale data. The code is included below for anyone that might need a push in the right direction.
"use strict";
var HID = require('node-hid');
var device = new HID.HID('USB_0dbc_0005_14400000');
var weight = []
var count = 0
module.exports.show_devices = function(){
console.log(devices);
}
module.exports.start_logging = function(){
device.on("data", function(data){
var bad_array = [
'\u0000S\u0000\u0000',
'\u0000W\u0000\u0000',
]
if (count < 20 && count % 2 == 0 && !contains(bad_array, data.toString('utf16le'))){
weight.push(key[data.toString('utf16le')])
}
if(count == 19){
display_weight()
}
if(count == 23){
count = -1
weight = []
}
count++
});
}
function display_weight(){
console.log(weight.join(''));
}
function contains(a, obj){
for(var i = 0; i < a.length; i++){
if(a[i] === obj){
return true;
}
}
return false;
}
var key = {
"\u0000Y\u0000\u0000" : "1",
"\u0000Z\u0000\u0000" : "2",
"\u0000[\u0000\u0000" : "3",
"\u0000\\\u0000\u0000" : "4",
"\u0000]\u0000\u0000" : "5",
"\u0000^\u0000\u0000" : "6",
"\u0000_\u0000\u0000" : "7",
"\u0000`\u0000\u0000" : "8",
"\u0000a\u0000\u0000" : "9",
"\u0000b\u0000\u0000" : "0",
"\u0000c\u0000\u0000" : "."
}

nodejs add null terminated string to buffer

I am trying to replicate a packet.
This packet:
2C 00 65 00 03 00 00 00 00 00 00 00 42 4C 41 5A
45 00 00 00 00 00 00 00 00 42 4C 41 5A 45......
2c 00 is the size of the packet...
65 00 is the packet id 101...
03 00 is the number of elements in the array...
Now here comes my problem, 42 4C 41 5A 45 is a string... There are exactly 3 Instances of that string in that packet if it is complete... But my problem is it is not just null terminated it has 00 00 00 00 spaces between those instances.
My code:
function channel_list(channels) {
var packet = new SmartBuffer();
packet.writeUInt16LE(101); // response packet for list of channels
packet.writeUInt16LE(channels.length)
channels.forEach(function (key){
console.log(key);
packet.writeStringNT(key);
});
packet.writeUInt16LE(packet.length + 2, 0);
console.log(packet.toBuffer());
}
But how do I add the padding?
I am using this package, https://github.com/JoshGlazebrook/smart-buffer/
Smart-Buffer keeps track of its position for you so you do not need to specify an offset to know where to insert the data to pad your string. You could do something like this with your existing code:
channels.forEach(function (key){
console.log(key);
packet.writeString(key); // This is the string with no padding added.
packet.writeUInt32BE(0); // Four 0x00's are added after the string itself.
});
I'm assuming you want: 42 4C 41 5A 45 00 00 00 00 42 4C 41 5A 45 00 00 00 00 etc.
Editing based on comments:
There is no built in way to do what you want, but you could do something like this:
channels.forEach(function (key){
console.log(key);
packet.writeString(key);
for(var i = 0; i <= (9 - key.length); i++)
packet.writeInt8(0);
});

Resources