New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

node-opcua-chunkmanager

Package Overview
Dependencies
Maintainers
1
Versions
185
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-opcua-chunkmanager - npm Package Compare versions

Comparing version 2.128.0 to 2.129.0

55

dist/chunk_manager.d.ts

@@ -0,1 +1,3 @@

/// <reference types="node" />
/// <reference types="node" />
/***

@@ -6,6 +8,6 @@ * @module node-opcua-chunkmanager

export declare function verify_message_chunk(messageChunk: Buffer): void;
export type WriteHeaderFunc = (chunk: Buffer, isLast: boolean, expectedLength: number) => void;
export type WriteSequenceHeaderFunc = (chunk: Buffer) => void;
export type SignBufferFunc = (buffer: Buffer) => Buffer;
export type EncryptBufferFunc = (buffer: Buffer) => Buffer;
export type WriteHeaderFunc = (this: ChunkManager, chunk: Buffer, isLast: boolean, expectedLength: number) => void;
export type WriteSequenceHeaderFunc = (this: ChunkManager, chunk: Buffer) => void;
export type SignBufferFunc = (this: ChunkManager, buffer: Buffer) => Buffer;
export type EncryptBufferFunc = (this: ChunkManager, buffer: Buffer) => Buffer;
export interface IChunkManagerOptions {

@@ -23,21 +25,18 @@ chunkSize: number;

}
export declare enum Mode {
None = 1,
Sign = 2,
SignAndEncrypt = 3
}
export declare class ChunkManager extends EventEmitter {
signBufferFunc?: SignBufferFunc;
encryptBufferFunc?: EncryptBufferFunc;
writeSequenceHeaderFunc?: WriteSequenceHeaderFunc;
writeHeaderFunc?: WriteHeaderFunc;
private readonly chunkSize;
private readonly headerSize;
private readonly signatureLength;
private readonly sequenceHeaderSize;
private readonly cipherBlockSize;
private readonly plainBlockSize;
private readonly maxBodySize;
private readonly maxBlock?;
private readonly dataOffset;
private chunk;
private cursor;
private pendingChunk;
private dataEnd;
constructor(options: IChunkManagerOptions);
#private;
readonly chunkSize: number;
readonly headerSize: number;
readonly maxBodySize: number;
readonly signatureLength: number;
readonly sequenceHeaderSize: number;
readonly cipherBlockSize: number;
readonly plainBlockSize: number;
readonly securityMode: Mode;
constructor(securityMode: Mode, options: IChunkManagerOptions);
evaluateTotalLengthAndChunks(bodySize: number): {

@@ -49,14 +48,2 @@ totalLength: number;

end(): void;
/**
* compute the signature of the chunk and append it at the end
* of the data block.
*
* @method _write_signature
* @private
*/
private _write_signature;
private _encrypt;
private _push_pending_chunk;
private _write_padding_bytes;
private _post_process_current_chunk;
}
"use strict";
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _ChunkManager_instances, _ChunkManager_signBufferFunc, _ChunkManager_encryptBufferFunc, _ChunkManager_writeSequenceHeaderFunc, _ChunkManager_writeHeaderFunc, _ChunkManager_maxBlock, _ChunkManager_dataOffset, _ChunkManager_chunk, _ChunkManager_cursor, _ChunkManager_pendingChunk, _ChunkManager_dataEnd, _ChunkManager__write_signature, _ChunkManager__encrypt, _ChunkManager__push_pending_chunk, _ChunkManager__write_padding_bytes, _ChunkManager__post_process_current_chunk;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChunkManager = void 0;
exports.verify_message_chunk = verify_message_chunk;
exports.ChunkManager = exports.Mode = exports.verify_message_chunk = void 0;
/***

@@ -21,5 +32,25 @@ * @module node-opcua-chunkmanager

}
exports.verify_message_chunk = verify_message_chunk;
var Mode;
(function (Mode) {
Mode[Mode["None"] = 1] = "None";
Mode[Mode["Sign"] = 2] = "Sign";
Mode[Mode["SignAndEncrypt"] = 3] = "SignAndEncrypt";
})(Mode || (exports.Mode = Mode = {}));
class ChunkManager extends events_1.EventEmitter {
constructor(options) {
constructor(securityMode, options) {
super();
_ChunkManager_instances.add(this);
_ChunkManager_signBufferFunc.set(this, void 0);
_ChunkManager_encryptBufferFunc.set(this, void 0);
_ChunkManager_writeSequenceHeaderFunc.set(this, void 0);
_ChunkManager_writeHeaderFunc.set(this, void 0);
// --------------
_ChunkManager_maxBlock.set(this, void 0);
_ChunkManager_dataOffset.set(this, void 0);
_ChunkManager_chunk.set(this, void 0);
_ChunkManager_cursor.set(this, void 0);
_ChunkManager_pendingChunk.set(this, void 0);
_ChunkManager_dataEnd.set(this, void 0);
this.securityMode = securityMode;
// { chunkSize : 32, headerSize : 10 ,signatureLength: 32 }

@@ -29,22 +60,25 @@ this.chunkSize = options.chunkSize;

if (this.headerSize) {
this.writeHeaderFunc = options.writeHeaderFunc;
(0, node_opcua_assert_1.assert)(typeof this.writeHeaderFunc === "function");
__classPrivateFieldSet(this, _ChunkManager_writeHeaderFunc, options.writeHeaderFunc, "f");
(0, node_opcua_assert_1.assert)(typeof __classPrivateFieldGet(this, _ChunkManager_writeHeaderFunc, "f") === "function");
}
this.sequenceHeaderSize = options.sequenceHeaderSize === undefined ? 8 : options.sequenceHeaderSize;
if (this.sequenceHeaderSize > 0) {
this.writeSequenceHeaderFunc = options.writeSequenceHeaderFunc;
(0, node_opcua_assert_1.assert)(typeof this.writeSequenceHeaderFunc === "function");
__classPrivateFieldSet(this, _ChunkManager_writeSequenceHeaderFunc, options.writeSequenceHeaderFunc, "f");
(0, node_opcua_assert_1.assert)(typeof __classPrivateFieldGet(this, _ChunkManager_writeSequenceHeaderFunc, "f") === "function");
}
this.signatureLength = options.signatureLength || 0;
this.signBufferFunc = options.signBufferFunc;
__classPrivateFieldSet(this, _ChunkManager_signBufferFunc, options.signBufferFunc, "f");
this.plainBlockSize = options.plainBlockSize || 0; // 256-14;
this.cipherBlockSize = options.cipherBlockSize || 0; // 256;
this.dataEnd = 0;
__classPrivateFieldSet(this, _ChunkManager_dataEnd, 0, "f");
if (this.cipherBlockSize === 0) {
(0, node_opcua_assert_1.assert)(securityMode === Mode.None || securityMode === Mode.Sign);
// we don't encrypt,we just sign
(0, node_opcua_assert_1.assert)(this.plainBlockSize === 0);
// unencrypted block
this.maxBodySize = this.chunkSize - this.headerSize - this.signatureLength - this.sequenceHeaderSize;
this.encryptBufferFunc = undefined;
__classPrivateFieldSet(this, _ChunkManager_encryptBufferFunc, undefined, "f");
}
else {
(0, node_opcua_assert_1.assert)(securityMode === Mode.SignAndEncrypt || securityMode === Mode.Sign);
(0, node_opcua_assert_1.assert)(this.plainBlockSize !== 0);

@@ -54,4 +88,4 @@ // During encryption a block with a size equal to PlainTextBlockSize is processed to produce a block

// be the same.
this.encryptBufferFunc = options.encryptBufferFunc;
(0, node_opcua_assert_1.assert)(typeof this.encryptBufferFunc === "function", "an encryptBufferFunc is required");
__classPrivateFieldSet(this, _ChunkManager_encryptBufferFunc, options.encryptBufferFunc, "f");
(0, node_opcua_assert_1.assert)(typeof __classPrivateFieldGet(this, _ChunkManager_encryptBufferFunc, "f") === "function", "an encryptBufferFunc is required");
// this is the formula proposed by OPCUA

@@ -63,4 +97,4 @@ this.maxBodySize =

// this is the formula proposed by ERN
this.maxBlock = Math.floor((this.chunkSize - this.headerSize) / this.cipherBlockSize);
this.maxBodySize = this.plainBlockSize * this.maxBlock - this.sequenceHeaderSize - this.signatureLength - 1;
__classPrivateFieldSet(this, _ChunkManager_maxBlock, Math.floor((this.chunkSize - this.headerSize) / this.cipherBlockSize), "f");
this.maxBodySize = this.plainBlockSize * __classPrivateFieldGet(this, _ChunkManager_maxBlock, "f") - this.sequenceHeaderSize - this.signatureLength - 1;
if (this.plainBlockSize > 256) {

@@ -72,6 +106,6 @@ this.maxBodySize -= 1;

// where the data starts in the block
this.dataOffset = this.headerSize + this.sequenceHeaderSize;
this.chunk = null;
this.cursor = 0;
this.pendingChunk = null;
__classPrivateFieldSet(this, _ChunkManager_dataOffset, this.headerSize + this.sequenceHeaderSize, "f");
__classPrivateFieldSet(this, _ChunkManager_chunk, null, "f");
__classPrivateFieldSet(this, _ChunkManager_cursor, 0, "f");
__classPrivateFieldSet(this, _ChunkManager_pendingChunk, null, "f");
}

@@ -91,16 +125,16 @@ evaluateTotalLengthAndChunks(bodySize) {

(0, node_opcua_assert_1.assert)(length - inputCursor !== 0);
if (this.cursor === 0) {
this._push_pending_chunk(false);
if (__classPrivateFieldGet(this, _ChunkManager_cursor, "f") === 0) {
__classPrivateFieldGet(this, _ChunkManager_instances, "m", _ChunkManager__push_pending_chunk).call(this, false);
}
// space left in current chunk
const spaceLeft = this.maxBodySize - this.cursor;
const spaceLeft = this.maxBodySize - __classPrivateFieldGet(this, _ChunkManager_cursor, "f");
const nbToWrite = Math.min(length - inputCursor, spaceLeft);
this.chunk = this.chunk || (0, node_opcua_buffer_utils_1.createFastUninitializedBuffer)(this.chunkSize);
__classPrivateFieldSet(this, _ChunkManager_chunk, __classPrivateFieldGet(this, _ChunkManager_chunk, "f") || (0, node_opcua_buffer_utils_1.createFastUninitializedBuffer)(this.chunkSize), "f");
if (buffer) {
buffer.copy(this.chunk, this.cursor + this.dataOffset, inputCursor, inputCursor + nbToWrite);
buffer.copy(__classPrivateFieldGet(this, _ChunkManager_chunk, "f"), __classPrivateFieldGet(this, _ChunkManager_cursor, "f") + __classPrivateFieldGet(this, _ChunkManager_dataOffset, "f"), inputCursor, inputCursor + nbToWrite);
}
inputCursor += nbToWrite;
this.cursor += nbToWrite;
if (this.cursor >= this.maxBodySize) {
this._post_process_current_chunk();
__classPrivateFieldSet(this, _ChunkManager_cursor, __classPrivateFieldGet(this, _ChunkManager_cursor, "f") + nbToWrite, "f");
if (__classPrivateFieldGet(this, _ChunkManager_cursor, "f") >= this.maxBodySize) {
__classPrivateFieldGet(this, _ChunkManager_instances, "m", _ChunkManager__post_process_current_chunk).call(this);
}

@@ -111,119 +145,116 @@ l -= nbToWrite;

end() {
if (this.cursor > 0) {
this._post_process_current_chunk();
if (__classPrivateFieldGet(this, _ChunkManager_cursor, "f") > 0) {
__classPrivateFieldGet(this, _ChunkManager_instances, "m", _ChunkManager__post_process_current_chunk).call(this);
}
this._push_pending_chunk(true);
__classPrivateFieldGet(this, _ChunkManager_instances, "m", _ChunkManager__push_pending_chunk).call(this, true);
}
/**
* compute the signature of the chunk and append it at the end
* of the data block.
*
* @method _write_signature
* @private
*/
_write_signature(chunk) {
if (this.signBufferFunc) {
(0, node_opcua_assert_1.assert)(typeof this.signBufferFunc === "function");
(0, node_opcua_assert_1.assert)(this.signatureLength !== 0);
const signatureStart = this.dataEnd;
const sectionToSign = chunk.subarray(0, signatureStart);
const signature = this.signBufferFunc(sectionToSign);
(0, node_opcua_assert_1.assert)(signature.length === this.signatureLength, "expecting signature length to match");
signature.copy(chunk, signatureStart);
}
exports.ChunkManager = ChunkManager;
_ChunkManager_signBufferFunc = new WeakMap(), _ChunkManager_encryptBufferFunc = new WeakMap(), _ChunkManager_writeSequenceHeaderFunc = new WeakMap(), _ChunkManager_writeHeaderFunc = new WeakMap(), _ChunkManager_maxBlock = new WeakMap(), _ChunkManager_dataOffset = new WeakMap(), _ChunkManager_chunk = new WeakMap(), _ChunkManager_cursor = new WeakMap(), _ChunkManager_pendingChunk = new WeakMap(), _ChunkManager_dataEnd = new WeakMap(), _ChunkManager_instances = new WeakSet(), _ChunkManager__write_signature = function _ChunkManager__write_signature(chunk) {
if (this.securityMode === Mode.None) {
(0, node_opcua_assert_1.assert)(this.signatureLength === 0, "expecting NO SIGN");
return;
}
if (__classPrivateFieldGet(this, _ChunkManager_signBufferFunc, "f")) {
(0, node_opcua_assert_1.assert)(typeof __classPrivateFieldGet(this, _ChunkManager_signBufferFunc, "f") === "function");
(0, node_opcua_assert_1.assert)(this.signatureLength !== 0);
const signatureStart = __classPrivateFieldGet(this, _ChunkManager_dataEnd, "f");
const sectionToSign = chunk.subarray(0, signatureStart);
const signature = __classPrivateFieldGet(this, _ChunkManager_signBufferFunc, "f").call(this, sectionToSign);
(0, node_opcua_assert_1.assert)(signature.length === this.signatureLength, "expecting signature length to match");
signature.copy(chunk, signatureStart);
}
else {
(0, node_opcua_assert_1.assert)(this.signatureLength === 0, "expecting NO SIGN");
}
}, _ChunkManager__encrypt = function _ChunkManager__encrypt(chunk) {
if (this.securityMode === Mode.None) {
// nothing todo
return;
}
if (this.plainBlockSize > 0 && __classPrivateFieldGet(this, _ChunkManager_encryptBufferFunc, "f")) {
(0, node_opcua_assert_1.assert)(__classPrivateFieldGet(this, _ChunkManager_dataEnd, "f") !== undefined);
const startEncryptionPos = this.headerSize;
const endEncryptionPos = __classPrivateFieldGet(this, _ChunkManager_dataEnd, "f") + this.signatureLength;
const areaToEncrypt = chunk.subarray(startEncryptionPos, endEncryptionPos);
(0, node_opcua_assert_1.assert)(areaToEncrypt.length % this.plainBlockSize === 0); // padding should have been applied
const nbBlock = areaToEncrypt.length / this.plainBlockSize;
const encryptedBuffer = __classPrivateFieldGet(this, _ChunkManager_encryptBufferFunc, "f").call(this, areaToEncrypt);
(0, node_opcua_assert_1.assert)(encryptedBuffer.length % this.cipherBlockSize === 0);
(0, node_opcua_assert_1.assert)(encryptedBuffer.length === nbBlock * this.cipherBlockSize);
encryptedBuffer.copy(chunk, this.headerSize, 0);
}
}, _ChunkManager__push_pending_chunk = function _ChunkManager__push_pending_chunk(isLast) {
if (__classPrivateFieldGet(this, _ChunkManager_pendingChunk, "f")) {
const expectedLength = __classPrivateFieldGet(this, _ChunkManager_pendingChunk, "f").length;
if (this.headerSize > 0) {
// Release 1.02 39 OPC Unified Architecture, Part 6:
// The sequence header ensures that the first encrypted block of every Message sent over
// a channel will start with different data.
__classPrivateFieldGet(this, _ChunkManager_writeHeaderFunc, "f").call(this, __classPrivateFieldGet(this, _ChunkManager_pendingChunk, "f").subarray(0, this.headerSize), isLast, expectedLength);
}
else {
(0, node_opcua_assert_1.assert)(this.signatureLength === 0, "expecting NO SIGN");
if (this.sequenceHeaderSize > 0) {
__classPrivateFieldGet(this, _ChunkManager_writeSequenceHeaderFunc, "f").call(this, __classPrivateFieldGet(this, _ChunkManager_pendingChunk, "f").subarray(this.headerSize, this.headerSize + this.sequenceHeaderSize));
}
__classPrivateFieldGet(this, _ChunkManager_instances, "m", _ChunkManager__write_signature).call(this, __classPrivateFieldGet(this, _ChunkManager_pendingChunk, "f"));
__classPrivateFieldGet(this, _ChunkManager_instances, "m", _ChunkManager__encrypt).call(this, __classPrivateFieldGet(this, _ChunkManager_pendingChunk, "f"));
/**
* @event chunk
* @param chunk {Buffer}
* @param isLast {Boolean} , true if final chunk
*/
this.emit("chunk", __classPrivateFieldGet(this, _ChunkManager_pendingChunk, "f"), isLast);
__classPrivateFieldSet(this, _ChunkManager_pendingChunk, null, "f");
}
_encrypt(chunk) {
if (this.plainBlockSize > 0) {
(0, node_opcua_assert_1.assert)(this.dataEnd !== undefined);
const startEncryptionPos = this.headerSize;
const endEncryptionPos = this.dataEnd + this.signatureLength;
const areaToEncrypt = chunk.subarray(startEncryptionPos, endEncryptionPos);
(0, node_opcua_assert_1.assert)(areaToEncrypt.length % this.plainBlockSize === 0); // padding should have been applied
const nbBlock = areaToEncrypt.length / this.plainBlockSize;
const encryptedBuffer = this.encryptBufferFunc(areaToEncrypt);
(0, node_opcua_assert_1.assert)(encryptedBuffer.length % this.cipherBlockSize === 0);
(0, node_opcua_assert_1.assert)(encryptedBuffer.length === nbBlock * this.cipherBlockSize);
encryptedBuffer.copy(chunk, this.headerSize, 0);
}
}, _ChunkManager__write_padding_bytes = function _ChunkManager__write_padding_bytes(nbPaddingByteTotal) {
const nbPaddingByte = nbPaddingByteTotal % 256;
const extraNbPaddingByte = Math.floor(nbPaddingByteTotal / 256);
(0, node_opcua_assert_1.assert)(extraNbPaddingByte === 0 || this.plainBlockSize > 256, "extraNbPaddingByte only requested when key size > 2048");
// write the padding byte
__classPrivateFieldGet(this, _ChunkManager_chunk, "f").writeUInt8(nbPaddingByte, __classPrivateFieldGet(this, _ChunkManager_cursor, "f") + __classPrivateFieldGet(this, _ChunkManager_dataOffset, "f"));
__classPrivateFieldSet(this, _ChunkManager_cursor, __classPrivateFieldGet(this, _ChunkManager_cursor, "f") + 1, "f");
for (let i = 0; i < nbPaddingByteTotal; i++) {
__classPrivateFieldGet(this, _ChunkManager_chunk, "f").writeUInt8(nbPaddingByte, __classPrivateFieldGet(this, _ChunkManager_cursor, "f") + __classPrivateFieldGet(this, _ChunkManager_dataOffset, "f") + i);
}
_push_pending_chunk(isLast) {
if (this.pendingChunk) {
const expectedLength = this.pendingChunk.length;
if (this.headerSize > 0) {
// Release 1.02 39 OPC Unified Architecture, Part 6:
// The sequence header ensures that the first encrypted block of every Message sent over
// a channel will start with different data.
this.writeHeaderFunc(this.pendingChunk.subarray(0, this.headerSize), isLast, expectedLength);
}
if (this.sequenceHeaderSize > 0) {
this.writeSequenceHeaderFunc(this.pendingChunk.subarray(this.headerSize, this.headerSize + this.sequenceHeaderSize));
}
this._write_signature(this.pendingChunk);
this._encrypt(this.pendingChunk);
/**
* @event chunk
* @param chunk {Buffer}
* @param isLast {Boolean} , true if final chunk
*/
this.emit("chunk", this.pendingChunk, isLast);
this.pendingChunk = null;
}
__classPrivateFieldSet(this, _ChunkManager_cursor, __classPrivateFieldGet(this, _ChunkManager_cursor, "f") + nbPaddingByteTotal, "f");
if (this.plainBlockSize > 256) {
__classPrivateFieldGet(this, _ChunkManager_chunk, "f").writeUInt8(extraNbPaddingByte, __classPrivateFieldGet(this, _ChunkManager_cursor, "f") + __classPrivateFieldGet(this, _ChunkManager_dataOffset, "f"));
__classPrivateFieldSet(this, _ChunkManager_cursor, __classPrivateFieldGet(this, _ChunkManager_cursor, "f") + 1, "f");
}
_write_padding_bytes(nbPaddingByteTotal) {
const nbPaddingByte = nbPaddingByteTotal % 256;
const extraNbPaddingByte = Math.floor(nbPaddingByteTotal / 256);
(0, node_opcua_assert_1.assert)(extraNbPaddingByte === 0 || this.plainBlockSize > 256, "extraNbPaddingByte only requested when key size > 2048");
// write the padding byte
this.chunk.writeUInt8(nbPaddingByte, this.cursor + this.dataOffset);
this.cursor += 1;
for (let i = 0; i < nbPaddingByteTotal; i++) {
this.chunk.writeUInt8(nbPaddingByte, this.cursor + this.dataOffset + i);
}
this.cursor += nbPaddingByteTotal;
}, _ChunkManager__post_process_current_chunk = function _ChunkManager__post_process_current_chunk() {
let extraEncryptionBytes = 0;
// add padding bytes if needed
if (this.plainBlockSize > 0) {
// write padding ( if encryption )
// let's calculate curLength = the length of the block to encrypt without padding yet
// +---------------+---------------+-------------+---------+--------------+------------+
// |SequenceHeader | data | paddingByte | padding | extraPadding | signature |
// +---------------+---------------+-------------+---------+--------------+------------+
let curLength = this.sequenceHeaderSize + __classPrivateFieldGet(this, _ChunkManager_cursor, "f") + this.signatureLength;
if (this.plainBlockSize > 256) {
this.chunk.writeUInt8(extraNbPaddingByte, this.cursor + this.dataOffset);
this.cursor += 1;
curLength += 2; // account for extraPadding Byte Number;
}
}
_post_process_current_chunk() {
let extraEncryptionBytes = 0;
// add padding bytes if needed
if (this.plainBlockSize > 0) {
// write padding ( if encryption )
// let's calculate curLength = the length of the block to encrypt without padding yet
// +---------------+---------------+-------------+---------+--------------+------------+
// |SequenceHeader | data | paddingByte | padding | extraPadding | signature |
// +---------------+---------------+-------------+---------+--------------+------------+
let curLength = this.sequenceHeaderSize + this.cursor + this.signatureLength;
if (this.plainBlockSize > 256) {
curLength += 2; // account for extraPadding Byte Number;
}
else {
curLength += 1;
}
// let's calculate the required number of padding bytes
const n = curLength % this.plainBlockSize;
const nbPaddingByteTotal = (this.plainBlockSize - n) % this.plainBlockSize;
this._write_padding_bytes(nbPaddingByteTotal);
const adjustedLength = this.sequenceHeaderSize + this.cursor + this.signatureLength;
(0, node_opcua_assert_1.assert)(adjustedLength % this.plainBlockSize === 0);
const nbBlock = adjustedLength / this.plainBlockSize;
extraEncryptionBytes = nbBlock * (this.cipherBlockSize - this.plainBlockSize);
else {
curLength += 1;
}
this.dataEnd = this.dataOffset + this.cursor;
// calculate the expected length of the chunk, once encrypted if encryption apply
const expectedLength = this.dataEnd + this.signatureLength + extraEncryptionBytes;
this.pendingChunk = this.chunk.subarray(0, expectedLength);
// note :
// - this.pending_chunk has the correct size but is not signed nor encrypted yet
// as we don't know what to write in the header yet
// - as a result,
this.chunk = null;
this.cursor = 0;
// let's calculate the required number of padding bytes
const n = curLength % this.plainBlockSize;
const nbPaddingByteTotal = (this.plainBlockSize - n) % this.plainBlockSize;
__classPrivateFieldGet(this, _ChunkManager_instances, "m", _ChunkManager__write_padding_bytes).call(this, nbPaddingByteTotal);
const adjustedLength = this.sequenceHeaderSize + __classPrivateFieldGet(this, _ChunkManager_cursor, "f") + this.signatureLength;
(0, node_opcua_assert_1.assert)(adjustedLength % this.plainBlockSize === 0);
const nbBlock = adjustedLength / this.plainBlockSize;
extraEncryptionBytes = nbBlock * (this.cipherBlockSize - this.plainBlockSize);
}
}
exports.ChunkManager = ChunkManager;
__classPrivateFieldSet(this, _ChunkManager_dataEnd, __classPrivateFieldGet(this, _ChunkManager_dataOffset, "f") + __classPrivateFieldGet(this, _ChunkManager_cursor, "f"), "f");
// calculate the expected length of the chunk, once encrypted if encryption apply
const expectedLength = __classPrivateFieldGet(this, _ChunkManager_dataEnd, "f") + this.signatureLength + extraEncryptionBytes;
__classPrivateFieldSet(this, _ChunkManager_pendingChunk, __classPrivateFieldGet(this, _ChunkManager_chunk, "f").subarray(0, expectedLength), "f");
// note :
// - this.pending_chunk has the correct size but is not signed nor encrypted yet
// as we don't know what to write in the header yet
// - as a result,
__classPrivateFieldSet(this, _ChunkManager_chunk, null, "f");
__classPrivateFieldSet(this, _ChunkManager_cursor, 0, "f");
};
//# sourceMappingURL=chunk_manager.js.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.readMessageHeader = readMessageHeader;
exports.readMessageHeader = void 0;
function readMessageHeader(stream) {
const msgType = String.fromCharCode(stream.readUInt8()) +
String.fromCharCode(stream.readUInt8()) +
String.fromCharCode(stream.readUInt8());
const msgType = String.fromCharCode(stream.readUInt8()) + String.fromCharCode(stream.readUInt8()) + String.fromCharCode(stream.readUInt8());
const isFinal = String.fromCharCode(stream.readUInt8());

@@ -12,2 +10,3 @@ const length = stream.readUInt32();

}
exports.readMessageHeader = readMessageHeader;
//# sourceMappingURL=read_message_header.js.map
{
"name": "node-opcua-chunkmanager",
"version": "2.128.0",
"version": "2.129.0",
"description": "pure nodejs OPCUA SDK - module chunkmanager",

@@ -39,3 +39,3 @@ "main": "./dist/index.js",

"homepage": "http://node-opcua.github.io/",
"gitHead": "67a73af6b831d8651a0e66ceb295f159cab4386b",
"gitHead": "8a1754350fb95a764e278d37a289f0c48ccb8c9d",
"files": [

@@ -42,0 +42,0 @@ "dist",

@@ -52,6 +52,6 @@ /***

export type WriteHeaderFunc = (chunk: Buffer, isLast: boolean, expectedLength: number) => void;
export type WriteSequenceHeaderFunc = (chunk: Buffer) => void;
export type SignBufferFunc = (buffer: Buffer) => Buffer;
export type EncryptBufferFunc = (buffer: Buffer) => Buffer;
export type WriteHeaderFunc = (this: ChunkManager, chunk: Buffer, isLast: boolean, expectedLength: number) => void;
export type WriteSequenceHeaderFunc = (this: ChunkManager, chunk: Buffer) => void;
export type SignBufferFunc = (this: ChunkManager, buffer: Buffer) => Buffer;
export type EncryptBufferFunc = (this: ChunkManager, buffer: Buffer) => Buffer;

@@ -73,27 +73,38 @@ export interface IChunkManagerOptions {

export enum Mode {
None = 1,
Sign = 2,
SignAndEncrypt = 3
}
export class ChunkManager extends EventEmitter {
public signBufferFunc?: SignBufferFunc;
public encryptBufferFunc?: EncryptBufferFunc;
public writeSequenceHeaderFunc?: WriteSequenceHeaderFunc;
public writeHeaderFunc?: WriteHeaderFunc;
#signBufferFunc?: SignBufferFunc;
#encryptBufferFunc?: EncryptBufferFunc;
#writeSequenceHeaderFunc?: WriteSequenceHeaderFunc;
#writeHeaderFunc?: WriteHeaderFunc;
private readonly chunkSize: number;
private readonly headerSize: number;
private readonly signatureLength: number;
private readonly sequenceHeaderSize: number;
private readonly cipherBlockSize: number;
private readonly plainBlockSize: number;
public readonly chunkSize: number;
public readonly headerSize: number;
public readonly maxBodySize: number;
public readonly signatureLength: number;
public readonly sequenceHeaderSize: number;
public readonly cipherBlockSize: number;
public readonly plainBlockSize: number;
// --------------
private readonly maxBodySize: number;
private readonly maxBlock?: number;
private readonly dataOffset: number;
private chunk: Buffer | null;
private cursor: number;
private pendingChunk: Buffer | null;
private dataEnd: number;
readonly #maxBlock?: number;
constructor(options: IChunkManagerOptions) {
readonly #dataOffset: number;
public readonly securityMode: Mode;
#chunk: Buffer | null;
#cursor: number;
#pendingChunk: Buffer | null;
#dataEnd: number;
constructor(securityMode: Mode, options: IChunkManagerOptions) {
super();
this.securityMode = securityMode;
// { chunkSize : 32, headerSize : 10 ,signatureLength: 32 }

@@ -104,4 +115,4 @@ this.chunkSize = options.chunkSize;

if (this.headerSize) {
this.writeHeaderFunc = options.writeHeaderFunc;
assert(typeof this.writeHeaderFunc === "function");
this.#writeHeaderFunc = options.writeHeaderFunc;
assert(typeof this.#writeHeaderFunc === "function");
}

@@ -111,19 +122,22 @@

if (this.sequenceHeaderSize > 0) {
this.writeSequenceHeaderFunc = options.writeSequenceHeaderFunc;
assert(typeof this.writeSequenceHeaderFunc === "function");
this.#writeSequenceHeaderFunc = options.writeSequenceHeaderFunc;
assert(typeof this.#writeSequenceHeaderFunc === "function");
}
this.signatureLength = options.signatureLength || 0;
this.signBufferFunc = options.signBufferFunc;
this.#signBufferFunc = options.signBufferFunc;
this.plainBlockSize = options.plainBlockSize || 0; // 256-14;
this.cipherBlockSize = options.cipherBlockSize || 0; // 256;
this.dataEnd = 0;
this.#dataEnd = 0;
if (this.cipherBlockSize === 0) {
assert(securityMode === Mode.None || securityMode === Mode.Sign);
// we don't encrypt,we just sign
assert(this.plainBlockSize === 0);
// unencrypted block
this.maxBodySize = this.chunkSize - this.headerSize - this.signatureLength - this.sequenceHeaderSize;
this.encryptBufferFunc = undefined;
this.#encryptBufferFunc = undefined;
} else {
assert(securityMode === Mode.SignAndEncrypt || securityMode === Mode.Sign);
assert(this.plainBlockSize !== 0);

@@ -134,4 +148,4 @@ // During encryption a block with a size equal to PlainTextBlockSize is processed to produce a block

this.encryptBufferFunc = options.encryptBufferFunc;
assert(typeof this.encryptBufferFunc === "function", "an encryptBufferFunc is required");
this.#encryptBufferFunc = options.encryptBufferFunc;
assert(typeof this.#encryptBufferFunc === "function", "an encryptBufferFunc is required");

@@ -145,4 +159,4 @@ // this is the formula proposed by OPCUA

// this is the formula proposed by ERN
this.maxBlock = Math.floor((this.chunkSize - this.headerSize) / this.cipherBlockSize);
this.maxBodySize = this.plainBlockSize * this.maxBlock - this.sequenceHeaderSize - this.signatureLength - 1;
this.#maxBlock = Math.floor((this.chunkSize - this.headerSize) / this.cipherBlockSize);
this.maxBodySize = this.plainBlockSize * this.#maxBlock - this.sequenceHeaderSize - this.signatureLength - 1;

@@ -156,7 +170,7 @@ if (this.plainBlockSize > 256) {

// where the data starts in the block
this.dataOffset = this.headerSize + this.sequenceHeaderSize;
this.#dataOffset = this.headerSize + this.sequenceHeaderSize;
this.chunk = null;
this.cursor = 0;
this.pendingChunk = null;
this.#chunk = null;
this.#cursor = 0;
this.#pendingChunk = null;
}

@@ -181,22 +195,22 @@

if (this.cursor === 0) {
this._push_pending_chunk(false);
if (this.#cursor === 0) {
this.#_push_pending_chunk(false);
}
// space left in current chunk
const spaceLeft = this.maxBodySize - this.cursor;
const spaceLeft = this.maxBodySize - this.#cursor;
const nbToWrite = Math.min(length - inputCursor, spaceLeft);
this.chunk = this.chunk || createFastUninitializedBuffer(this.chunkSize);
this.#chunk = this.#chunk || createFastUninitializedBuffer(this.chunkSize);
if (buffer) {
buffer.copy(this.chunk!, this.cursor + this.dataOffset, inputCursor, inputCursor + nbToWrite);
buffer.copy(this.#chunk!, this.#cursor + this.#dataOffset, inputCursor, inputCursor + nbToWrite);
}
inputCursor += nbToWrite;
this.cursor += nbToWrite;
this.#cursor += nbToWrite;
if (this.cursor >= this.maxBodySize) {
this._post_process_current_chunk();
if (this.#cursor >= this.maxBodySize) {
this.#_post_process_current_chunk();
}

@@ -208,6 +222,6 @@ l -= nbToWrite;

public end() {
if (this.cursor > 0) {
this._post_process_current_chunk();
if (this.#cursor > 0) {
this.#_post_process_current_chunk();
}
this._push_pending_chunk(true);
this.#_push_pending_chunk(true);
}

@@ -222,13 +236,16 @@

*/
private _write_signature(chunk: Buffer) {
if (this.signBufferFunc) {
assert(typeof this.signBufferFunc === "function");
#_write_signature(chunk: Buffer) {
if (this.securityMode === Mode.None) {
assert(this.signatureLength === 0, "expecting NO SIGN");
return;
}
if (this.#signBufferFunc) {
assert(typeof this.#signBufferFunc === "function");
assert(this.signatureLength !== 0);
const signatureStart = this.dataEnd;
const signatureStart = this.#dataEnd;
const sectionToSign = chunk.subarray(0, signatureStart);
const signature = this.signBufferFunc(sectionToSign);
assert(signature.length === this.signatureLength , "expecting signature length to match");
const signature = this.#signBufferFunc.call(this, sectionToSign);
assert(signature.length === this.signatureLength, "expecting signature length to match");
signature.copy(chunk, signatureStart);

@@ -240,7 +257,11 @@ } else {

private _encrypt(chunk: Buffer) {
if (this.plainBlockSize > 0) {
assert(this.dataEnd !== undefined);
#_encrypt(chunk: Buffer) {
if (this.securityMode === Mode.None) {
// nothing todo
return;
}
if (this.plainBlockSize > 0 && this.#encryptBufferFunc) {
assert(this.#dataEnd !== undefined);
const startEncryptionPos = this.headerSize;
const endEncryptionPos = this.dataEnd + this.signatureLength;
const endEncryptionPos = this.#dataEnd + this.signatureLength;

@@ -252,3 +273,3 @@ const areaToEncrypt = chunk.subarray(startEncryptionPos, endEncryptionPos);

const encryptedBuffer = this.encryptBufferFunc!(areaToEncrypt);
const encryptedBuffer = this.#encryptBufferFunc!.call(this, areaToEncrypt);
assert(encryptedBuffer.length % this.cipherBlockSize === 0);

@@ -261,5 +282,5 @@ assert(encryptedBuffer.length === nbBlock * this.cipherBlockSize);

private _push_pending_chunk(isLast: boolean) {
if (this.pendingChunk) {
const expectedLength = this.pendingChunk.length;
#_push_pending_chunk(isLast: boolean) {
if (this.#pendingChunk) {
const expectedLength = this.#pendingChunk.length;

@@ -270,11 +291,14 @@ if (this.headerSize > 0) {

// a channel will start with different data.
this.writeHeaderFunc!(this.pendingChunk.subarray(0, this.headerSize), isLast, expectedLength);
this.#writeHeaderFunc!.call(this, this.#pendingChunk.subarray(0, this.headerSize), isLast, expectedLength);
}
if (this.sequenceHeaderSize > 0) {
this.writeSequenceHeaderFunc!(this.pendingChunk.subarray(this.headerSize, this.headerSize + this.sequenceHeaderSize));
this.#writeSequenceHeaderFunc!.call(
this,
this.#pendingChunk.subarray(this.headerSize, this.headerSize + this.sequenceHeaderSize)
);
}
this._write_signature(this.pendingChunk);
this.#_write_signature(this.#pendingChunk);
this._encrypt(this.pendingChunk);
this.#_encrypt(this.#pendingChunk);

@@ -286,8 +310,8 @@ /**

*/
this.emit("chunk", this.pendingChunk, isLast);
this.pendingChunk = null;
this.emit("chunk", this.#pendingChunk, isLast);
this.#pendingChunk = null;
}
}
private _write_padding_bytes(nbPaddingByteTotal: number) {
#_write_padding_bytes(nbPaddingByteTotal: number) {
const nbPaddingByte = nbPaddingByteTotal % 256;

@@ -299,17 +323,17 @@ const extraNbPaddingByte = Math.floor(nbPaddingByteTotal / 256);

// write the padding byte
this.chunk!.writeUInt8(nbPaddingByte, this.cursor + this.dataOffset);
this.cursor += 1;
this.#chunk!.writeUInt8(nbPaddingByte, this.#cursor + this.#dataOffset);
this.#cursor += 1;
for (let i = 0; i < nbPaddingByteTotal; i++) {
this.chunk!.writeUInt8(nbPaddingByte, this.cursor + this.dataOffset + i);
this.#chunk!.writeUInt8(nbPaddingByte, this.#cursor + this.#dataOffset + i);
}
this.cursor += nbPaddingByteTotal;
this.#cursor += nbPaddingByteTotal;
if (this.plainBlockSize > 256) {
this.chunk!.writeUInt8(extraNbPaddingByte, this.cursor + this.dataOffset);
this.cursor += 1;
this.#chunk!.writeUInt8(extraNbPaddingByte, this.#cursor + this.#dataOffset);
this.#cursor += 1;
}
}
private _post_process_current_chunk() {
#_post_process_current_chunk() {
let extraEncryptionBytes = 0;

@@ -324,3 +348,3 @@ // add padding bytes if needed

// +---------------+---------------+-------------+---------+--------------+------------+
let curLength = this.sequenceHeaderSize + this.cursor + this.signatureLength;
let curLength = this.sequenceHeaderSize + this.#cursor + this.signatureLength;
if (this.plainBlockSize > 256) {

@@ -335,4 +359,4 @@ curLength += 2; // account for extraPadding Byte Number;

this._write_padding_bytes(nbPaddingByteTotal);
const adjustedLength = this.sequenceHeaderSize + this.cursor + this.signatureLength;
this.#_write_padding_bytes(nbPaddingByteTotal);
const adjustedLength = this.sequenceHeaderSize + this.#cursor + this.signatureLength;

@@ -344,8 +368,8 @@ assert(adjustedLength % this.plainBlockSize === 0);

this.dataEnd = this.dataOffset + this.cursor;
this.#dataEnd = this.#dataOffset + this.#cursor;
// calculate the expected length of the chunk, once encrypted if encryption apply
const expectedLength = this.dataEnd + this.signatureLength + extraEncryptionBytes;
const expectedLength = this.#dataEnd + this.signatureLength + extraEncryptionBytes;
this.pendingChunk = this.chunk!.subarray(0, expectedLength);
this.#pendingChunk = this.#chunk!.subarray(0, expectedLength);
// note :

@@ -355,5 +379,5 @@ // - this.pending_chunk has the correct size but is not signed nor encrypted yet

// - as a result,
this.chunk = null;
this.cursor = 0;
this.#chunk = null;
this.#cursor = 0;
}
}

@@ -8,10 +8,8 @@ /***

export function readMessageHeader(stream: BinaryStream): MessageHeader {
const msgType =
String.fromCharCode(stream.readUInt8()) + String.fromCharCode(stream.readUInt8()) + String.fromCharCode(stream.readUInt8());
const msgType = String.fromCharCode(stream.readUInt8()) +
String.fromCharCode(stream.readUInt8()) +
String.fromCharCode(stream.readUInt8());
const isFinal = String.fromCharCode(stream.readUInt8());
const length = stream.readUInt32();
return {msgType, isFinal, length};
return { msgType, isFinal, length };
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc