How to deal with block length in Node.js crypto streams - javascript

I want to crypt an input stream and send it to another server via TCP. So far so good. Everything runs smoothly, until the connection is closed. In almost any case the needed block size of 192 bits is not met and the script crashes with wrong final block length, although I turned auto padding on.
It seems like auto padding only works, when using the legacy interface. Am I doing something wrong here?
var net = require("net")
, crypto = require("crypto");
var credentials = { algorithm: "aes192", password: "password" }
, decipher = crypto.createDecipher(credentials.algorithm, credentials.password)
, cipher = crypto.createCipher(credentials.algorithm, credentials.password);
decipher.setAutoPadding(true);
cipher.setAutoPadding(true);
net.createServer(function(socket) {
socket.pipe(socket);
}).listen(2000);
var socket = net.connect(2000);
socket.pipe(decipher).pipe(process.stdout);
process.stdin.pipe(cipher).pipe(socket);
socket.write("Too short.");
socket.end();
In my ideal Node.js world, the (De-)Cipher Stream would automatically pad the last block, when the source stream is closed. I think this is a design flaw.
Apart from opening an issue, how can I circumvent this behaviour? Do I have to put a byte counter between Socket and (De-)Cipher Streams?

You have set your pipes like this :
stdin | cipher | socket (loopback) | decipher | stdout
But you bypass the encryption by writing directly to the socket, using them like this :
socket (loopback) | decipher | stdout
Try with this code :
var net = require("net")
, crypto = require("crypto");
var credentials = { algorithm: "aes192", password: "password" }
, decipher = crypto.createDecipher(credentials.algorithm, credentials.password)
, cipher = crypto.createCipher(credentials.algorithm, credentials.password);
decipher.setAutoPadding(false); //set to false to keep the padding
cipher.setAutoPadding(true);
//Loopback
server = net.createServer(function(socket) {
socket.pipe(socket);
})
server.listen(2000);
var socket = net.connect(2000);
//cipher to the loopback socket, to decipher and stdout
cipher.pipe(socket).pipe(decipher).pipe(process.stdout);
//write some data
cipher.write("Too short.");
//Clean exit
cipher.end();
server.unref();
For the purpose of demonstration, I removed auto padding from the Decryptor object so you can see the leftover padding. Piping the program in xxd (at the command line, not in node) gives me this ouput :
$ nodejs so.js | xxd
0000000: 546f 6f20 7368 6f72 742e 0606 0606 0606 Too short.......
With the 0x06 repeated 6 times.

Related

How to send this HEX command to my device using Node-red

Hello all, I want to send hex commands to my device using Node red. I'm new to node red and JavaScript, what is the way to send this command in the proper way. I want to write it in a function.
The device is connected via serial port and on rs232 interface.
The things that I have tried:
Blockquote
"
1-
var buf = Buffer.from([0xaa,0x3f,0x00,0x00,0xf0,0x11]).toString;
msg.payload = buf;
return msg;
2-
var buf = Buffer.from([0xaa,0x3f,0x00,0x00,0xf0,0x11]);
msg.payload = buf;
return msg;
3-
var buf = Buffer.from(['aa','3f','00','00','f0','11']);
msg.payload = buf;
return msg;
And some more ways, like without using a function. In most cases I'm getting no response. I'm pretty sure of the physical connections, since using a different software which is UART Assistant and over the same port with same settings, the device is responding to the same command that I send.

What to do when Arduino sends empty ArrayBuffer to NW.js?

