mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-20 06:55:08 -04:00
Merge pull request #2 from ConfiguredThings/libhydrogen-support
Libhydrogen support
This commit is contained in:
commit
fe4a5fbd46
8 changed files with 432 additions and 10 deletions
11
package-lock.json
generated
11
package-lock.json
generated
|
@ -13,6 +13,7 @@
|
|||
"@astronautlabs/amf": "^0.0.6",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@blu3r4y/lzma": "^2.3.3",
|
||||
"@configuredthings/libhydrogen-wasm": "0.1.0",
|
||||
"@wavesenterprise/crypto-gost-js": "^2.1.0-RC1",
|
||||
"@xmldom/xmldom": "^0.8.10",
|
||||
"argon2-browser": "^1.18.0",
|
||||
|
@ -2069,6 +2070,16 @@
|
|||
"node": ">=0.1.90"
|
||||
}
|
||||
},
|
||||
"node_modules/@configuredthings/libhydrogen-wasm": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://npm.pkg.github.com/download/@configuredthings/libhydrogen-wasm/0.1.0/09ea0d48f4acd9294909fa95028379bf02a81629",
|
||||
"integrity": "sha512-kk32qNPHc5RRn35DLi/MpiNDBJZzj4NNzxpcP4LYFQGxWxqMbMSTmQWK7IMsMAA54alzDV31CbtNGDHjkjiKmQ==",
|
||||
"license": "UNLICENSED",
|
||||
"engines": {
|
||||
"node": ">=20.10.0",
|
||||
"npm": ">=10.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@discoveryjs/json-ext": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
|
||||
|
|
|
@ -97,6 +97,7 @@
|
|||
"@astronautlabs/amf": "^0.0.6",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@blu3r4y/lzma": "^2.3.3",
|
||||
"@configuredthings/libhydrogen-wasm": "0.1.0",
|
||||
"@wavesenterprise/crypto-gost-js": "^2.1.0-RC1",
|
||||
"@xmldom/xmldom": "^0.8.10",
|
||||
"argon2-browser": "^1.18.0",
|
||||
|
|
|
@ -157,7 +157,8 @@
|
|||
"Typex",
|
||||
"Lorenz",
|
||||
"Colossus",
|
||||
"SIGABA"
|
||||
"SIGABA",
|
||||
"LibHydrogen Curve25519 Sign"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
46
src/core/operations/JSONToArrayBuffer.mjs
Normal file
46
src/core/operations/JSONToArrayBuffer.mjs
Normal file
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* @file Developed by {@link https://configuredthings.com Configured Things} with funding from the {@link https://www.ukri.org UKRI}
|
||||
* {@link https://www.dsbd.tech Digital Security by Design} program.
|
||||
* @author Configured Things Ltd. <getconfigured@configuredthings.com>
|
||||
* @copyright Crown Copyright 2025
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
|
||||
/**
|
||||
* JSON to ArrayBuffer operation
|
||||
*/
|
||||
class JSONToArrayBuffer extends Operation {
|
||||
|
||||
/**
|
||||
* JSONToArrayBuffer constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "JSON to ArrayBuffer";
|
||||
this.module = "Default";
|
||||
this.description = "Serialises a JSON object to an ArrayBuffer";
|
||||
this.infoURL = ""; // Usually a Wikipedia link. Remember to remove localisation (i.e. https://wikipedia.org/etc rather than https://en.wikipedia.org/etc)
|
||||
this.inputType = "JSON";
|
||||
this.outputType = "ArrayBuffer";
|
||||
this.args = [
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {JSON} input
|
||||
* @param {Object[]} args
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
run(input, args) {
|
||||
const messageStr = JSON.stringify(input);
|
||||
const textEncoder = new TextEncoder();
|
||||
const messageAb = textEncoder.encode(messageStr).buffer;
|
||||
return messageAb;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default JSONToArrayBuffer;
|
303
src/core/operations/LibHydrogenCurve25519Sign.mjs
Normal file
303
src/core/operations/LibHydrogenCurve25519Sign.mjs
Normal file
|
@ -0,0 +1,303 @@
|
|||
/**
|
||||
* @file Developed by {@link https://configuredthings.com Configured Things} with funding from the {@link https://www.ukri.org UKRI}
|
||||
* {@link https://www.dsbd.tech Digital Security by Design} program.
|
||||
* @author Configured Things Ltd. <getconfigured@configuredthings.com>
|
||||
* @copyright Crown Copyright 2025
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
|
||||
import * as hydro from "@configuredthings/libhydrogen-wasm/libHydrogen.js";
|
||||
|
||||
/**
|
||||
* LibHydrogen Curve25519 Sign operation
|
||||
*/
|
||||
class LibHydrogenCurve25519Signing extends Operation {
|
||||
|
||||
/**
|
||||
* LibHydrogenCurve25519Sign constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "LibHydrogen Curve25519 Sign";
|
||||
this.module = "Crypto";
|
||||
this.description = "Computes a signature for a message using the lightweight LibHydrogen cryptography library";
|
||||
this.infoURL = "https://libhydrogen.org/";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "JSON";
|
||||
this.args = [
|
||||
{
|
||||
name: "Context",
|
||||
type: "string",
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
name: "Sender's private key",
|
||||
type: "byteArray",
|
||||
value: ""
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
/**
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {JSON}
|
||||
*/
|
||||
async run(input, args) {
|
||||
const [context, privateKey] = args;
|
||||
const wasmSrc = await fetch(new URL(`${self.docURL}/assets/libhydrogen-wasm/libhydrogen.wasm`));
|
||||
const wasm = await WebAssembly.compileStreaming(wasmSrc);
|
||||
const imports = {
|
||||
"wasi_snapshot_preview1": {
|
||||
args_get() {
|
||||
return 0;
|
||||
},
|
||||
args_sizes_get() {
|
||||
return 0;
|
||||
},
|
||||
clock_res_get() {
|
||||
return 0;
|
||||
},
|
||||
clock_time_get() {
|
||||
return 0;
|
||||
},
|
||||
environ_sizes_get() {
|
||||
return 0;
|
||||
},
|
||||
environ_get() {
|
||||
return 0;
|
||||
},
|
||||
proc_exit() {
|
||||
return 0;
|
||||
},
|
||||
fd_write() {
|
||||
return 0;
|
||||
},
|
||||
fd_advise() {
|
||||
return 0;
|
||||
},
|
||||
fd_allocate() {
|
||||
return 0;
|
||||
},
|
||||
fd_close() {
|
||||
return 0;
|
||||
},
|
||||
fd_datasync() {
|
||||
return 0;
|
||||
},
|
||||
fd_fdstat_get() {
|
||||
return 0;
|
||||
},
|
||||
fd_fdstat_set_flags() {
|
||||
return 0;
|
||||
},
|
||||
fd_fdstat_set_rights() {
|
||||
return 0;
|
||||
},
|
||||
fd_filestat_get() {
|
||||
return 0;
|
||||
},
|
||||
fd_filestat_set_size() {
|
||||
return 0;
|
||||
},
|
||||
fd_filestat_set_times() {
|
||||
return 0;
|
||||
},
|
||||
fd_pread() {
|
||||
return 0;
|
||||
},
|
||||
fd_prestat_get() {
|
||||
return 0;
|
||||
},
|
||||
fd_prestat_dir_name() {
|
||||
return 0;
|
||||
},
|
||||
fd_pwrite() {
|
||||
return 0;
|
||||
},
|
||||
fd_read() {
|
||||
return 0;
|
||||
},
|
||||
fd_readdir() {
|
||||
return 0;
|
||||
},
|
||||
fd_renumber() {
|
||||
return 0;
|
||||
},
|
||||
fd_seek() {
|
||||
return 0;
|
||||
},
|
||||
fd_sync() {
|
||||
return 0;
|
||||
},
|
||||
fd_tell() {
|
||||
return 0;
|
||||
},
|
||||
path_create_directory() {
|
||||
return 0;
|
||||
},
|
||||
path_filestat_get() {
|
||||
return 0;
|
||||
},
|
||||
path_filestat_set_times() {
|
||||
return 0;
|
||||
},
|
||||
path_link() {
|
||||
return 0;
|
||||
},
|
||||
path_open() {
|
||||
return 0;
|
||||
},
|
||||
path_readlink() {
|
||||
return 0;
|
||||
},
|
||||
path_remove_directory() {
|
||||
return 0;
|
||||
},
|
||||
path_rename() {
|
||||
return 0;
|
||||
},
|
||||
path_symlink() {
|
||||
return 0;
|
||||
},
|
||||
path_unlink_file() {
|
||||
return 0;
|
||||
},
|
||||
poll_oneoff() {
|
||||
return 0;
|
||||
},
|
||||
sched_yield() {
|
||||
return 0;
|
||||
},
|
||||
random_get(buf, buf_len) {
|
||||
const random_arr = new Uint8Array(dataview.buffer, buf, buf_len);
|
||||
crypto.getRandomValues(random_arr);
|
||||
return 0;
|
||||
},
|
||||
sock_accept() {
|
||||
return 0;
|
||||
},
|
||||
sock_recv() {
|
||||
return 0;
|
||||
},
|
||||
sock_send() {
|
||||
return 0;
|
||||
},
|
||||
sock_shutdown() {
|
||||
return 0;
|
||||
},
|
||||
}
|
||||
};
|
||||
instance = await WebAssembly.instantiate(wasm, imports);
|
||||
// Get the memory are used as a stack when calling into the WASI
|
||||
const memory = instance.exports.memory;
|
||||
// DataView takes care of our platform specific endian conversions
|
||||
dataview = new DataView(memory.buffer);
|
||||
// We must call a start method per WASI specification
|
||||
// Libhydrogen's main method is one we have patched to initialise it
|
||||
instance.exports._start();
|
||||
// Generated signature for JSON input
|
||||
return await sign(input, context, privateKey);
|
||||
}
|
||||
/* eslint-enable camelcase */
|
||||
|
||||
}
|
||||
|
||||
let instance, dataview;
|
||||
|
||||
/**
|
||||
* Helper function to reserve space in the buffer used
|
||||
* as a stack between js and the wasm.
|
||||
* @private
|
||||
* @param {Object} offset - Must be an an object so we can update it's value
|
||||
* @param {number} offset.value
|
||||
* @param {number} length
|
||||
* @returns {Uint8Array} Returns a UInt8Array representation of the buffer
|
||||
*
|
||||
* @example
|
||||
* // Designed to allow a sequence of reservations such as
|
||||
*
|
||||
* let offset = {value: 0};
|
||||
* buf1 = reserve (offset, 100);
|
||||
* buf2 = reserve (offset, 590);
|
||||
* ...
|
||||
*/
|
||||
function reserve(offset, length) {
|
||||
const a = new Uint8Array(dataview.buffer, offset.value, length);
|
||||
const newOffset = a.byteOffset + a.byteLength;
|
||||
offset.value = newOffset;
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* An object containing the signature, the ArrayBuffer used to generate the signature, and the signing operation's context
|
||||
* @typedef {Object} SignedObject
|
||||
* @property {Uint8Array} context - A buffer representing the context used to define the context of the signing operation,
|
||||
see {@link https://github.com/jedisct1/libhydrogen/wiki/Contexts}
|
||||
* @property {Uint8Array} input - A buffer representing the stringified JSON object used as the input to the signing operation
|
||||
* @property {Uint8Array} signature - A buffer representing the digital signature of the signed JSON object
|
||||
*/
|
||||
|
||||
/**
|
||||
* Digital signing of an ArrayBuffer's contents
|
||||
* @private
|
||||
* @param {ArrayBuffer} input - An ArrayBuffer to be signed
|
||||
* @param {string} context - A string used to define the context of the signing operation,
|
||||
* see {@link https://github.com/jedisct1/libhydrogen/wiki/Contexts}
|
||||
* @param {Uint8Array} privateKey - The private key to use for the digital signing operation
|
||||
* @returns {SignedObject} An object containing the signature, the ArrayBuffer used to generate the signature, and the signing operation's context
|
||||
*/
|
||||
async function sign(input, context, privateKey) {
|
||||
// Importing libhydrogen's signing keygen and signing and verification functions
|
||||
// eslint-disable-next-line camelcase
|
||||
const { hydro_sign_create } = instance.exports;
|
||||
const textEncoder = new TextEncoder();
|
||||
|
||||
// We have to create the stack frame to pass to libHydrogen
|
||||
// in the dataview Buffer, and then pass in pointers to
|
||||
// that buffer
|
||||
const offset = { value: 0 };
|
||||
const contextArr = reserve(offset, hydro.hash_CONTEXTBYTES);
|
||||
const contextAb = textEncoder.encode(context);
|
||||
|
||||
for (let i = 0; i < hydro.hash_CONTEXTBYTES; i++) {
|
||||
contextArr.set([contextAb.at(i)], i);
|
||||
}
|
||||
|
||||
const messageTypedArr = new Uint8Array(input);
|
||||
const messageArr = reserve(offset, messageTypedArr.length);
|
||||
|
||||
for (let i = 0; i < messageTypedArr.length; i++) {
|
||||
messageArr.set([messageTypedArr.at(i)], i);
|
||||
}
|
||||
|
||||
// Generate a key pair
|
||||
const privateKeyArr = reserve(offset, hydro.sign_SECRETKEYBYTES);
|
||||
for (let i = 0; i < privateKey.length; i++) {
|
||||
privateKeyArr.set([privateKey.at(i)], i);
|
||||
}
|
||||
|
||||
// Reserving memory for the signature
|
||||
const signature = reserve(offset, hydro.sign_BYTES);
|
||||
|
||||
// Creating signature of message with secret key
|
||||
hydro_sign_create(
|
||||
signature.byteOffset,
|
||||
messageArr.byteOffset,
|
||||
messageArr.byteLength,
|
||||
contextArr.byteOffset,
|
||||
privateKeyArr.byteOffset,
|
||||
);
|
||||
|
||||
return {
|
||||
context: contextArr,
|
||||
input: messageArr,
|
||||
signature
|
||||
};
|
||||
}
|
||||
|
||||
export default LibHydrogenCurve25519Signing;
|
|
@ -1,6 +1,8 @@
|
|||
/**
|
||||
* @author Configured Things Ltd. [getconfigured@configuredthings.com]
|
||||
* @copyright Crown Copyright 2024
|
||||
* @file Developed by {@link https://configuredthings.com Configured Things} with funding from the {@link https://www.ukri.org UKRI}
|
||||
* {@link https://www.dsbd.tech Digital Security by Design} program.
|
||||
* @author Configured Things Ltd. <getconfigured@configuredthings.com>
|
||||
* @copyright Crown Copyright 2025
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
|
@ -24,8 +26,8 @@ class MQTTPublish extends Operation {
|
|||
this.module = "MQTT";
|
||||
this.description = "Publishes a message to an MQTT broker";
|
||||
this.infoURL = "https://en.wikipedia.org/wiki/MQTT";
|
||||
this.inputType = "String";
|
||||
this.outputType = "String";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "ArrayBuffer";
|
||||
this.args = [
|
||||
{
|
||||
name: "MQTT broker URL",
|
||||
|
@ -41,19 +43,19 @@ class MQTTPublish extends Operation {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {String} input
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {String}
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [broker, topic] = args;
|
||||
const mqttUrlRegex = /^(ws|mqtt)s?:\/\/(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]))*|([01]?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\.([01]?[0-9][0-9]?|2[0-4][0-9]|25[0-5])){3}|(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))(:([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?$/;
|
||||
const mqttUrlRegex = /^(ws|mqtt)s?:\/\/(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]))*|([01]?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\.([01]?[0-9][0-9]?|2[0-4][0-9]|25[0-5])){3}|(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))(:([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?/;
|
||||
const mqttTopicRegex = /^[\u0000-\uFFFF]+(\/[\u0000-\uFFFF]+)+$/;
|
||||
if (mqttUrlRegex.test(broker)) {
|
||||
if (mqttTopicRegex.test(broker)) {
|
||||
const client = mqtt.connect(broker);
|
||||
client.on("connect", () => {
|
||||
client.publish(topic, input);
|
||||
client.publish(topic, Buffer.from(input));
|
||||
client.end();
|
||||
});
|
||||
} else throw new OperationError(`Invalid MQTT topic name - ${topic}`);
|
||||
|
|
54
src/core/operations/SignedObjectToArrayBuffer.mjs
Normal file
54
src/core/operations/SignedObjectToArrayBuffer.mjs
Normal file
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* @file Developed by {@link https://configuredthings.com Configured Things} with funding from the {@link https://www.ukri.org UKRI}
|
||||
* {@link https://www.dsbd.tech Digital Security by Design} program.
|
||||
* @author Configured Things Ltd. <getconfigured@configuredthings.com>
|
||||
* @copyright Crown Copyright 2025
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
|
||||
/**
|
||||
* Signed Object to ArrayBuffer operation
|
||||
*/
|
||||
class SignedObjectToArrayBuffer extends Operation {
|
||||
|
||||
/**
|
||||
* SignedJSONToArrayBuffer constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Signed Object to ArrayBuffer";
|
||||
this.module = "Default";
|
||||
this.description = "Converts a digitally signed object created by, for example, the 'LibHydrogen Curve25519 Sign' operation to an ArrayBuffer";
|
||||
this.infoURL = ""; // Usually a Wikipedia link. Remember to remove localisation (i.e. https://wikipedia.org/etc rather than https://en.wikipedia.org/etc)
|
||||
this.inputType = "JSON";
|
||||
this.outputType = "ArrayBuffer";
|
||||
this.args = [
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {JSON} input
|
||||
* @param {Object[]} args
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
run(input, args) {
|
||||
const properties = ["context", "signature", "input"];
|
||||
const output = properties.reduce((previousBytes, prop) => {
|
||||
if (!Object.hasOwn(input, prop)) {
|
||||
throw new OperationError(`Input missing '${prop}' property`);
|
||||
} else {
|
||||
const combinedBytes = new Uint8Array(previousBytes.byteLength + input[prop].byteLength);
|
||||
combinedBytes.set(previousBytes);
|
||||
combinedBytes.set(input[prop], previousBytes.byteLength);
|
||||
return combinedBytes;
|
||||
}
|
||||
}, new Uint8Array());
|
||||
return output.buffer;
|
||||
}
|
||||
}
|
||||
|
||||
export default SignedObjectToArrayBuffer;
|
|
@ -82,7 +82,11 @@ module.exports = {
|
|||
context: "node_modules/node-forge/dist",
|
||||
from: "prime.worker.min.js",
|
||||
to: "assets/forge/"
|
||||
}
|
||||
}, {
|
||||
context: "node_modules/@configuredthings/libhydrogen-wasm/",
|
||||
from: "libhydrogen.wasm",
|
||||
to: "assets/libhydrogen-wasm"
|
||||
},
|
||||
]
|
||||
}),
|
||||
new ModifySourcePlugin({
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue