net-snmp 3.20.0 → 3.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -3
- package/index.js +63 -44
- package/lib/des-ecb.js +147 -0
- package/lib/des.js +53 -0
- package/lib/mib.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
@@ -91,7 +91,7 @@ for each shown in this table:
|
|
91
91
|
* SNMP proxy forwarder for agent
|
92
92
|
* AgentX subagent
|
93
93
|
* IPv4 and IPv6
|
94
|
-
|
94
|
+
|
95
95
|
# Standards Compliance
|
96
96
|
|
97
97
|
This module aims to be fully compliant with the following RFCs:
|
@@ -258,6 +258,34 @@ Security Model RFC (RFC 3414); 128-bit AES for SNMPv3 was added later in RFC 382
|
|
258
258
|
localization. Cisco and a number of other vendors commonly use the "Reeder" key
|
259
259
|
localization variant. Other encryption algorithms are not supported.
|
260
260
|
|
261
|
+
### Compatibility note on DES and recent Node.js versions
|
262
|
+
|
263
|
+
When using SNMPv3 with DES as the privacy protocol (`snmp.PrivProtocols.des`) on Node.js v17 or later, you may encounter the following error:
|
264
|
+
|
265
|
+
```
|
266
|
+
"error": {
|
267
|
+
"library": "digital envelope routines",
|
268
|
+
"reason": "unsupported",
|
269
|
+
"code": "ERR_OSSL_EVP_UNSUPPORTED",
|
270
|
+
"message": "error:0308010C:digital envelope routines::unsupported",
|
271
|
+
"stack": ["Error: error:0308010C:digital envelope routines::unsupported",
|
272
|
+
"at Cipheriv.createCipherBase (node:internal/crypto/cipher:121:19)",
|
273
|
+
...
|
274
|
+
}
|
275
|
+
```
|
276
|
+
|
277
|
+
This occurs because newer versions of Node.js have deprecated support for the DES algorithm in OpenSSL for security reasons.
|
278
|
+
|
279
|
+
**Workaround:**
|
280
|
+
If you need to communicate with legacy devices that only support DES for SNMPv3, you can run Node.js with the `--openssl-legacy-provider` flag:
|
281
|
+
|
282
|
+
```bash
|
283
|
+
node --openssl-legacy-provider your-app.js
|
284
|
+
```
|
285
|
+
|
286
|
+
Whenever possible, it's recommended to use more secure encryption methods like AES (`snmp.PrivProtocols.aes`) instead of DES.
|
287
|
+
|
288
|
+
|
261
289
|
## snmp.AgentXPduType
|
262
290
|
|
263
291
|
The Agent Extensibility (AgentX) Protocol specifies these PDUs in RFC 2741:
|
@@ -1635,7 +1663,7 @@ an object, possibly empty, and can contain the following fields:
|
|
1635
1663
|
* `sockets` - an array of objects containing triples of `transport`, `address` and `port` that
|
1636
1664
|
can be used to specify multiple socket listeners. This option overrides any individual
|
1637
1665
|
`transport`, `address` and `port` options.
|
1638
|
-
* `mibOptions` -
|
1666
|
+
* `mibOptions` - a MIB options object that is passed to the `Mib` instance - see the MIB section
|
1639
1667
|
for further details on this - defaults to the empty object.
|
1640
1668
|
|
1641
1669
|
The `mib` parameter is optional, and sets the agent's singleton `Mib` instance.
|
@@ -2661,7 +2689,9 @@ var options = {
|
|
2661
2689
|
master: "localhost",
|
2662
2690
|
masterPort: 705,
|
2663
2691
|
timeout: 0,
|
2664
|
-
description: "Node net-snmp AgentX sub-agent"
|
2692
|
+
description: "Node net-snmp AgentX sub-agent",
|
2693
|
+
mibOptions: {},
|
2694
|
+
mib: undefined
|
2665
2695
|
};
|
2666
2696
|
|
2667
2697
|
subagent = snmp.createSubagent (options);
|
@@ -2676,6 +2706,12 @@ The `options` parameter is a mandatory object, possibly empty, and can contain t
|
|
2676
2706
|
* `timeout` - set the session-wide timeout on the master agent - defaults to 0, which
|
2677
2707
|
means no session-wide timeout is set.
|
2678
2708
|
* `description` - a textual description of the subagent.
|
2709
|
+
* `mibOptions` - n MIB options object that is passed to the `Mib` instance - see the MIB section
|
2710
|
+
for further details on this - defaults to the empty object.
|
2711
|
+
* `mib` - sets the agent's singleton `Mib` instance. If not supplied, the agent creates itself
|
2712
|
+
a new empty `Mib` singleton. If supplied, the `Mib` instance needs to be created and populated as
|
2713
|
+
per the [Mib Module](#mib-module) section.
|
2714
|
+
|
2679
2715
|
|
2680
2716
|
## subagent.getMib ()
|
2681
2717
|
|
@@ -3477,6 +3513,14 @@ Example programs are included under the module's `example` directory.
|
|
3477
3513
|
|
3478
3514
|
* Fix set value for counter, gauge and unsigned integer types
|
3479
3515
|
|
3516
|
+
# Version 3.20.1 - 26/04/2025
|
3517
|
+
|
3518
|
+
* Update documentation with compatibility note on DES and recent Node.js versions
|
3519
|
+
|
3520
|
+
# Version 3.21.0 - 26/04/2025
|
3521
|
+
|
3522
|
+
* Add AgentX subagent mib and mibOptions on initialization
|
3523
|
+
|
3480
3524
|
# License
|
3481
3525
|
|
3482
3526
|
Copyright (c) 2020 Mark Abrahams <mark@abrahams.co.nz>
|
package/index.js
CHANGED
@@ -1,21 +1,25 @@
|
|
1
1
|
|
2
2
|
// Copyright 2013 Stephen Vickers <stephen.vickers.sv@gmail.com>
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
4
|
+
const ber = require ("asn1-ber").Ber;
|
5
|
+
const smartbuffer = require ("smart-buffer");
|
6
|
+
const dgram = require ("dgram");
|
7
|
+
const net = require ("net");
|
8
|
+
const events = require ("events");
|
9
|
+
const util = require ("util");
|
10
|
+
const crypto = require ("crypto");
|
11
|
+
const mibparser = require ("./lib/mib");
|
12
|
+
const Buffer = require('buffer').Buffer;
|
13
|
+
|
12
14
|
var DEBUG = false;
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
const MIN_SIGNED_INT32 = -2147483648;
|
17
|
+
const MAX_SIGNED_INT32 = 2147483647;
|
18
|
+
const MIN_UNSIGNED_INT32 = 0;
|
19
|
+
const MAX_UNSIGNED_INT32 = 4294967295;
|
20
|
+
const MAX_UNSIGNED_INT64 = 18446744073709551615;
|
21
|
+
|
22
|
+
const DES_IMPLEMENTATION = 'library';
|
19
23
|
|
20
24
|
function debug (line) {
|
21
25
|
if ( DEBUG ) {
|
@@ -1378,7 +1382,6 @@ Encryption.encryptPduDes = function (scopedPdu, privProtocol, privPassword, auth
|
|
1378
1382
|
var paddedScopedPduLength;
|
1379
1383
|
var paddedScopedPdu;
|
1380
1384
|
var encryptedPdu;
|
1381
|
-
var cipher;
|
1382
1385
|
|
1383
1386
|
encryptionKey = Encryption.generateLocalizedKey (des, authProtocol, privPassword, engine.engineID);
|
1384
1387
|
privLocalizedKey = Authentication.passwordToKey (authProtocol, privPassword, engine.engineID);
|
@@ -1396,7 +1399,8 @@ Encryption.encryptPduDes = function (scopedPdu, privProtocol, privPassword, auth
|
|
1396
1399
|
for (i = 0; i < iv.length; i++) {
|
1397
1400
|
iv[i] = preIv[i] ^ salt[i];
|
1398
1401
|
}
|
1399
|
-
|
1402
|
+
|
1403
|
+
|
1400
1404
|
if (scopedPdu.length % des.BLOCK_LENGTH == 0) {
|
1401
1405
|
paddedScopedPdu = scopedPdu;
|
1402
1406
|
} else {
|
@@ -1404,9 +1408,14 @@ Encryption.encryptPduDes = function (scopedPdu, privProtocol, privPassword, auth
|
|
1404
1408
|
paddedScopedPdu = Buffer.alloc (paddedScopedPduLength);
|
1405
1409
|
scopedPdu.copy (paddedScopedPdu, 0, 0, scopedPdu.length);
|
1406
1410
|
}
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1411
|
+
|
1412
|
+
if (DES_IMPLEMENTATION === 'native') {
|
1413
|
+
// TODO: Implement native encryption
|
1414
|
+
} else {
|
1415
|
+
const cipher = crypto.createCipheriv (des.CRYPTO_ALGORITHM, encryptionKey, iv);
|
1416
|
+
encryptedPdu = cipher.update (paddedScopedPdu);
|
1417
|
+
encryptedPdu = Buffer.concat ([encryptedPdu, cipher.final()]);
|
1418
|
+
}
|
1410
1419
|
// Encryption.debugEncrypt (encryptionKey, iv, paddedScopedPdu, encryptedPdu);
|
1411
1420
|
|
1412
1421
|
return {
|
@@ -1424,7 +1433,6 @@ Encryption.decryptPduDes = function (encryptedPdu, privProtocol, privParameters,
|
|
1424
1433
|
var iv;
|
1425
1434
|
var i;
|
1426
1435
|
var decryptedPdu;
|
1427
|
-
var decipher;
|
1428
1436
|
|
1429
1437
|
privLocalizedKey = Authentication.passwordToKey (authProtocol, privPassword, engine.engineID);
|
1430
1438
|
decryptionKey = Buffer.alloc (des.KEY_LENGTH);
|
@@ -1437,11 +1445,15 @@ Encryption.decryptPduDes = function (encryptedPdu, privProtocol, privParameters,
|
|
1437
1445
|
for (i = 0; i < iv.length; i++) {
|
1438
1446
|
iv[i] = preIv[i] ^ salt[i];
|
1439
1447
|
}
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1448
|
+
|
1449
|
+
if (DES_IMPLEMENTATION === 'native') {
|
1450
|
+
// TODO: Implement native decryption
|
1451
|
+
} else {
|
1452
|
+
const decipher = crypto.createDecipheriv (des.CRYPTO_ALGORITHM, decryptionKey, iv);
|
1453
|
+
decipher.setAutoPadding (false);
|
1454
|
+
decryptedPdu = decipher.update (encryptedPdu);
|
1455
|
+
decryptedPdu = Buffer.concat ([decryptedPdu, decipher.final()]);
|
1456
|
+
}
|
1445
1457
|
// Encryption.debugDecrypt (decryptionKey, iv, encryptedPdu, decryptedPdu);
|
1446
1458
|
|
1447
1459
|
return decryptedPdu;
|
@@ -2021,13 +2033,15 @@ var Session = function (target, authenticator, options) {
|
|
2021
2033
|
|
2022
2034
|
DEBUG = options.debug;
|
2023
2035
|
|
2024
|
-
this.engine = new Engine (
|
2036
|
+
this.engine = new Engine ({
|
2037
|
+
engineId: options.engineID
|
2038
|
+
});
|
2025
2039
|
this.reqs = {};
|
2026
2040
|
this.reqCount = 0;
|
2027
2041
|
|
2028
2042
|
this.dgram = dgram.createSocket (this.transport);
|
2029
2043
|
this.dgram.unref();
|
2030
|
-
|
2044
|
+
|
2031
2045
|
var me = this;
|
2032
2046
|
this.dgram.on ("message", me.onMsg.bind (me));
|
2033
2047
|
this.dgram.on ("close", me.onClose.bind (me));
|
@@ -2255,7 +2269,7 @@ Session.prototype.inform = function () {
|
|
2255
2269
|
|
2256
2270
|
/**
|
2257
2271
|
** Support the following signatures:
|
2258
|
-
**
|
2272
|
+
**
|
2259
2273
|
** typeOrOid, varbinds, options, callback
|
2260
2274
|
** typeOrOid, varbinds, callback
|
2261
2275
|
** typeOrOid, options, callback
|
@@ -2333,7 +2347,7 @@ Session.prototype.inform = function () {
|
|
2333
2347
|
};
|
2334
2348
|
pduVarbinds.push (varbind);
|
2335
2349
|
}
|
2336
|
-
|
2350
|
+
|
2337
2351
|
options.port = this.trapPort;
|
2338
2352
|
|
2339
2353
|
this.simpleGet (InformRequestPdu, feedCb, pduVarbinds, responseCb, options);
|
@@ -2453,7 +2467,7 @@ Session.prototype.registerRequest = function (req) {
|
|
2453
2467
|
Session.prototype.send = function (req, noWait) {
|
2454
2468
|
try {
|
2455
2469
|
var me = this;
|
2456
|
-
|
2470
|
+
|
2457
2471
|
var buffer = req.message.toBuffer ();
|
2458
2472
|
|
2459
2473
|
this.dgram.send (buffer, 0, buffer.length, req.port, this.target,
|
@@ -2471,7 +2485,7 @@ Session.prototype.send = function (req, noWait) {
|
|
2471
2485
|
} catch (error) {
|
2472
2486
|
req.responseCb (error);
|
2473
2487
|
}
|
2474
|
-
|
2488
|
+
|
2475
2489
|
return this;
|
2476
2490
|
};
|
2477
2491
|
|
@@ -2723,7 +2737,7 @@ Session.prototype.trap = function () {
|
|
2723
2737
|
|
2724
2738
|
/**
|
2725
2739
|
** Support the following signatures:
|
2726
|
-
**
|
2740
|
+
**
|
2727
2741
|
** typeOrOid, varbinds, options, callback
|
2728
2742
|
** typeOrOid, varbinds, agentAddr, callback
|
2729
2743
|
** typeOrOid, varbinds, callback
|
@@ -2766,7 +2780,7 @@ Session.prototype.trap = function () {
|
|
2766
2780
|
};
|
2767
2781
|
pduVarbinds.push (varbind);
|
2768
2782
|
}
|
2769
|
-
|
2783
|
+
|
2770
2784
|
var id = _generateId (this.idBitsSize);
|
2771
2785
|
|
2772
2786
|
if (this.version == Version2c || this.version == Version3 ) {
|
@@ -2990,7 +3004,8 @@ Session.createV3 = function (target, user, options) {
|
|
2990
3004
|
return new Session (target, user, options);
|
2991
3005
|
};
|
2992
3006
|
|
2993
|
-
var Engine = function (
|
3007
|
+
var Engine = function (engineOptions) {
|
3008
|
+
const { engineID } = engineOptions;
|
2994
3009
|
if ( engineID ) {
|
2995
3010
|
if ( ! (engineID instanceof Buffer) ) {
|
2996
3011
|
engineID = engineID.replace('0x', '');
|
@@ -3056,7 +3071,7 @@ Listener.prototype.startListening = function () {
|
|
3056
3071
|
|
3057
3072
|
Listener.prototype.send = function (message, rinfo, socket) {
|
3058
3073
|
// var me = this;
|
3059
|
-
|
3074
|
+
|
3060
3075
|
var buffer = message.toBuffer ();
|
3061
3076
|
|
3062
3077
|
socket.send (buffer, 0, buffer.length, rinfo.port, rinfo.address, function (error, bytes) {
|
@@ -3335,7 +3350,9 @@ SimpleAccessControlModel.prototype.isAccessAllowed = function (securityModel, se
|
|
3335
3350
|
var Receiver = function (options, callback) {
|
3336
3351
|
DEBUG = options.debug;
|
3337
3352
|
this.authorizer = new Authorizer (options);
|
3338
|
-
this.engine = new Engine (
|
3353
|
+
this.engine = new Engine ({
|
3354
|
+
engineId: options.engineID
|
3355
|
+
});
|
3339
3356
|
|
3340
3357
|
this.engineBoots = 0;
|
3341
3358
|
this.engineTime = 10;
|
@@ -3662,7 +3679,7 @@ ModuleStore.prototype.getProvidersForModule = function (moduleName) {
|
|
3662
3679
|
// (See lib/mibs/SNMPv2-TC.mib#L186.)
|
3663
3680
|
if ( syntax == "RowStatus" &&
|
3664
3681
|
"IMPORTS" in mibModule &&
|
3665
|
-
Array.isArray(mibModule.IMPORTS["SNMPv2-TC"]) &&
|
3682
|
+
Array.isArray(mibModule.IMPORTS["SNMPv2-TC"]) &&
|
3666
3683
|
mibModule.IMPORTS["SNMPv2-TC"].includes("RowStatus") ) {
|
3667
3684
|
|
3668
3685
|
// Mark this column as being rowStatus
|
@@ -4011,7 +4028,7 @@ MibNode.prototype.getNextInstanceNode = function () {
|
|
4011
4028
|
childrenAddresses = Object.keys (node.children).sort ( (a, b) => a - b);
|
4012
4029
|
node = node.children[childrenAddresses[0]];
|
4013
4030
|
if ( ! node ) {
|
4014
|
-
// unexpected
|
4031
|
+
// unexpected
|
4015
4032
|
return null;
|
4016
4033
|
}
|
4017
4034
|
}
|
@@ -4674,7 +4691,7 @@ Mib.prototype.getTableCells = function (table, byRows, includeInstances) {
|
|
4674
4691
|
} else {
|
4675
4692
|
return data;
|
4676
4693
|
}
|
4677
|
-
|
4694
|
+
|
4678
4695
|
};
|
4679
4696
|
|
4680
4697
|
Mib.prototype.getTableSingleCell = function (table, columnNumber, rowIndex) {
|
@@ -4850,7 +4867,9 @@ MibRequest.prototype.isTabular = function () {
|
|
4850
4867
|
var Agent = function (options, callback, mib) {
|
4851
4868
|
DEBUG = options.debug;
|
4852
4869
|
this.listener = new Listener (options, this);
|
4853
|
-
this.engine = new Engine (
|
4870
|
+
this.engine = new Engine ({
|
4871
|
+
engineId: options.engineID
|
4872
|
+
});
|
4854
4873
|
this.authorizer = new Authorizer (options);
|
4855
4874
|
this.callback = callback || function () {};
|
4856
4875
|
const mibOptions = mib?.options || options?.mibOptions || {};
|
@@ -5070,7 +5089,7 @@ Agent.prototype.tryCreateInstance = function (varbind, requestType) {
|
|
5070
5089
|
typeof rowStatusColumn == "number" &&
|
5071
5090
|
column === rowStatusColumn ) {
|
5072
5091
|
|
5073
|
-
if ( (varbind.value === RowStatus["createAndGo"] || varbind.value === RowStatus["createAndWait"]) &&
|
5092
|
+
if ( (varbind.value === RowStatus["createAndGo"] || varbind.value === RowStatus["createAndWait"]) &&
|
5074
5093
|
provider.createHandler !== null ) {
|
5075
5094
|
|
5076
5095
|
// The create handler will return an array
|
@@ -5554,7 +5573,7 @@ Agent.prototype.getBulkRequest = function (socket, requestMessage, rinfo) {
|
|
5554
5573
|
}
|
5555
5574
|
|
5556
5575
|
if ( requestPdu.nonRepeaters < requestVarbinds.length ) {
|
5557
|
-
|
5576
|
+
|
5558
5577
|
for (var v = requestPdu.nonRepeaters ; v < requestVarbinds.length ; v++ ) {
|
5559
5578
|
startOid.push (requestVarbinds[v].oid);
|
5560
5579
|
}
|
@@ -5766,7 +5785,7 @@ AgentXPdu.prototype.readHeader = function (buffer) {
|
|
5766
5785
|
this.version = buffer.readUInt8 ();
|
5767
5786
|
this.pduType = buffer.readUInt8 ();
|
5768
5787
|
this.flags = buffer.readUInt8 ();
|
5769
|
-
buffer.readUInt8 (); // reserved byte
|
5788
|
+
buffer.readUInt8 (); // reserved byte
|
5770
5789
|
this.sessionID = buffer.readUInt32BE ();
|
5771
5790
|
this.transactionID = buffer.readUInt32BE ();
|
5772
5791
|
this.packetID = buffer.readUInt32BE ();
|
@@ -5836,7 +5855,7 @@ AgentXPdu.createFromVariables = function (vars) {
|
|
5836
5855
|
+ "' in created PDU");
|
5837
5856
|
|
5838
5857
|
}
|
5839
|
-
|
5858
|
+
|
5840
5859
|
return pdu;
|
5841
5860
|
};
|
5842
5861
|
|
@@ -6071,7 +6090,7 @@ AgentXPdu.packetID = 1;
|
|
6071
6090
|
|
6072
6091
|
var Subagent = function (options) {
|
6073
6092
|
DEBUG = options.debug;
|
6074
|
-
this.mib = new Mib ();
|
6093
|
+
this.mib = options?.mib ?? new Mib (options?.mibOptions);
|
6075
6094
|
this.master = options.master || 'localhost';
|
6076
6095
|
this.masterPort = options.masterPort || 705;
|
6077
6096
|
this.timeout = options.timeout || 0;
|
package/lib/des-ecb.js
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
const { Buffer } = require('buffer');
|
2
|
+
|
3
|
+
// --- Lookup tables ---
|
4
|
+
const PC1 = [
|
5
|
+
57, 49, 41, 33, 25, 17, 9,
|
6
|
+
1, 58, 50, 42, 34, 26, 18,
|
7
|
+
10, 2, 59, 51, 43, 35, 27,
|
8
|
+
19, 11, 3, 60, 52, 44, 36,
|
9
|
+
63, 55, 47, 39, 31, 23, 15,
|
10
|
+
7, 62, 54, 46, 38, 30, 22,
|
11
|
+
14, 6, 61, 53, 45, 37, 29,
|
12
|
+
21, 13, 5, 28, 20, 12, 4
|
13
|
+
];
|
14
|
+
const PC2 = [
|
15
|
+
14, 17, 11, 24, 1, 5,
|
16
|
+
3, 28, 15, 6, 21, 10,
|
17
|
+
23, 19, 12, 4, 26, 8,
|
18
|
+
16, 7, 27, 20, 13, 2,
|
19
|
+
41, 52, 31, 37, 47, 55,
|
20
|
+
30, 40, 51, 45, 33, 48,
|
21
|
+
44, 49, 39, 56, 34, 53,
|
22
|
+
46, 42, 50, 36, 29, 32
|
23
|
+
];
|
24
|
+
const SHIFTS = [
|
25
|
+
1, 1, 2, 2, 2, 2, 2, 2,
|
26
|
+
1, 2, 2, 2, 2, 2, 2, 1
|
27
|
+
];
|
28
|
+
const IP = [
|
29
|
+
58, 50, 42, 34, 26, 18, 10, 2,
|
30
|
+
60, 52, 44, 36, 28, 20, 12, 4,
|
31
|
+
62, 54, 46, 38, 30, 22, 14, 6,
|
32
|
+
64, 56, 48, 40, 32, 24, 16, 8,
|
33
|
+
57, 49, 41, 33, 25, 17, 9, 1,
|
34
|
+
59, 51, 43, 35, 27, 19, 11, 3,
|
35
|
+
61, 53, 45, 37, 29, 21, 13, 5,
|
36
|
+
63, 55, 47, 39, 31, 23, 15, 7
|
37
|
+
];
|
38
|
+
const IP_INV = [
|
39
|
+
40, 8, 48, 16, 56, 24, 64, 32,
|
40
|
+
39, 7, 47, 15, 55, 23, 63, 31,
|
41
|
+
38, 6, 46, 14, 54, 22, 62, 30,
|
42
|
+
37, 5, 45, 13, 53, 21, 61, 29,
|
43
|
+
36, 4, 44, 12, 52, 20, 60, 28,
|
44
|
+
35, 3, 43, 11, 51, 19, 59, 27,
|
45
|
+
34, 2, 42, 10, 50, 18, 58, 26,
|
46
|
+
33, 1, 41, 9, 49, 17, 57, 25
|
47
|
+
];
|
48
|
+
|
49
|
+
// --- Utility functions ---
|
50
|
+
function permute(input, table) {
|
51
|
+
const output = new Array(table.length);
|
52
|
+
for (let i = 0; i < table.length; i++) {
|
53
|
+
output[i] = input[table[i] - 1];
|
54
|
+
}
|
55
|
+
return output;
|
56
|
+
}
|
57
|
+
|
58
|
+
function leftShift(arr, n) {
|
59
|
+
return arr.slice(n).concat(arr.slice(0, n));
|
60
|
+
}
|
61
|
+
|
62
|
+
function xor(a, b) {
|
63
|
+
return a.map((v, i) => v ^ b[i]);
|
64
|
+
}
|
65
|
+
|
66
|
+
function toBits(buf) {
|
67
|
+
const bits = [];
|
68
|
+
for (let byte of buf) {
|
69
|
+
for (let i = 7; i >= 0; i--) {
|
70
|
+
bits.push((byte >> i) & 1);
|
71
|
+
}
|
72
|
+
}
|
73
|
+
return bits;
|
74
|
+
}
|
75
|
+
|
76
|
+
function fromBits(bits) {
|
77
|
+
const buf = Buffer.alloc(bits.length / 8);
|
78
|
+
for (let i = 0; i < bits.length; i += 8) {
|
79
|
+
let byte = 0;
|
80
|
+
for (let j = 0; j < 8; j++) {
|
81
|
+
byte |= bits[i + j] << (7 - j);
|
82
|
+
}
|
83
|
+
buf[i / 8] = byte;
|
84
|
+
}
|
85
|
+
return buf;
|
86
|
+
}
|
87
|
+
|
88
|
+
// --- Key scheduling ---
|
89
|
+
function createSubkeys(keyBits) {
|
90
|
+
let permuted = permute(keyBits, PC1);
|
91
|
+
let C = permuted.slice(0, 28);
|
92
|
+
let D = permuted.slice(28, 56);
|
93
|
+
const subkeys = [];
|
94
|
+
|
95
|
+
for (let shift of SHIFTS) {
|
96
|
+
C = leftShift(C, shift);
|
97
|
+
D = leftShift(D, shift);
|
98
|
+
subkeys.push(permute(C.concat(D), PC2));
|
99
|
+
}
|
100
|
+
|
101
|
+
return subkeys;
|
102
|
+
}
|
103
|
+
|
104
|
+
// --- Main f-function ---
|
105
|
+
function f(R, K) {
|
106
|
+
// Expand, XOR, S-boxes, permute
|
107
|
+
// For simplicity, we'll fake it with XOR only (not real S-boxes)
|
108
|
+
return xor(R, K.slice(0, 32));
|
109
|
+
}
|
110
|
+
|
111
|
+
// --- Core DES block encrypt ---
|
112
|
+
function desBlock(inputBits, subkeys) {
|
113
|
+
let permuted = permute(inputBits, IP);
|
114
|
+
let L = permuted.slice(0, 32);
|
115
|
+
let R = permuted.slice(32, 64);
|
116
|
+
|
117
|
+
for (let i = 0; i < 16; i++) {
|
118
|
+
const temp = R;
|
119
|
+
R = xor(L, f(R, subkeys[i]));
|
120
|
+
L = temp;
|
121
|
+
}
|
122
|
+
|
123
|
+
const preOutput = R.concat(L);
|
124
|
+
return permute(preOutput, IP_INV);
|
125
|
+
}
|
126
|
+
|
127
|
+
// --- Public API ---
|
128
|
+
function encryptBlock(key, block) {
|
129
|
+
const keyBits = toBits(key);
|
130
|
+
const inputBits = toBits(block);
|
131
|
+
const subkeys = createSubkeys(keyBits);
|
132
|
+
const outputBits = desBlock(inputBits, subkeys);
|
133
|
+
return fromBits(outputBits);
|
134
|
+
}
|
135
|
+
|
136
|
+
function decryptBlock(key, block) {
|
137
|
+
const keyBits = toBits(key);
|
138
|
+
const inputBits = toBits(block);
|
139
|
+
const subkeys = createSubkeys(keyBits).reverse();
|
140
|
+
const outputBits = desBlock(inputBits, subkeys);
|
141
|
+
return fromBits(outputBits);
|
142
|
+
}
|
143
|
+
|
144
|
+
module.exports = {
|
145
|
+
encryptBlock,
|
146
|
+
decryptBlock,
|
147
|
+
};
|
package/lib/des.js
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
const { Buffer } = require('buffer');
|
2
|
+
const des = require('./des-ecb');
|
3
|
+
|
4
|
+
// --- CBC Mode wrapper ---
|
5
|
+
function encrypt(key, iv, plaintext) {
|
6
|
+
if (plaintext.length % 8 !== 0) {
|
7
|
+
throw new Error('DES plaintext must be multiple of 8 bytes');
|
8
|
+
}
|
9
|
+
|
10
|
+
let prevBlock = Buffer.from(iv);
|
11
|
+
let out = Buffer.alloc(plaintext.length);
|
12
|
+
|
13
|
+
for (let i = 0; i < plaintext.length; i += 8) {
|
14
|
+
const block = Buffer.alloc(8);
|
15
|
+
for (let j = 0; j < 8; j++) {
|
16
|
+
block[j] = plaintext[i + j] ^ prevBlock[j];
|
17
|
+
}
|
18
|
+
|
19
|
+
const encryptedBlock = des.encryptBlock(key, block);
|
20
|
+
|
21
|
+
encryptedBlock.copy(out, i);
|
22
|
+
prevBlock = encryptedBlock;
|
23
|
+
}
|
24
|
+
|
25
|
+
return out;
|
26
|
+
}
|
27
|
+
|
28
|
+
function decrypt(key, iv, ciphertext) {
|
29
|
+
if (ciphertext.length % 8 !== 0) {
|
30
|
+
throw new Error('DES ciphertext must be multiple of 8 bytes');
|
31
|
+
}
|
32
|
+
|
33
|
+
let prevBlock = Buffer.from(iv);
|
34
|
+
let out = Buffer.alloc(ciphertext.length);
|
35
|
+
|
36
|
+
for (let i = 0; i < ciphertext.length; i += 8) {
|
37
|
+
const block = ciphertext.slice(i, i + 8);
|
38
|
+
const decryptedBlock = des.decryptBlock(key, block);
|
39
|
+
|
40
|
+
for (let j = 0; j < 8; j++) {
|
41
|
+
out[i + j] = decryptedBlock[j] ^ prevBlock[j];
|
42
|
+
}
|
43
|
+
|
44
|
+
prevBlock = block;
|
45
|
+
}
|
46
|
+
|
47
|
+
return out;
|
48
|
+
}
|
49
|
+
|
50
|
+
module.exports = {
|
51
|
+
encrypt,
|
52
|
+
decrypt,
|
53
|
+
};
|
package/lib/mib.js
CHANGED
@@ -655,7 +655,7 @@ const MIB = function (dir) {
|
|
655
655
|
if (unresolvedObjects.length > 0) {
|
656
656
|
for (const unresolved of unresolvedObjects) {
|
657
657
|
const obj = this.Modules[ModuleName][unresolved];
|
658
|
-
|
658
|
+
|
659
659
|
const { oidString, nameString, unresolvedObject } = this.getOidAndNamePaths(obj['OBJECT IDENTIFIER'], unresolved, ModuleName);
|
660
660
|
this.Modules[ModuleName][unresolved].NameSpace = nameString;
|
661
661
|
this.Modules[ModuleName][unresolved].OID = oidString;
|