I've been playing around with the MPR121-Shield Capacitive Touch Sensor by Adafruit. In Arduino's IDE, there is an example of code you can simply download and run, and it works perfectly : when I touch on the pin 11, for example, it returns ''11 touched'', and when I release it, it returns ''11 pressed''. Great!
Now the problem comes when I try to transfer that data to NW.js. By using Chrome's serial port in NW.js, I can connect to the port in which my Arduino is connected, and try to read whichever data the Arduino is sending. However, as I try to read the data, the only thing I receive is an ArrayBuffer filled with bytes of 0. I am really not sure what is happening here, as both devices work perfectly when I run it in Arduino's IDE, but it returns basically nothing with chrome.serialport.
Does anyone have a tip or an idea of what's going on here? If I do a console.log(info.data), I only get an ArrayBuffer with empty bites.
Thanks
Here is my code :
const ab2str = require('arraybuffer-to-string');
nw.Window.get().showDevTools();
let buffer = "";
chrome.serial.getDevices(devices => {
devices.forEach(device => console.log(device));
});
// let port = "COM3";
let port = "/dev/cu.usbmodem142401";
chrome.serial.connect(port, {bitrate: 1000000}, () => {
console.log("Serialport connected:" + port);
chrome.serial.onReceive.addListener(onDataReceived);
});
function onDataReceived(info) {
let lines = ab2str(info.data).split("\n");
lines[0] = buffer + lines[0];
buffer = lines.pop();
lines.forEach(line => {
const [type, value] = line.split("=");
console.log(type, value);
});
}
The Tx and Rx baud rates has to be the same to properly decode the information, and the arduino IDE handles that for you in the first case, but you will need to handle it manually for the second case. In serial port communication, single bit is transferred at a time unlike in parallel ports where you will have all bits availed at the same time for reading. So, in serial ports, the rate at which the information is transmitted(Tx) should be the same as the rate at which the information is received(Rx), otherwise bits could be lost and you may get a wrong information. The arduino IDE handles most of these issues for you, if I'm not wrong the IDE allows you to change the baud rate, but the default is 9600.

Invalid parameter in encrypt (JavaScript, UWP)

I would like to encrypt data in UWP appliaction writen in javascript.
var publicKey = Windows.Security.Cryptography.Core.PersistedKeyProvider.openPublicKeyFromCertificate(cert, "", Windows.Security.Cryptography.Core.CryptographicPadding.none);
var buffer = Windows.Security.Cryptography.CryptographicBuffer.createFromByteArray(bytes);
var iv = null;
var encrypted = Windows.Security.Cryptography.Core.CryptographicEngine.encrypt(publicKey, buffer, iv);
But I get exception on the last line:
0x80090027 - JavaScript runtime error: Parametr není správný.
(Invalid parameter)
But which parameter?
Certificate is created by command
New-SelfSignedCertificate -Type Custom -Subject "test" -KeyAlgorithm RSA -KeyLength 2048 -CertStoreLocation "Cert:\CurrentUser\My"
and obtained by Windows.Security.Cryptography.Certificates.CertificateStores.
When RSA is used, buffer must have some defined size. If it is smaller exception (Invalid parameter - without any details) is raised.
When padding is changed from CryptographicPadding.none to CryptographicPadding.rsaPkcs1V15 encrypting works.

How to message child process in Firefox add-on like Chrome native messaging

I am trying to emulate Chrome's native messaging feature using Firefox's add-on SDK. Specifically, I'm using the child_process module along with the emit method to communicate with a python child process.
I am able to successfully send messages to the child process, but I am having trouble getting messages sent back to the add-on. Chrome's native messaging feature uses stdin/stdout. The first 4 bytes of every message in both directions represents the size in bytes of the following message so the receiver knows how much to read. Here's what I have so far:
Add-on to Child Process
var utf8 = new TextEncoder("utf-8").encode(message);
var latin = new TextDecoder("latin1").decode(utf8);
emit(childProcess.stdin, "data", new TextDecoder("latin1").decode(new Uint32Array([utf8.length])));
emit(childProcess.stdin, "data", latin);
emit(childProcess.stdin, "end");
Child Process (Python) from Add-on
text_length_bytes = sys.stdin.read(4)
text_length = struct.unpack('i', text_length_bytes)[0]
text = sys.stdin.read(text_length).decode('utf-8')
Child Process to Add-on
sys.stdout.write(struct.pack('I', len(message)))
sys.stdout.write(message)
sys.stdout.flush()
Add-on from Child Process
This is where I'm struggling. I have it working when the length is less than 255. For instance, if the length is 55, this works:
childProcess.stdout.on('data', (data) => { // data is '7' (55 UTF-8 encoded)
var utf8Encoded = new TextEncoder("utf-8).encode(data);
console.log(utf8Encoded[0]); // 55
}
But, like I said, it does not work for all numbers. I'm sure I have to do something with TypedArrays, but I'm struggling to put everything together.
The problem here, is that Firefox is trying to read stdout as UTF-8 stream by default. Since UTF-8 doesn't use the full first byte, you get corrupted characters for example for 255. The solution is to tell Firefox to read in binary encoding, which means you'll have to manually parse the actual message content later on.
var childProcess = spawn("mybin", [ '-a' ], { encoding: null });
Your listener would then work like
var decoder = new TextDecoder("utf-8");
var readIncoming = (data) => {
// read the first four bytes, which indicate the size of the following message
var size = (new Uint32Array(data.subarray(0, 4).buffer))[0];
//TODO: handle size > data.byteLength - 4
// read the message
var message = decoder.decode(data.subarray(4, size));
//TODO: do stuff with message
// Read the next message if there are more bytes.
if(data.byteLength > 4 + size)
readIncoming(data.subarray(4 + size));
};
childProcess.stdout.on('data', (data) => {
// convert the data string to a byte array
// The bytes got converted by char code, see https://dxr.mozilla.org/mozilla-central/source/addon-sdk/source/lib/sdk/system/child_process/subprocess.js#357
var bytes = Uint8Array.from(data, (c) => c.charCodeAt(0));
readIncoming(bytes);
});
Maybe is this similar to this problem:
Chrome native messaging doesn't accept messages of certain sizes (Windows)
Windows-only: Make sure that the program's I/O mode is set to O_BINARY. By default, the I/O mode is O_TEXT, which corrupts the message format as line breaks (\n = 0A) are replaced with Windows-style line endings (\r\n = 0D 0A). The I/O mode can be set using __setmode.

Javascript with SJCL lib, decrypt AES in GCM mode

I try to decrypt an cipher with AES in GCM mode with the SJCL library in Javascript (from within CasperJS).
When I execute the code below the error I receive is:
error: TypeError: 'undefined' is not a function (evaluating 'b.encrypt([0,
0,0,0])')
The code:
var masterkey = '39537496606860671661230109146651832357';
var cipher = 'Sa2Rk3bbdiaI7mO/';
var iv = '59804781381539321505720964105';
var authdata = '199590863504973848417387014842606357793';
var decff = sjcl.mode.gcm.decrypt(masterkey, cipher, iv, authdata);
console.log (decff);
As you can see, I am basically just calling the decrypt function as the SJCL docs told me to.
The encryption was done in python with this code: https://github.com/bozhu/AES-GCM-Python Wich I found is this thread: AES in GCM mode in Python
Is there anything special I have to consider when encrypting in one language and decrypting in another? Im afraid so...
Can I check somehow if the encryption information are valid AES/GCM?
Im not really sure how to proceed here since Im no JS or Python or encryption expert.
For background information:
I try to achieve a more or less secure encryption in pure python (so I can run it on Google App Engine) and the fitting decryption in pure JS.
Thanks for any help.
You cannot directly decrypt try converting your encrypted string, cypher, IV and auth data to bitArray.
const data = sjcl.mode.gcm.decrypt(cipherArray, encryptedBitArray, iv, authArray, 128);
Here 128 is size you can use 256 as well.
Also try to append your IV with the encypted string.
const bitArray = sjcl.codec.base64.toBits(content);
const bitArrayCopy = bitArray.slice(0);
const ivdec = bitArrayCopy.slice(0, 4);
const encryptedBitArray = bitArray.slice(4);
var key = sjcl.codec.base64.toBits("2d73c1dd2f6a3c981afc7c0d49d7b58f");
let cipher = new sjcl.cipher.aes(key);

Categories